2022-08-12 22:17:42 -07:00
|
|
|
-----------
|
|
|
|
-- Lasso --
|
|
|
|
-----------
|
|
|
|
|
|
|
|
local abs = math.abs
|
|
|
|
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
})
|
|
|
|
|
|
|
|
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
|
2022-02-10 18:00:06 -08:00
|
|
|
})
|