chair_lift-cd2025/chair_lift_entity.lua
2022-02-13 21:52:53 +01:00

267 lines
9.4 KiB
Lua

local S = chair_lift.translator
local player_set_animation = nil
if minetest.get_modpath("player_api") then
player_set_animation = player_api.set_animation
elseif minetes.get_modpath("hades_player") then
player_set_animation = hades_player.player_set_animation
end
local chair_pos_offset = vector.new(-3/16, -2.5+3/16, 0)
local function get_rotation(param2)
local dir = minetest.facedir_to_dir(param2)
local rot = vector.dir_to_rotation(dir)
if param2>=20 then
rot.z = math.pi
end
return rot
end
local chair_entity = {
initial_properties = {
physical = true,
collisionbox = {-0.5,-0.5,-0.5,0.5,0.8,0,5},
selectionbox = {-0.5,-0.5,-0.5,0.5,1.4,0,5},
visual = "mesh",
mesh = "chair_lift_seat.obj",
visual_size = {x=1,y=1,z=1},
textures = {"chair_lift_seet.png"},
},
driver = nil,
prev_pos = nil,
}
function chair_entity:on_activate(staticdata, dtime_s)
self.object:set_armor_groups({immortal=1})
if staticdata and staticdata~="" then
staticdata = minetest.deserialize(staticdata)
self.powered_wheel = staticdata.powered_wheel
self.forward = staticdata.forward
self.prev_pos = staticdata.prev_pos
else
local pos = self.object:get_pos()
self.prev_pos = vector.new(pos)
pos = vector.subtract(pos, chair_pos_offset)
print("check powered_wheel: "..minetest.pos_to_string(pos))
self.powered_wheel, self.forward = chair_lift.find_powered_wheel(pos, nil)
print("powered_wheel: "..dump(self.powered_wheel))
end
self.prev_pos = self.object:get_pos()
end
function chair_entity:get_staticdata()
local staticdata = {
powered_wheel = self.powered_wheel,
}
return minetest.serialize(staticdata)
end
function chair_entity:on_rightclick(clicker)
local player_name = clicker:get_player_name()
if self.driver==nil then
-- attach
clicker:set_attach(self.object, "", {x=0,y=0,z=0},{x=0,y=0,z=0})
minetest.after(0.1, function() player_set_animation(clicker, "set", 30) end)
self.driver = player_name
else
if self.driver==player_name then
-- detach
clicker:set_detach()
self.driver = nil
minetest.after(0.1, function() player_set_animation(clicker, "stand") end)
else
end
end
end
function chair_entity:on_punch(puncher)
if self.driver==nil then
local inv = puncher:get_inventory()
inv:add_item("main", ItemStack("chair_lift:seet"))
self.object:remove()
end
end
function chair_entity:cause_fall(pos)
-- update pos, cause fall
--print("Cause fall pos:"..minetest.pos_to_string(pos))
self.object:move_to(pos)
self.object:set_velocity(vector.new(0,0,0))
self.object:set_acceleration(vector.new(0,-9.81,0))
if self.driver then
local player = minetest.get_player_by_name(self.driver)
if player then
player:set_detach()
minetest.after(0.1, function() player_set_animation(player, "stand") end)
end
self.driver = nil
end
self.fall = true
return
end
function chair_entity:on_step(dtime)
if self.fall then
return
end
--
local pos = self.object:get_pos()
local rpos = vector.subtract(pos, chair_pos_offset)
--print("start_pos: "..minetest.pos_to_string(pos))
local act_speed = vector.length(self.object:get_velocity())
local track = vector.distance(self.prev_pos, pos)
if track>0 then
-- one by one, to eliminate posibly problems with position on lagy servers
local act_pos = vector.subtract(self.prev_pos, chair_pos_offset)
local act_npos = vector.round(act_pos)
local act_node = minetest.get_node(act_npos)
local act_def = minetest.registered_nodes[act_node.name]
if not act_def or not act_def._steel_rope then
--print("Fall, missing steel rope at; "..minetest.pos_to_string(act_pos))
act_pos = vector.add(act_pos, chair_pos_offset)
self:cause_fall(act_pos)
return
end
local act_offset
if self.forward then
act_offset = act_def._steel_rope.forward_offset
else
act_offset = act_def._steel_rope.backward_offset
end
-- reduce track
local act_dir = minetest.facedir_to_dir(act_node.param2%32)
local act_rot = get_rotation(act_node.param2%32)
--print("dir: "..minetest.pos_to_string(act_dir).." param2: "..act_node.param2.." rot: "..minetest.pos_to_string(vector.dir_to_rotation(act_dir)).." rot2: "..minetest.pos_to_string(get_rotation(act_node.param2%32)))
--print("offset: "..minetest.pos_to_string(act_offset).." from "..act_node.name.." forward "..dump(self.forward))
act_offset = vector.rotate(act_offset, act_rot)
--print("offset: "..minetest.pos_to_string(act_offset))
local act_opos = vector.add(act_npos, act_offset)
--print("act_pos: "..minetest.pos_to_string(act_pos))
--print("act_opos: "..minetest.pos_to_string(act_opos))
--print("track: "..track)
local next_track = vector.distance(act_pos, act_opos)
track = track - next_track
--print("track: "..track)
while track>0 do
act_pos = act_opos
local old_npos = act_npos
local old_node = act_node
local old_def = act_def
if self.forward then
act_npos = appliances.get_sides_pos(old_npos, old_node, old_def._steel_rope.forward)
else
act_npos = appliances.get_sides_pos(old_npos, old_node, old_def._steel_rope.backward)
end
act_node = minetest.get_node(act_npos)
act_def = minetest.registered_nodes[act_node.name]
if not act_def or not act_def._steel_rope then
-- update pos, cause fall
--print("Fall, missing steel rope while at; "..minetest.pos_to_string(act_pos))
act_pos = vector.add(act_pos, chair_pos_offset)
self:cause_fall(act_pos)
return
end
local test_pos = appliances.get_sides_pos(act_npos, act_node, act_def._steel_rope.forward)
local forward = not vector.equals(old_npos, test_pos)
--print("old_npos: "..minetest.pos_to_string(old_npos).." test_pos"..minetest.pos_to_string(test_pos))
if forward then
act_offset = act_def._steel_rope.forward_offset
else
act_offset = act_def._steel_rope.backward_offset
end
act_dir = minetest.facedir_to_dir(act_node.param2%32)
act_rot = get_rotation(act_node.param2%32)
--print("dir: "..minetest.pos_to_string(act_dir).." param2: "..act_node.param2.." rot: "..minetest.pos_to_string(vector.dir_to_rotation(act_dir)))
--print("offset: "..minetest.pos_to_string(act_offset).." from "..act_node.name)
act_offset = vector.rotate(act_offset, act_rot)
--print("offset: "..minetest.pos_to_string(act_offset))
act_opos = vector.add(act_npos, act_offset)
--print("old_npos: "..minetest.pos_to_string(old_npos).." act_npos"..minetest.pos_to_string(act_npos))
--print("old_forward: "..dump(self.forward).." act_forward: "..dump(forward))
--print("act_pos: "..minetest.pos_to_string(act_pos))
--print("act_opos: "..minetest.pos_to_string(act_opos))
track = track - vector.distance(act_pos, act_opos)
--print("track: "..track)
self.forward = forward
end
local old_pos = act_pos
act_pos = act_opos
local diff_pos = vector.subtract(act_pos, old_pos)
if track<0 then
--print("new_pos: "..minetest.pos_to_string(act_pos))
--print("old_pos: "..minetest.pos_to_string(old_pos))
--print("diff_pos: "..minetest.pos_to_string(diff_pos).." len: "..vector.length(diff_pos))
act_pos = vector.add(act_pos, vector.multiply(diff_pos, track/vector.length(diff_pos)))
--print("new_pos: "..minetest.pos_to_string(act_pos).." dis: "..vector.distance(old_pos, act_pos))
end
act_pos = vector.add(act_pos, chair_pos_offset)
--print("new_pos: "..minetest.pos_to_string(act_pos))
self.object:move_to(act_pos)
self.prev_pos = act_pos
self.object:set_velocity(vector.multiply(vector.normalize(diff_pos), act_speed))
-- rotation should be corrected, depend on velocity direction
end
-- check powered wheel
if self.powered_wheel then
local node = minetest.get_node(self.powered_wheel)
--print(dump(node))
if minetest.get_item_group(node.name, "lift_powered_wheel")>0 then
local meta = minetest.get_meta(self.powered_wheel)
local lift_speed = meta:get_float("lift_speed")
if (lift_speed==0) and act_speed>0 then
-- stop and update self forward
self.object:set_velocity(vector.new(0,0,0))
elseif (lift_speed>0) then
-- speed
local dir = vector.rotate(vector.new(0,0,1), self.object:get_rotation())
self.object:set_velocity(vector.multiply(dir, lift_speed))
--print("new speed: "..lift_speed)
end
else
self.object:set_velocity(vector.new(0,0,0))
end
else
self.object:set_velocity(vector.new(0,0,0))
end
end
minetest.register_entity("chair_lift:seet", chair_entity)
minetest.register_craftitem("chair_lift:seet", {
description = S("Chair Lift Seet"),
inventory_image = "chair_lift_seet_inv.png",
on_place = function (itemstack, placer, pointed_thing)
if pointed_thing.type~="node" then
return itemstack
end
local pos = pointed_thing.under
local node = minetest.get_node(pos)
if minetest.get_item_group(node.name, "lift_steel_rope")<1 then
return itemstack
end
pos = vector.add(pos, chair_pos_offset)
--print("Chair to pos: "..minetest.pos_to_string(pos))
minetest.add_entity(pos, "chair_lift:seet")
itemstack:take_item()
return itemstack
end,
})