-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchair_lift_entity.lua
285 lines (255 loc) · 10 KB
/
chair_lift_entity.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
local S = chair_lift.translator
local player_mod = chair_lift.adaptation.player_mod
if (not adaptation_lib.check_keys_aviable("[chair_lift] chair lift entity:", chair_lift.adaptation, {"player_mod"})) then
return
end
local chair_pos_offset = vector.new(0, -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_wheel_steel.png",
"chair_lift_dark_steel.png",
"chair_lift_pole_steel.png",
"power_generators_shaft_steel.png",
"default_glass.png",
},
use_texture_alpha = true,
},
driver = nil,
prev_pos = nil,
}
--function chair_entity:on_activate(staticdata, dtime_s)
function chair_entity:on_activate(staticdata)
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,
forward = self.forward,
}
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})
player_mod.attach_player(player_name, true)
minetest.after(0.2, function()
local player = minetest.get_player_by_name(player_name)
if player then
player_mod.set_animation(player, "sit")
end
end)
self.driver = player_name
else
if self.driver==player_name then
-- detach
clicker:set_detach()
self.driver = nil
player_mod.deattach_player(player_name, nil)
player_mod.set_animation(clicker, "stand")
end
end
end
function chair_entity:on_punch(puncher)
if self.driver==nil then
local inv = puncher:get_inventory()
local noadd = inv:add_item("main", ItemStack("chair_lift:seat"))
if noadd:get_count()>0 then
minetest.add_item(puncher:get_pos(), noadd)
end
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_mod.set_animation(player, "stand") end)
end
self.driver = nil
end
self.fall = true
return
end
--function chair_entity:on_step(dtime)
function chair_entity:on_step(_)
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
self.object:set_rotation(vector.new(0,minetest.dir_to_yaw(diff_pos),0))
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:seat", chair_entity)
minetest.register_craftitem("chair_lift:seat", {
description = S("Chair Lift Seat"),
inventory_image = "chair_lift_seat_inv.png",
--on_place = function (itemstack, placer, pointed_thing)
on_place = function (itemstack, _, 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:seat")
itemstack:take_item()
return itemstack
end,
})