Fixed moving items
[walkway.git] / init.lua
1 walkway = {}
2
3
4 -- taken from moreblocks
5 local box_slope_half = {
6 type = "fixed",
7 fixed = {
8 {-0.5, -0.5, -0.5, 0.5, -0.375, 0.5},
9 {-0.5, -0.375, -0.25, 0.5, -0.25, 0.5},
10 {-0.5, -0.25, 0, 0.5, -0.125, 0.5},
11 {-0.5, -0.125, 0.25, 0.5, 0, 0.5},
12 }
13 }
14
15 local box_slope_half_raised = {
16 type = "fixed",
17 fixed = {
18 {-0.5, -0.5, -0.5, 0.5, 0.125, 0.5},
19 {-0.5, 0.125, -0.25, 0.5, 0.25, 0.5},
20 {-0.5, 0.25, 0, 0.5, 0.375, 0.5},
21 {-0.5, 0.375, 0.25, 0.5, 0.5, 0.5},
22 }
23 }
24 local function same_sign(x, y)
25 return (x > 0 and y > 0) or (x < 0 and y < 0)
26 end
27 local function diff_sign(x, y)
28 return (x > 0 and y < 0) or (x < 0 and y > 0)
29 end
30 local function abs(x)
31 if x > 0 then
32 return x
33 else
34 return -x
35 end
36 end
37 local speed = 0.4
38 local function generate_velocity_vector(dir, vx, vz, node)
39 local vy=0
40 local p = 1
41 -- local dir = vector.new(minetest.facedir_to_dir(node.param2))
42 if node.name=="walkway:slope_1" or node.name=="walkway:slope_2" then
43 p = 1
44 vx=0
45 vz=0
46 if same_sign(dir.x/speed+vx,dir.x) or same_sign(dir.z/speed+vz,dir.z) then
47 -- minetest.chat_send_all("CASE 1")
48 vy = 1
49 elseif diff_sign(dir.x/speed+vx,dir.x) or diff_sign(dir.z/speed+vz,dir.z) then
50 vy = -1
51 end
52 elseif node.name=="walkway:slope_1_down" or node.name=="walkway:slope_2_down" then
53 vx=0 -- dirty fix, could not get this to work properly.
54 vz=0
55 p = -1
56 if same_sign(dir.x/speed+vx,dir.x) or same_sign(dir.z/speed+vz,dir.z) then
57 vy = -1
58 elseif diff_sign(dir.x/speed+vx,dir.x) or diff_sign(dir.z/speed+vz,dir.z) then
59 vy = 1
60 end
61
62 end
63 -- minetest.chat_send_all(dir.x..";"..p*(dir.x / speed+vx)..",".. vy*(abs((dir.x +dir.z)/speed+vx+vz))/2 ..","..p*(dir.z / speed+vz)..";"..dir.z)
64 return {x = p*(dir.x / speed+vx), y = vy*(abs((dir.x +dir.z)/speed))/2, z = p*(dir.z / speed+vz)}
65 end
66
67
68 minetest.register_entity("walkway:moving_dummy",{
69 initial_properties = {
70 hp_max = 1,
71 physical = false,
72 collisionbox = {0.005, -0.005, 0.005, -0.005, 0.005, -0.025},
73 visual = "cube",
74 visual_size = {x = 1, y = 1},
75 textures = {"blank.png","blank.png", "blank.png","blank.png","blank.png","blank.png"},
76 spritediv = {x = 1, y = 1},
77 initial_sprite_basepos = {x = 0, y = 0},
78 is_visible = true;
79 },
80 player = nil,
81 on_step = function (self, dtime)
82 local name = ""
83 if self.player and self.player:is_player() then
84 name = self.player:get_player_name()
85 elseif not self.player then
86 self.object:remove()
87 return
88 end
89 local pos = self.object:getpos()
90 local napos = minetest.get_node(pos)
91 local dir = vector.new(minetest.facedir_to_dir(napos.param2)) -- a copy of the facedir so we don't overwrite the facedir table
92 local vx=0
93 local vz=0
94 if name ~="" then
95 -- based on code from the tower crane mod --
96 local ctrl = self.player:get_player_control()
97 local yaw = self.player:get_look_horizontal()
98 local pos = self.player:getpos()
99 local walk_speed = minetest.settings:get("movement_speed_walk") or 4
100 local speed_forward = 0
101 local speed_right= 0
102 self.object:setyaw(yaw)
103 if (ctrl.up or ctrl.down or ctrl.left or ctrl.right) then
104 default.player_set_animation(self.player, "walk" , 30)
105 else
106 default.player_set_animation(self.player, "stand" , 30)
107 end
108
109 if ctrl.up then -- forward
110 speed_forward = walk_speed
111 elseif ctrl.down then -- backward
112 speed_forward = -walk_speed
113 end
114
115 if ctrl.right then -- right
116 speed_right = walk_speed
117 elseif ctrl.left then -- left
118 speed_right = -walk_speed
119 end
120
121 if ctrl.jump then
122 -- detach on jump
123 local veldir = self.object:getvelocity();
124 self.player:set_detach()
125 self.player:setpos({x = pos.x + veldir.x / 3, y = pos.y+1, z = pos.z + veldir.z / 3})
126 self.object:remove()
127 default.player_attached[name] = false
128 return
129 end
130
131 -- calculate the direction vector
132 vx = math.cos(yaw+math.pi/2) * speed_forward + math.cos(yaw) * speed_right
133 vz = math.sin(yaw+math.pi/2) * speed_forward + math.sin(yaw) * speed_right
134 if dir.x == 0 then
135 vx = 0
136 elseif dir.z == 0 then
137 vz = 0
138 end
139 elseif not self.player:is_player() then
140 self.object:setyaw(self.player:getyaw())
141 end
142
143
144 -- if napos.name == "walkway:belt_straight" then
145 -- self.object:setvelocity({x = dir.x / speed, y = 0, z = dir.z / speed})
146 if napos.name == "air" then
147 napos = minetest.get_node({x = pos.x, y = pos.y -1, z = pos.z})
148 dir = vector.new(minetest.facedir_to_dir(napos.param2))
149 elseif not string.sub(napos.name,1,string.len("walkway:")) == "walkway:" then
150 napos = minetest.get_node({x = pos.x, y = pos.y + 1, z = pos.z})
151 dir = vector.new(minetest.facedir_to_dir(napos.param2))
152 end
153 -- minetest.chat_send_all(napos.name)
154
155 if string.sub(napos.name,1,string.len("walkway:")) == "walkway:" then
156 if dir.x == 0 then
157 dir.x = (math.floor(pos.x + 0.5) - pos.x) * 2
158 elseif dir.z == 0 then
159 dir.z = (math.floor(pos.z + 0.5) - pos.z) * 2
160 end
161 self.object:setvelocity(generate_velocity_vector(dir, vx, vz, napos))
162 else
163 if self.player then
164 local veldir = self.object:getvelocity();
165 self.player:set_detach()
166 self.player:setpos({x = pos.x + veldir.x / 3, y = pos.y, z = pos.z + veldir.z / 3})
167 self.object:remove()
168 else
169 self.object:remove()
170 end
171 if name ~="" then
172 default.player_attached[name] = false
173 end
174 end
175 end
176 })
177 nodedef = {
178 groups = {cracky=1},
179 paramtype = "light",
180 paramtype2 = "facedir",
181 is_ground_content = true,
182 legacy_facedir_simple = true,
183
184 }
185
186 minetest.register_node("walkway:belt", {
187 description = "Moving Walkway",
188 tiles = {{name="factory_belt_top_animation.png", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=0.2}}, "factory_belt_bottom.png", "factory_belt_side.png",
189 "factory_belt_side.png", "factory_belt_side.png", "factory_belt_side.png"},
190 groups = {cracky=1},
191 drawtype = "nodebox",
192 paramtype = "light",
193 paramtype2 = "facedir",
194 is_ground_content = true,
195 legacy_facedir_simple = true,
196 node_box = {
197 type = "fixed",
198 fixed = {{-0.5,-0.5,-0.5,0.5,0.0,0.5},}
199 },
200 })
201 minetest.register_node("walkway:slope_1",
202 {description = "Moving Walkway",
203 tiles = {{name="factory_belt_top_animation.png", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=0.2}}, "factory_belt_bottom.png", "factory_belt_side.png",
204 "factory_belt_side.png", "factory_belt_side.png", "factory_belt_side.png"},
205 groups = {cracky=1},
206
207 drawtype = "mesh",
208 paramtype = "light",
209 paramtype2 = "facedir",
210 on_place = minetest.rotate_node,
211 description = desc,
212 is_ground_content = true,
213 legacy_facedir_simple = true,
214 mesh = "moreblocks_slope_half.obj",
215 collision_box = box_slope_half,
216 selection_box = box_slope_half,
217 })
218 minetest.register_node("walkway:slope_2",
219 {description = "Moving Walkway",
220 tiles = {{name="factory_belt_top_animation.png", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=0.2}}, "factory_belt_bottom.png", "factory_belt_side.png",
221 "factory_belt_side.png", "factory_belt_side.png", "factory_belt_side.png"},
222 groups = {cracky=1},
223
224 drawtype = "mesh",
225 paramtype = "light",
226 paramtype2 = "facedir",
227 on_place = minetest.rotate_node,
228 description = desc,
229 is_ground_content = true,
230 legacy_facedir_simple = true,
231 mesh = "moreblocks_slope_half_raised.obj",
232 collision_box = box_slope_half_raised,
233 selection_box = box_slope_half_raised,
234 })
235 minetest.register_node("walkway:slope_1_down",
236 {description = "Moving Walkway",
237 tiles = {{name="factory_belt_top_animation_down.png", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=0.2}}, "factory_belt_bottom.png", "factory_belt_side.png",
238 "factory_belt_side.png", "factory_belt_side.png", "factory_belt_side.png"},
239 groups = {cracky=1},
240
241 drawtype = "mesh",
242 paramtype = "light",
243 paramtype2 = "facedir",
244 on_place = minetest.rotate_node,
245 description = desc,
246 is_ground_content = true,
247 legacy_facedir_simple = true,
248 mesh = "moreblocks_slope_half.obj",
249 collision_box = box_slope_half,
250 selection_box = box_slope_half,
251 })
252 minetest.register_node("walkway:slope_2_down",
253 {description = "Moving Walkway",
254 tiles = {{name="factory_belt_top_animation_down.png", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=0.2}}, "factory_belt_bottom.png", "factory_belt_side.png",
255 "factory_belt_side.png", "factory_belt_side.png", "factory_belt_side.png"},
256 groups = {cracky=1},
257
258 drawtype = "mesh",
259 paramtype = "light",
260 paramtype2 = "facedir",
261 on_place = minetest.rotate_node,
262 description = desc,
263 is_ground_content = true,
264 legacy_facedir_simple = true,
265 mesh = "moreblocks_slope_half_raised.obj",
266 collision_box = box_slope_half_raised,
267 selection_box = box_slope_half_raised,
268 })
269
270
271
272 -- minetest.register_node("walkway:belt_straight", {
273 -- description = "straight Conveyor Belt",
274 -- tiles = {{name="factory_belt_top_animation.png", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=0.4}}, "factory_belt_bottom.png", "factory_belt_side.png",
275 -- "factory_belt_side.png", "factory_belt_side.png", "factory_belt_side.png"},
276 -- groups = {cracky=1},
277 -- drawtype = "nodebox",
278 -- paramtype = "light",
279 -- paramtype2 = "facedir",
280 -- is_ground_content = true,
281 -- legacy_facedir_simple = true,
282 -- node_box = {
283 -- type = "fixed",
284 -- fixed = {{-0.5,-0.5,-0.5,0.5,0.0625,0.5},}
285 -- },
286 -- })
287
288 -- minetest.register_abm({
289 -- nodenames = {"walkway:belt", "walkway:belt_straight"},
290 -- neighbors = nil,
291 -- interval = 1,
292 -- chance = 1,
293 -- action = function(pos, node, active_object_count, active_object_count_wider)
294 -- local all_objects = minetest.get_objects_inside_radius(pos, 0.75)
295 -- local _,obj
296 -- for _,obj in ipairs(all_objects) do
297 -- if not obj:is_player() and obj:get_luaentity() and obj:get_luaentity().name == "__builtin:item" then
298 -- walkway.do_moving_item({x = pos.x, y = pos.y + 0.15, z = pos.z}, obj:get_luaentity().itemstring)
299 -- obj:get_luaentity().itemstring = ""
300 -- obj:remove()
301 -- end
302 -- end
303 -- end,
304 -- })
305
306 minetest.register_abm({
307 nodenames = {"walkway:belt", "walkway:belt_straight", "walkway:slope_1", "walkway:slope_2", "walkway:slope_1_down", "walkway:slope_2_down"},
308 neighbors = nil,
309 interval = 1,
310 chance = 1,
311 action = function(pos, node, active_object_count, active_object_count_wider)
312 local all_objects = minetest.get_objects_inside_radius(pos, 0.75)
313 local _,obj
314 for _,obj in ipairs(all_objects) do
315 if obj:is_player() and not obj:get_attach() then
316 -- dum = walkway.do_moving_dummy():get_luaentity()
317 local dum = minetest.add_entity({x = pos.x, y = pos.y + 0.15, z = pos.z}, "walkway:moving_dummy"):get_luaentity()
318 dum.player = obj
319 obj:set_attach(dum.object, "", {x=0,y=9,z=0}, {x=0,y=0,z=0})
320 local name = obj:get_player_name()
321 default.player_attached[name] = true
322 elseif obj:get_luaentity() and string.sub(obj:get_luaentity().name,1,string.len("mobs_animal")) == "mobs_animal" then
323 local dir = vector.new(minetest.facedir_to_dir(node.param2))
324 obj:setvelocity(generate_velocity_vector(dir,0, 0, node))
325 -- dum = walkway.do_moving_dummy({x = pos.x, y = pos.y + 0.15, z = pos.z}, obj):get_luaentity()
326 -- dum.player = obj
327 -- obj:set_attach(dum.object, "", {x=0,y=-1,z=0}, {x=0,y=0,z=0})
328 elseif obj:get_luaentity() and obj:get_luaentity().name == "__builtin:item" then
329 walkway.do_moving_item({x = pos.x, y = pos.y + 0.15, z = pos.z}, obj:get_luaentity().itemstring)
330 obj:get_luaentity().itemstring = ""
331 obj:remove()
332 end
333 end
334 end,
335 })
336
337 -- Based off of the pipeworks item code
338
339 function walkway.do_moving_item(pos, item)
340 if item==":" then
341 return
342 end
343 local stack = ItemStack(item)
344 local obj = minetest.add_entity(pos, "walkway:moving_item")
345 obj:get_luaentity():set_item(stack:to_string())
346 return obj
347 end
348
349
350 minetest.register_entity("walkway:moving_item", {
351 initial_properties = {
352 hp_max = 1,
353 physical = false,
354 collisionbox = {0.125, 0.125, 0.125, 0.125, 0.125, 0.125},
355 visual = "wielditem",
356 visual_size = {x = 0.5, y = 0.5},
357 textures = {""},
358 spritediv = {x = 1, y = 1},
359 initial_sprite_basepos = {x = 0, y = 0},
360 is_visible = false,
361 },
362
363 physical_state = true,
364 itemstring = '',
365 set_item = function(self, itemstring)
366 self.itemstring = itemstring
367 local stack = ItemStack(itemstring)
368 local count = stack:get_count()
369 local max_count = stack:get_stack_max()
370 if count > max_count then
371 count = max_count
372 self.itemstring = stack:get_name().." "..max_count
373 end
374 local s = 0.15 + 0.15 * (count / max_count)
375 local c = 0.8 * s
376 local itemtable = stack:to_table()
377 local itemname = nil
378 if itemtable then
379 itemname = stack:to_table().name
380 end
381 local item_texture = nil
382 local item_type = ""
383 if core.registered_items[itemname] then
384 item_texture = core.registered_items[itemname].inventory_image
385 item_type = core.registered_items[itemname].type
386 end
387 prop = {
388 is_visible = true,
389 visual = "wielditem",
390 textures = {itemname},
391 visual_size = {x = s, y = s},
392 collisionbox = {-c, -c, -c, c, c, c},
393 automatic_rotate = math.pi * 0.2,
394 }
395 self.object:set_properties(prop)
396 end,
397
398 get_staticdata = function(self)
399 return core.serialize({
400 itemstring = self.itemstring
401 })
402 end,
403
404 on_activate = function(self, staticdata, dtime_s)
405 if string.sub(staticdata, 1, string.len("return")) == "return" then
406 local data = core.deserialize(staticdata)
407 if data and type(data) == "table" then
408 self.itemstring = data.itemstring
409 end
410 else
411 self.itemstring = staticdata
412 end
413 self.object:set_armor_groups({immortal = 1})
414 self:set_item(self.itemstring)
415 end,
416
417 on_step = function(self, dtime)
418 local pos = self.object:getpos()
419 local napos = minetest.get_node(pos)
420 local dir = vector.new(minetest.facedir_to_dir(napos.param2)) -- a copy of the facedir so we don't overwrite the facedir table
421 if napos.name == "air" then
422 napos = minetest.get_node({x = pos.x, y = pos.y -1, z = pos.z})
423 dir = vector.new(minetest.facedir_to_dir(napos.param2))
424 elseif not string.sub(napos.name,1,string.len("walkway:")) == "walkway:" then
425 napos = minetest.get_node({x = pos.x, y = pos.y + 1, z = pos.z})
426 dir = vector.new(minetest.facedir_to_dir(napos.param2))
427 end
428
429 if napos.name == "walkway:belt_straight" then
430 self.object:setvelocity({x = dir.x / speed, y = 0, z = dir.z / speed})
431 elseif string.sub(napos.name,1,string.len("walkway:")) == "walkway:" then
432 if dir.x == 0 then
433 dir.x = (math.floor(pos.x + 0.5) - pos.x) * 2
434 elseif dir.z == 0 then
435 dir.z = (math.floor(pos.z + 0.5) - pos.z) * 2
436 end
437 self.object:setvelocity(generate_velocity_vector(dir, 0, 0, napos))
438 else
439 local stack = ItemStack(self.itemstring)
440 local veldir = self.object:getvelocity();
441 minetest.item_drop(stack, walkway.no_player, {x = pos.x + veldir.x / 3, y = pos.y, z = pos.z + veldir.z / 3})
442 self.object:remove()
443 end
444 end
445 })
446
447 minetest.register_craft({
448 output = "walkway:belt 12",
449 recipe = {
450 {"", "default:gold_ingot", ""},
451 {"default:stone", "default:mese_crystal", "default:stone"},
452 {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}
453 }
454 })