3453d435c7e06bf6417d519441253c5159343677
[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(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
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, 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(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
178
179 minetest.register_node("walkway:belt", {
180 description = "Moving Walkway",
181 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",
182 "factory_belt_side.png", "factory_belt_side.png", "factory_belt_side.png"},
183 groups = {cracky=1},
184 drawtype = "nodebox",
185 paramtype = "light",
186 paramtype2 = "facedir",
187 is_ground_content = true,
188 legacy_facedir_simple = true,
189 node_box = {
190 type = "fixed",
191 fixed = {{-0.5,-0.5,-0.5,0.5,0.0,0.5},}
192 },
193 })
194 minetest.register_node("walkway:slope_1",
195 {description = "Moving Walkway",
196 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",
197 "factory_belt_side.png", "factory_belt_side.png", "factory_belt_side.png"},
198 groups = {cracky=1},
199
200 drawtype = "mesh",
201 paramtype = "light",
202 paramtype2 = "facedir",
203 on_place = minetest.rotate_node,
204 description = desc,
205 is_ground_content = true,
206 legacy_facedir_simple = true,
207 mesh = "moreblocks_slope_half.obj",
208 collision_box = box_slope_half,
209 selection_box = box_slope_half,
210 })
211 minetest.register_node("walkway:slope_2",
212 {description = "Moving Walkway",
213 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",
214 "factory_belt_side.png", "factory_belt_side.png", "factory_belt_side.png"},
215 groups = {cracky=1},
216
217 drawtype = "mesh",
218 paramtype = "light",
219 paramtype2 = "facedir",
220 on_place = minetest.rotate_node,
221 description = desc,
222 is_ground_content = true,
223 legacy_facedir_simple = true,
224 mesh = "moreblocks_slope_half_raised.obj",
225 collision_box = box_slope_half_raised,
226 selection_box = box_slope_half_raised,
227 })
228 minetest.register_node("walkway:slope_1_down",
229 {description = "Moving Walkway",
230 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",
231 "factory_belt_side.png", "factory_belt_side.png", "factory_belt_side.png"},
232 groups = {cracky=1},
233
234 drawtype = "mesh",
235 paramtype = "light",
236 paramtype2 = "facedir",
237 on_place = minetest.rotate_node,
238 description = desc,
239 is_ground_content = true,
240 legacy_facedir_simple = true,
241 mesh = "moreblocks_slope_half.obj",
242 collision_box = box_slope_half,
243 selection_box = box_slope_half,
244 })
245 minetest.register_node("walkway:slope_2_down",
246 {description = "Moving Walkway",
247 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",
248 "factory_belt_side.png", "factory_belt_side.png", "factory_belt_side.png"},
249 groups = {cracky=1},
250
251 drawtype = "mesh",
252 paramtype = "light",
253 paramtype2 = "facedir",
254 on_place = minetest.rotate_node,
255 description = desc,
256 is_ground_content = true,
257 legacy_facedir_simple = true,
258 mesh = "moreblocks_slope_half_raised.obj",
259 collision_box = box_slope_half_raised,
260 selection_box = box_slope_half_raised,
261 })
262
263
264
265 -- minetest.register_node("walkway:belt_straight", {
266 -- description = "straight Conveyor Belt",
267 -- 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",
268 -- "factory_belt_side.png", "factory_belt_side.png", "factory_belt_side.png"},
269 -- groups = {cracky=1},
270 -- drawtype = "nodebox",
271 -- paramtype = "light",
272 -- paramtype2 = "facedir",
273 -- is_ground_content = true,
274 -- legacy_facedir_simple = true,
275 -- node_box = {
276 -- type = "fixed",
277 -- fixed = {{-0.5,-0.5,-0.5,0.5,0.0625,0.5},}
278 -- },
279 -- })
280
281 minetest.register_abm({
282 nodenames = {"walkway:belt", "walkway:belt_straight"},
283 neighbors = nil,
284 interval = 1,
285 chance = 1,
286 action = function(pos, node, active_object_count, active_object_count_wider)
287 local all_objects = minetest.get_objects_inside_radius(pos, 0.75)
288 local _,obj
289 for _,obj in ipairs(all_objects) do
290 if not obj:is_player() and obj:get_luaentity() and obj:get_luaentity().name == "__builtin:item" then
291 walkway.do_moving_item({x = pos.x, y = pos.y + 0.15, z = pos.z}, obj:get_luaentity().itemstring)
292 obj:get_luaentity().itemstring = ""
293 obj:remove()
294 end
295 end
296 end,
297 })
298
299 minetest.register_abm({
300 nodenames = {"walkway:belt", "walkway:belt_straight", "walkway:slope_1", "walkway:slope_2", "walkway:slope_1_down", "walkway:slope_2_down"},
301 neighbors = nil,
302 interval = 1,
303 chance = 1,
304 action = function(pos, node, active_object_count, active_object_count_wider)
305 local all_objects = minetest.get_objects_inside_radius(pos, 1)
306 local _,obj
307 -- minetest.chat_send_all(node.name)
308 for _,obj in ipairs(all_objects) do
309
310 if obj:is_player() and not obj:get_attach() then
311 dum = walkway.do_moving_dummy({x = pos.x, y = pos.y + 0.15, z = pos.z}, obj):get_luaentity()
312 dum.player = obj
313 obj:set_attach(dum.object, "", {x=0,y=9,z=0}, {x=0,y=0,z=0})
314 local name = obj:get_player_name()
315 default.player_attached[name] = true
316 elseif obj:get_luaentity() and string.sub(obj:get_luaentity().name,1,string.len("mobs_animal")) == "mobs_animal" then
317 local napos = minetest.get_node(pos)
318 obj:setvelocity(generate_velocity_vector(0, 0, node))
319 -- dum = walkway.do_moving_dummy({x = pos.x, y = pos.y + 0.15, z = pos.z}, obj):get_luaentity()
320 -- dum.player = obj
321 -- obj:set_attach(dum.object, "", {x=0,y=-1,z=0}, {x=0,y=0,z=0})
322 end
323 end
324 end,
325 })
326
327 -- Based off of the pipeworks item code
328
329 function walkway.do_moving_item(pos, item)
330 if item==":" then
331 return
332 end
333 local stack = ItemStack(item)
334 local obj = minetest.add_entity(pos, "walkway:moving_item")
335 obj:get_luaentity():set_item(stack:to_string())
336 return obj
337 end
338
339 function walkway.do_moving_dummy(pos, player)
340 local stack = ItemStack(item)
341 local obj = minetest.add_entity(pos, "walkway:moving_dummy")
342 -- obj:attach(player)
343 return obj
344 end
345
346
347 minetest.register_entity("walkway:moving_item", {
348 initial_properties = {
349 hp_max = 1,
350 physical = false,
351 collisionbox = {0.125, 0.125, 0.125, 0.125, 0.125, 0.125},
352 visual = "wielditem",
353 visual_size = {x = 0.5, y = 0.5},
354 textures = {""},
355 spritediv = {x = 1, y = 1},
356 initial_sprite_basepos = {x = 0, y = 0},
357 is_visible = false,
358 },
359
360 physical_state = true,
361 itemstring = '',
362 set_item = function(self, itemstring)
363 self.itemstring = itemstring
364 local stack = ItemStack(itemstring)
365 local count = stack:get_count()
366 local max_count = stack:get_stack_max()
367 if count > max_count then
368 count = max_count
369 self.itemstring = stack:get_name().." "..max_count
370 end
371 local s = 0.15 + 0.15 * (count / max_count)
372 local c = 0.8 * s
373 local itemtable = stack:to_table()
374 local itemname = nil
375 if itemtable then
376 itemname = stack:to_table().name
377 end
378 local item_texture = nil
379 local item_type = ""
380 if core.registered_items[itemname] then
381 item_texture = core.registered_items[itemname].inventory_image
382 item_type = core.registered_items[itemname].type
383 end
384 prop = {
385 is_visible = true,
386 visual = "wielditem",
387 textures = {itemname},
388 visual_size = {x = s, y = s},
389 collisionbox = {-c, -c, -c, c, c, c},
390 automatic_rotate = math.pi * 0.2,
391 }
392 self.object:set_properties(prop)
393 end,
394
395 get_staticdata = function(self)
396 return core.serialize({
397 itemstring = self.itemstring
398 })
399 end,
400
401 on_activate = function(self, staticdata, dtime_s)
402 if string.sub(staticdata, 1, string.len("return")) == "return" then
403 local data = core.deserialize(staticdata)
404 if data and type(data) == "table" then
405 self.itemstring = data.itemstring
406 end
407 else
408 self.itemstring = staticdata
409 end
410 self.object:set_armor_groups({immortal = 1})
411 self:set_item(self.itemstring)
412 end,
413
414 on_step = function(self, dtime)
415 local pos = self.object:getpos()
416 local napos = minetest.get_node(pos)
417 local dir = vector.new(minetest.facedir_to_dir(napos.param2)) -- a copy of the facedir so we don't overwrite the facedir table
418 if napos.name == "walkway:belt_straight" then
419 self.object:setvelocity({x = dir.x / speed, y = 0, z = dir.z / speed})
420 elseif napos.name == "walkway:belt" then
421 if dir.x == 0 then
422 dir.x = (math.floor(pos.x + 0.5) - pos.x) * 2
423 elseif dir.z == 0 then
424 dir.z = (math.floor(pos.z + 0.5) - pos.z) * 2
425 end
426 self.object:setvelocity({x = dir.x / speed, y = 0, z = dir.z / speed})
427 else
428 local stack = ItemStack(self.itemstring)
429 local veldir = self.object:getvelocity();
430 minetest.item_drop(stack, walkway.no_player, {x = pos.x + veldir.x / 3, y = pos.y, z = pos.z + veldir.z / 3})
431 self.object:remove()
432 end
433 end
434 })
435
436 minetest.register_craft({
437 output = "walkway:belt 12",
438 recipe = {
439 {"", "default:gold_ingot", ""},
440 {"default:stone", "default:mese_crystal", "default:stone"},
441 {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}
442 }
443 })