Harvest Update

This commit is contained in:
ElCeejo 2022-10-17 17:23:26 -07:00
parent d1453b9501
commit 4642fb63fd
56 changed files with 1689 additions and 972 deletions

View file

@ -3,359 +3,253 @@
-----------
local abs = math.abs
local asin = math.asin
local atan2 = math.atan2
local cos = math.cos
local deg = math.deg
local sin = math.sin
function animalia.initialize_lasso(self)
self.lasso_origin = self:recall("lasso_origin") or nil
if self.lasso_origin then
self.caught_with_lasso = true
if type(self.lasso_origin) == "table"
and minetest.get_item_group(minetest.get_node(self.lasso_origin).name, "fence") > 0 then
local object = minetest.add_entity(self.lasso_origin, "animalia:lasso_fence_ent")
object:get_luaentity().parent = self.object
elseif type(self.lasso_origin) == "string"
and minetest.get_player_by_name(self.lasso_origin) then
self.lasso_origin = minetest.get_player_by_name(self.lasso_origin)
else
self:forget("lasso_origin")
end
end
local function diff(a, b) -- Get difference between 2 angles
return atan2(sin(b - a), cos(b - a))
end
function animalia.set_lasso_visual(self, target)
if not creatura.is_alive(self)
or (self.lasso_visual
and self.lasso_visual:get_luaentity()) then return end
local pos = self.object:get_pos()
local object = minetest.add_entity(pos, "animalia:lasso_visual")
local ent = object:get_luaentity()
self.lasso_visual = object
self.lasso_origin = target
ent.parent = self.object
ent.lasso_origin = target
return object
local vec_add, vec_dir, vec_dist, vec_len = vector.add, vector.direction, vector.distance, vector.length
local dir2yaw, dir2rot = minetest.dir_to_yaw, vector.dir_to_rotation
-- Entities --
local using_lasso = {}
minetest.register_entity("animalia:lasso_entity", {
visual = "mesh",
mesh = "animalia_lasso_entity.b3d",
textures = {"animalia_lasso_entity.png"},
pointable = false,
on_activate = function(self)
self.object:set_armor_groups({immortal = 1})
end,
_scale = 1,
on_step = function(self, dtime)
local pos, parent = self.object:get_pos(), (self.object:get_attach() or self._attached)
local pointed_ent = self._point_to and self._point_to:get_luaentity()
local point_to = self._point_to and self._point_to:get_pos()
if not pos or not parent or not point_to then self.object:remove() return end
if type(parent) == "string" then
parent = minetest.get_player_by_name(parent)
local tgt_pos = parent:get_pos()
local dist = vec_dist(pos, tgt_pos)
if dist > 0.5 then
self.object:set_pos(tgt_pos)
else
self.object:move_to(tgt_pos)
end
self.object:set_rotation(dir2rot(vec_dir(tgt_pos, point_to)))
elseif parent.x then
point_to.y = point_to.y + pointed_ent.height * 0.5
self.object:set_rotation(dir2rot(vec_dir(pos, point_to)))
else
self.object:remove()
return
end
local size = vec_dist(pos, point_to)
if abs(size - self._scale) > 0.1 then
self.object:set_properties({
visual_size = {x = 1, y = 1, z = size}
})
self._scale = size
end
end
})
local function remove_from_fence(self)
local pos = self.object:get_pos()
local mob = self._mob and self._mob:get_luaentity()
if not mob then
self.object:remove()
return
end
mob._lassod_to = nil
mob:forget("_lassod_to")
mob._lasso_ent:remove()
local dirs = {
{x = 0.5, y = 0, z = 0},
{x = -0.5, y = 0, z = 0},
{x = 0, y = 0.5, z = 0},
{x = 0, y = -0.5, z = 0},
{x = 0, y = 0, z = 0.5},
{x = 0, y = 0, z = -0.5}
}
for i = 1, 6 do
local i_pos = vec_add(pos, dirs[i])
if not creatura.get_node_def(i_pos).walkable then
minetest.add_item(i_pos, "animalia:lasso")
break
end
end
self.object:remove()
end
minetest.register_entity("animalia:tied_lasso_entity", {
collisionbox = {-0.25,-0.25,-0.25, 0.25,0.25,0.25},
visual = "cube",
visual_size = {x = 0.3, y = 0.3},
mesh = "model",
textures = {
"animalia_tied_lasso_entity.png",
"animalia_tied_lasso_entity.png",
"animalia_tied_lasso_entity.png",
"animalia_tied_lasso_entity.png",
"animalia_tied_lasso_entity.png",
"animalia_tied_lasso_entity.png",
},
on_activate = function(self)
self.object:set_armor_groups({immortal = 1})
end,
on_step = function(self)
local mob = self._mob and self._mob:get_luaentity()
if not mob then remove_from_fence(self) return end
end,
on_rightclick = remove_from_fence,
on_punch = remove_from_fence
})
-- API --
local function add_lasso(self, origin)
local pos = self.object:get_pos()
if not pos then return end
local object = minetest.add_entity(pos, "animalia:lasso_entity")
local ent = object and object:get_luaentity()
if not ent then return end
-- Attachment point of entity
ent._attached = origin
if type(origin) == "string" then
local player = minetest.get_player_by_name(origin)
--object:set_attach(player)
else
object:set_pos(origin)
end
self._lassod_to = origin
ent._point_to = self.object
self:memorize("_lassod_to", origin)
return object
end
local function get_rope_velocity(pos1, pos2, dist)
local force = dist / 10
local vel = vector.new((pos2.x - pos1.x) * force, ((pos2.y - pos1.y) / (24 + dist)), (pos2.z - pos1.z) * force)
return vel
end
function animalia.initialize_lasso(self)
self._lassod_to = self:recall("_lassod_to") or self:recall("lasso_origin")
if self._lassod_to then
local origin = self._lassod_to
if type(origin) == "table"
and minetest.get_item_group(minetest.get_node(origin).name, "fence") > 0 then
local object = minetest.add_entity(origin, "animalia:tied_lasso_entity")
object:get_luaentity()._mob = self.object
self._lasso_ent = add_lasso(self, origin)
elseif type(origin) == "string" then
self._lassod_to = origin
self._lasso_ent = add_lasso(self, origin)
else
self:forget("_lassod_to")
end
end
end
function animalia.update_lasso_effects(self)
if not creatura.is_alive(self) then return end
if self.caught_with_lasso
and self.lasso_origin then
local pos = self.object:get_pos()
pos.y = pos.y + (self:get_height() * 0.5)
animalia.set_lasso_visual(self, self.lasso_origin)
if type(self.lasso_origin) == "userdata"
or type(self.lasso_origin) == "string" then
if type(self.lasso_origin) == "string" then
self.lasso_origin = minetest.get_player_by_name(self.lasso_origin)
if not self.lasso_origin then
self.caught_with_lasso = nil
self.lasso_origin = nil
self:forget("lasso_origin")
if self.lasso_visual then
self.lasso_visual:remove()
self.lasso_visual = nil
end
return
end
end
self:memorize("lasso_origin", self.lasso_origin:get_player_name())
-- Get distance to lasso player
local player = self.lasso_origin
local lasso_origin = player:get_pos()
lasso_origin.y = lasso_origin.y + 1
local dist = vector.distance(pos, lasso_origin)
if player:get_wielded_item():get_name() ~= "animalia:lasso"
or vector.distance(pos, lasso_origin) > 16 then
self.caught_with_lasso = nil
self.lasso_origin = nil
self:forget("lasso_origin")
if self.lasso_visual then
self.lasso_visual:remove()
self.lasso_visual = nil
end
end
-- Apply physics
if dist > 6
or abs(lasso_origin.y - pos.y) > 8 then
local p_target = vector.add(pos, vector.multiply(vector.direction(pos, lasso_origin), dist * 0.8))
local g = -0.18
local v = vector.new(0, 0, 0)
v.x = (1.0 + (0.005 * dist)) * (p_target.x - pos.x) / dist
v.y = -((1.0 + (0.03 * dist)) * ((lasso_origin.y - 4) - pos.y) / (dist * (g * dist)))
v.z = (1.0 + (0.005 * dist)) * (p_target.z - pos.z) / dist
self.object:add_velocity(v)
end
elseif type(self.lasso_origin) == "table" then
self:memorize("lasso_origin", self.lasso_origin)
local lasso_origin = self.lasso_origin
local dist = vector.distance(pos, lasso_origin)
if dist > 6
or abs(lasso_origin.y - pos.y) > 8 then
local p_target = vector.add(pos, vector.multiply(vector.direction(pos, lasso_origin), dist * 0.8))
local g = -0.18
local v = vector.new(0, 0, 0)
v.x = (1.0 + (0.005 * dist)) * (p_target.x - pos.x) / dist
v.y = -((1.0 + (0.03 * dist)) * ((lasso_origin.y - 4) - pos.y) / (dist * (g * dist)))
v.z = (1.0 + (0.005 * dist)) * (p_target.z - pos.z) / dist
self.object:add_velocity(v)
end
local objects = minetest.get_objects_inside_radius(lasso_origin, 1)
local is_lasso_attached = false
for _, object in ipairs(objects) do
if object
and object:get_luaentity()
and object:get_luaentity().name == "animalia:lasso_fence_ent" then
is_lasso_attached = true
end
end
if not is_lasso_attached then
self.caught_with_lasso = nil
self.lasso_origin = nil
self:forget("lasso_origin")
if self.lasso_visual then
self.lasso_visual:remove()
self.lasso_visual = nil
end
end
else
local objects = minetest.get_objects_inside_radius(self.lasso_origin, 0.4)
for _, object in ipairs(objects) do
if object
and object:get_luaentity()
and object:get_luaentity().name == "animalia:lasso_fence_ent" then
minetest.add_item(object:get_pos(), "animalia:lasso")
object:remove()
end
end
self.caught_with_lasso = nil
self.lasso_origin = nil
self:forget("lasso_origin")
if self.lasso_visual then
self.lasso_visual:remove()
self.lasso_visual = nil
end
end
end
local pos = self.object:get_pos()
if not creatura.is_alive(self) then return end
if self._lassod_to then
local lasso = self._lassod_to
self._lasso_ent = self._lasso_ent or add_lasso(self, lasso)
if type(lasso) == "string" then
using_lasso[lasso] = self
local name = lasso
lasso = minetest.get_player_by_name(lasso)
if lasso:get_wielded_item():get_name() ~= "animalia:lasso" then
using_lasso[name] = nil
self._lasso_ent:remove()
self._lasso_ent = nil
self._lassod_to = nil
self:forget("_lassod_to")
return
end
local lasso_pos = lasso:get_pos()
local dist = vec_dist(pos, lasso_pos)
local vel = self.object:get_velocity()
if not vel or dist < 8 and self.touching_ground then return end
if vec_len(vel) < 8 then
self.object:add_velocity(get_rope_velocity(pos, lasso_pos, dist))
end
return
elseif type(lasso) == "table" then
local dist = vec_dist(pos, lasso)
local vel = self.object:get_velocity()
if not vel or dist < 8 and self.touching_ground then return end
if vec_len(vel) < 8 then
self.object:add_velocity(get_rope_velocity(pos, lasso, dist))
end
return
end
end
if self._lasso_ent then
self._lasso_ent:remove()
self._lasso_ent = nil
self._lassod_to = nil
self:forget("_lassod_to")
end
end
local function is_lasso_in_use(player)
for _, ent in pairs(minetest.luaentities) do
if ent.name
and ent.name:match("^animalia:") then
if ent.lasso_origin
and type(ent.lasso_origin) == "userdata"
and ent.lasso_origin == player then
return true
end
end
end
return false
end
local function update_lasso_rotation(self)
if not self.parent
or not self.lasso_origin then self.object:remove() return end
local lasso_origin = self.lasso_origin
if type(lasso_origin) == "userdata" then
lasso_origin = lasso_origin:get_pos()
lasso_origin.y = lasso_origin.y + 1
end
local object = self.parent
if not object then return end
local pos = object:get_pos()
pos.y = pos.y + object:get_luaentity():get_height()
local rot = vector.dir_to_rotation(vector.direction(lasso_origin, pos))
self.object:set_pos(lasso_origin)
self.object:set_rotation(rot)
self.object:set_properties({
visual_size = {x = 6, z = 10 * vector.distance(pos, lasso_origin), y = 6}
})
end
minetest.register_entity("animalia:lasso_visual", {
hp_max = 1,
physical = false,
collisionbox = {0, 0, 0, 0, 0, 0},
visual = "mesh",
mesh = "animalia_lasso.b3d",
visual_size = {x = 2, y = 2},
textures = {"animalia_lasso_cube.png"},
is_visible = true,
makes_footstep_sound = false,
glow = 1,
on_step = function(self)
self.object:set_armor_groups({immortal = 1})
if not self.parent
or not self.lasso_origin
or (self.parent
and (not creatura.is_alive(self.parent)
or not self.parent:get_luaentity().caught_with_lasso)) then
self.object:remove()
return
end
update_lasso_rotation(self)
end
})
minetest.register_entity("animalia:frog_tongue_visual", {
hp_max = 1,
physical = false,
collisionbox = {0, 0, 0, 0, 0, 0},
visual = "mesh",
mesh = "animalia_lasso.b3d",
visual_size = {x = 2, y = 2},
textures = {"animalia_frog_tongue.png"},
is_visible = true,
makes_footstep_sound = false,
on_step = function(self)
self.object:set_armor_groups({immortal = 1})
if not self.parent
or not self.lasso_origin
or (self.parent
and (not creatura.is_alive(self.parent)
or not self.parent:get_luaentity().caught_with_lasso)) then
self.object:remove()
return
end
update_lasso_rotation(self)
end
})
minetest.register_entity("animalia:lasso_fence_ent", {
physical = false,
collisionbox = {-0.25,-0.25,-0.25, 0.25,0.25,0.25},
visual = "cube",
visual_size = {x = 0.3, y = 0.3},
mesh = "model",
textures = {
"animalia_lasso_cube.png",
"animalia_lasso_cube.png",
"animalia_lasso_cube.png",
"animalia_lasso_cube.png",
"animalia_lasso_cube.png",
"animalia_lasso_cube.png",
},
makes_footstep_sound = false,
on_step = function(self)
if not self.parent
or not self.parent:get_luaentity()
or not self.parent:get_luaentity().lasso_origin then
self.object:remove()
return
end
local pos = self.object:get_pos()
local node = minetest.get_node(pos)
if not minetest.registered_nodes[node.name].walkable
or minetest.get_item_group(node.name, "fence") < 1 then
local ent = self.parent:get_luaentity()
ent.lasso_origin = ent:memorize("lasso_origin", nil)
ent.caught_with_lasso = nil
if ent.lasso_visual then
ent.lasso_visual:remove()
ent.lasso_visual = nil
end
minetest.add_item(self.object:get_pos(), "animalia:lasso")
self.object:remove()
return
end
end,
on_rightclick = function(self)
if self.parent then
local ent = self.parent:get_luaentity()
ent.lasso_origin = ent:memorize("lasso_origin", nil)
ent.caught_with_lasso = nil
if ent.lasso_visual then
ent.lasso_visual:remove()
ent.lasso_visual = nil
end
end
local dirs = {
vector.new(1, 0, 0),
vector.new(-1, 0, 0),
vector.new(0, 1, 0),
vector.new(0, -1, 0),
vector.new(0, 0, 1),
vector.new(0, 0, -1),
}
for i = 1, 6 do
local pos = vector.add(self.object:get_pos(), dirs[i])
local name = minetest.get_node(pos).name
if not minetest.registered_nodes[name].walkable then
minetest.add_item(pos, "animalia:lasso")
break
end
end
self.object:remove()
end,
on_punch = function(self)
if self.parent then
local ent = self.parent:get_luaentity()
ent.lasso_origin = ent:memorize("lasso_origin", nil)
ent.caught_with_lasso = nil
if ent.lasso_visual then
ent.lasso_visual:remove()
ent.lasso_visual = nil
end
end
local dirs = {
vector.new(1, 0, 0),
vector.new(-1, 0, 0),
vector.new(0, 1, 0),
vector.new(0, -1, 0),
vector.new(0, 0, 1),
vector.new(0, 0, -1),
}
for i = 1, 6 do
local pos = vector.add(self.object:get_pos(), dirs[i])
local name = minetest.get_node(pos).name
if not minetest.registered_nodes[name].walkable then
minetest.add_item(pos, "animalia:lasso")
break
end
end
self.object:remove()
end
})
-- Item
minetest.register_craftitem("animalia:lasso", {
description = "Lasso",
inventory_image = "animalia_lasso.png",
on_secondary_use = function(_, placer, pointed_thing)
if pointed_thing.type == "object" then
if pointed_thing.ref:is_player() then return end
local ent = pointed_thing.ref:get_luaentity()
if not ent.catch_with_lasso then return end
if not ent.caught_with_lasso
and not is_lasso_in_use(placer) then
ent.caught_with_lasso = true
ent.lasso_origin = placer
elseif ent.lasso_origin
and ent.lasso_origin == placer then
ent.caught_with_lasso = nil
ent.lasso_origin = nil
end
end
end,
on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type == "node" then
local pos = minetest.get_pointed_thing_position(pointed_thing)
if minetest.get_item_group(minetest.get_node(pos).name, "fence") > 0 then
local objects = minetest.get_objects_inside_radius(placer:get_pos(), 21)
for _, obj in ipairs(objects) do
if obj:get_luaentity()
and obj:get_luaentity().lasso_origin
and obj:get_luaentity().lasso_visual
and type(obj:get_luaentity().lasso_origin) == "userdata"
and obj:get_luaentity().lasso_origin == placer then
obj:get_luaentity().lasso_visual:get_luaentity().lasso_origin = pos
obj:get_luaentity().lasso_origin = pos
local object = minetest.add_entity(pos, "animalia:lasso_fence_ent")
object:get_luaentity().parent = obj
itemstack:take_item(1)
break
end
end
end
end
return itemstack
end
})
description = "Lasso",
inventory_image = "animalia_lasso.png",
on_secondary_use = function(_, placer, pointed)
local ent = pointed.ref and pointed.ref:get_luaentity()
if ent
and (ent.name:match("^animalia:")
or ent.name:match("^monstrum:")) then
if not ent.catch_with_lasso then return end
local name = placer:get_player_name()
if not ent._lassod_to
and not using_lasso[name] then
using_lasso[name] = ent
ent._lassod_to = name
ent:memorize("_lassod_to", name)
elseif ent._lassod_to
and ent._lassod_to == name then
using_lasso[name] = nil
ent._lassod_to = nil
ent:forget("_lassod_to")
end
end
end,
on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type == "node" then
local pos = minetest.get_pointed_thing_position(pointed_thing)
if minetest.get_item_group(minetest.get_node(pos).name, "fence") > 0 then
local name = placer:get_player_name()
local ent = using_lasso[name]
if ent
and ent._lassod_to
and ent._lassod_to == name then
using_lasso[name] = nil
ent._lasso_ent:set_detach()
ent._lasso_ent:set_pos(pos)
ent._lasso_ent:get_luaentity()._attached = pos
ent._lassod_to = pos
ent:memorize("_lassod_to", pos)
local fence_obj = minetest.add_entity(pos, "animalia:tied_lasso_entity")
fence_obj:get_luaentity()._mob = ent.object
fence_obj:get_luaentity()._lasso_obj = ent._lasso_ent
itemstack:take_item(1)
end
end
end
return itemstack
end
})