2016-05-12 12:23:42 +02:00
-- BALL: energy ball that flies around, can bounce and activate stuff
-- rnd 2016:
2016-06-07 07:51:00 +02:00
-- TO DO: move mode: ball just rolling around on ground, also if inside slope it would "roll down", just increased velocity in slope direction
2016-06-12 20:30:32 +02:00
local ballcount = { } ;
2016-05-12 18:07:45 +02:00
local function round ( x )
if x < 0 then
return - math.floor ( - x + 0.5 ) ;
else
return math.floor ( x + 0.5 ) ;
end
end
2016-05-24 19:49:24 +02:00
basic_machines.ball = { } ;
basic_machines.ball . bounce_materials = { -- to be used with bounce setting 2 in ball spawner: 1: bounce in x direction, 2: bounce in z direction, otherwise it bounces in y direction
2016-05-26 16:35:43 +02:00
[ " default:wood " ] = 1 ,
2016-06-07 07:51:00 +02:00
[ " xpanes:bar_2 " ] = 1 ,
[ " xpanes:bar_10 " ] = 1 ,
[ " darkage:iron_bars " ] = 1 ,
2016-05-26 16:35:43 +02:00
[ " default:glass " ] = 2 ,
2016-05-24 19:49:24 +02:00
} ;
2016-05-21 20:01:14 +02:00
local ball_spawner_update_form = function ( pos )
local meta = minetest.get_meta ( pos ) ;
local x0 , y0 , z0 ;
x0 = meta : get_int ( " x0 " ) ; y0 = meta : get_int ( " y0 " ) ; z0 = meta : get_int ( " z0 " ) ; -- direction of velocity
2016-05-26 16:35:43 +02:00
local energy , bounce , g , puncheable , gravity , hp , hurt ;
2016-05-21 20:01:14 +02:00
local speed = meta : get_float ( " speed " ) ; -- if positive sets initial ball speed
energy = meta : get_float ( " energy " ) ; -- if positive activates, negative deactivates, 0 does nothing
bounce = meta : get_int ( " bounce " ) ; -- if nonzero bounces when hit obstacle, 0 gets absorbed
gravity = meta : get_float ( " gravity " ) ; -- gravity
2016-05-26 16:35:43 +02:00
hp = meta : get_float ( " hp " ) ;
hurt = meta : get_float ( " hurt " ) ;
2016-05-21 20:01:14 +02:00
puncheable = meta : get_int ( " puncheable " ) ; -- if 1 can be punched by players in protection, if 2 can be punched by anyone
2016-05-26 21:12:05 +02:00
local texture = meta : get_string ( " texture " ) or " basic_machines_ball.png " ;
2016-05-21 20:01:14 +02:00
local form =
2016-05-26 21:12:05 +02:00
" size[4.25,4.75] " .. -- width, height
2016-05-21 20:01:14 +02:00
" field[0.25,0.5;1,1;x0;target; " .. x0 .. " ] field[1.25,0.5;1,1;y0;; " .. y0 .. " ] field[2.25,0.5;1,1;z0;; " .. z0 .. " ] " ..
" field[3.25,0.5;1,1;speed;speed; " .. speed .. " ] " ..
--speed, jump, gravity,sneak
" field[0.25,1.5;1,1;energy;energy; " .. energy .. " ] " ..
" field[1.25,1.5;1,1;bounce;bounce; " .. bounce .. " ] " ..
" field[2.25,1.5;1,1;gravity;gravity; " .. gravity .. " ] " ..
" field[3.25,1.5;1,1;puncheable;puncheable; " .. puncheable .. " ] " ..
2016-05-26 16:35:43 +02:00
" field[0.25,2.5;1,1;hp;hp; " .. hp .. " ] " .. " field[1.25,2.5;1,1;hurt;hurt; " .. hurt .. " ] " ..
2016-05-26 21:12:05 +02:00
" field[0.25,3.5;4,1;texture;texture; " .. texture .. " ] " ..
" button_exit[3.25,4.25;1,1;OK;OK] " ;
2016-05-24 19:49:24 +02:00
if meta : get_int ( " admin " ) == 1 then
local lifetime = meta : get_int ( " lifetime " ) ;
if lifetime <= 0 then lifetime = 20 end
2016-05-26 16:35:43 +02:00
form = form .. " field[2.25,2.5;1,1;lifetime;lifetime; " .. lifetime .. " ] "
2016-05-24 19:49:24 +02:00
end
2016-05-21 20:01:14 +02:00
meta : set_string ( " formspec " , form ) ;
end
2016-05-12 12:23:42 +02:00
minetest.register_entity ( " basic_machines:ball " , {
timer = 0 ,
lifetime = 20 , -- how long it exists before disappearing
2016-05-21 20:01:14 +02:00
energy = 1 , -- if negative it will deactivate stuff, positive will activate, 0 wont do anything
puncheable = 1 , -- can be punched by players in protection
bounce = 0 , -- 0: absorbs in block, 1 = proper bounce=lag buggy, -- to do: 2 = line of sight bounce
gravity = 0 ,
speed = 5 , -- velocity when punched
2016-05-26 16:35:43 +02:00
hurt = 0 , -- how much damage it does to target entity, if 0 damage disabled
2016-05-12 12:23:42 +02:00
owner = " " ,
origin = { x = 0 , y = 0 , z = 0 } ,
2016-05-26 16:35:43 +02:00
lastpos = { x = 0 , y = 0 , z = 0 } , -- last not-colliding position
2016-05-21 20:01:14 +02:00
hp_max = 100 ,
2016-05-26 16:35:43 +02:00
elasticity = 0.9 , -- speed gets multiplied by this after bounce
2016-05-12 12:23:42 +02:00
visual = " sprite " ,
2016-05-13 19:11:55 +02:00
visual_size = { x = .6 , y = .6 } ,
2016-05-21 20:01:14 +02:00
collisionbox = { - 0.5 , - 0.5 , - 0.5 , 0.5 , 0.5 , 0.5 } ,
2016-05-12 12:23:42 +02:00
physical = false ,
2016-05-21 20:01:14 +02:00
2016-05-12 12:23:42 +02:00
--textures={"basic_machines_ball"},
2016-05-26 16:35:43 +02:00
2016-05-12 12:23:42 +02:00
on_activate = function ( self , staticdata )
self.object : set_properties ( { textures = { " basic_machines_ball.png " } } )
self.timer = 0 ; self.owner = " " ;
self.origin = self.object : getpos ( ) ;
end ,
2016-05-21 20:01:14 +02:00
on_punch = function ( self , puncher , time_from_last_punch , tool_capabilities , dir )
if self.puncheable == 0 then return end
if self.puncheable == 1 then -- only those in protection
local name = puncher : get_player_name ( ) ;
local pos = self.object : getpos ( ) ;
if minetest.is_protected ( pos , name ) then return end
end
--minetest.chat_send_all(minetest.pos_to_string(dir))
if time_from_last_punch < 0.5 then return end
local v = self.speed or 1 ;
local velocity = dir ;
velocity.x = velocity.x * v ; velocity.y = velocity.y * v ; velocity.z = velocity.z * v ;
self.object : setvelocity ( velocity )
end ,
2016-05-12 12:23:42 +02:00
on_step = function ( self , dtime )
self.timer = self.timer + dtime
if self.timer > self.lifetime then
2016-06-12 20:30:32 +02:00
local count = ballcount [ self.owner ] or 1 ; count = count - 1 ; ballcount [ self.owner ] = count ;
2016-05-21 20:01:14 +02:00
self.object : remove ( )
2016-05-12 12:23:42 +02:00
return
end
local pos = self.object : getpos ( )
local origin = self.origin ;
2016-05-13 19:11:55 +02:00
local r = 30 ; -- maximal distance when balls disappear
2016-05-23 23:26:02 +02:00
local dist = math.max ( math.abs ( pos.x - origin.x ) , math.abs ( pos.y - origin.y ) , math.abs ( pos.z - origin.z ) ) ;
if dist > r then -- remove if it goes too far
2016-06-12 20:30:32 +02:00
local count = ballcount [ self.owner ] or 1 ; count = count - 1 ; ballcount [ self.owner ] = count ;
2016-05-12 12:23:42 +02:00
self.object : remove ( )
return
end
local nodename = minetest.get_node ( pos ) . name ;
local walkable = false ;
if nodename ~= " air " then
walkable = minetest.registered_nodes [ nodename ] . walkable ;
2016-05-26 16:35:43 +02:00
if nodename == " basic_machines:ball_spawner " and dist > 0.5 then walkable = true end -- ball can activate spawner, just not originating one
2016-05-12 12:23:42 +02:00
end
2016-05-26 16:35:43 +02:00
if not walkable then
self.lastpos = pos
if self.hurt ~= 0 then -- check for coliding nearby objects
local objects = minetest.get_objects_inside_radius ( pos , 1 ) ;
if # objects > 1 then
for _ , obj in pairs ( objects ) do
local p = obj : getpos ( ) ;
local d = math.sqrt ( ( p.x - pos.x ) ^ 2 + ( p.y - pos.y ) ^ 2 + ( p.z - pos.z ) ^ 2 ) ;
if d > 0 then
2016-05-26 21:12:05 +02:00
if minetest.is_protected ( p , self.owner ) then return end
2016-05-26 16:35:43 +02:00
obj : set_hp ( obj : get_hp ( ) - self.hurt )
2016-06-12 20:30:32 +02:00
local count = ballcount [ self.owner ] or 1 ; count = count - 1 ; ballcount [ self.owner ] = count ;
self.object : remove ( ) ;
return
2016-05-26 16:35:43 +02:00
end
end
end
end
end
2016-05-12 12:23:42 +02:00
if walkable then -- we hit a node
--minetest.chat_send_all(" hit node at " .. minetest.pos_to_string(pos))
2016-05-12 13:48:22 +02:00
2016-05-12 12:23:42 +02:00
local node = minetest.get_node ( pos ) ;
local table = minetest.registered_nodes [ node.name ] ;
2016-05-23 19:32:21 +02:00
if table and table.mesecons and table.mesecons . effector then -- activate target
2016-05-26 16:35:43 +02:00
2016-05-21 20:01:14 +02:00
if minetest.is_protected ( pos , self.owner ) then return end
2016-05-12 13:48:22 +02:00
local effector = table.mesecons . effector ;
2016-05-26 16:35:43 +02:00
local energy = self.energy ;
self.object : remove ( ) ;
if energy > 0 then
2016-05-12 13:48:22 +02:00
if not effector.action_on then return end
effector.action_on ( pos , node , 16 ) ;
2016-05-26 16:35:43 +02:00
elseif energy < 0 then
2016-05-12 13:48:22 +02:00
if not effector.action_off then return end
effector.action_off ( pos , node , 16 ) ;
end
2016-05-21 20:01:14 +02:00
2016-05-26 16:35:43 +02:00
2016-05-12 18:07:45 +02:00
else -- bounce ( copyright rnd, 2016 )
2016-05-21 20:01:14 +02:00
local bounce = self.bounce ;
2016-06-12 20:30:32 +02:00
if self.bounce == 0 then
local count = ballcount [ self.owner ] or 1 ; count = count - 1 ; ballcount [ self.owner ] = count ;
self.object : remove ( )
return end
2016-05-21 20:01:14 +02:00
2016-05-26 16:35:43 +02:00
local n = { x = 0 , y = 0 , z = 0 } ; -- this will be bounce normal
2016-05-12 13:48:22 +02:00
local v = self.object : getvelocity ( ) ;
2016-05-23 19:32:21 +02:00
local opos = { x = round ( pos.x ) , y = round ( pos.y ) , z = round ( pos.z ) } ; -- obstacle
local bpos = { x = ( pos.x - opos.x ) , y = ( pos.y - opos.y ) , z = ( pos.z - opos.z ) } ; -- boundary position on cube, approximate
2016-05-12 18:07:45 +02:00
2016-05-24 19:49:24 +02:00
if bounce == 2 then -- uses special blocks for non buggy lag proof bouncing: by default it bounces in y direction
local bounce_direction = basic_machines.ball . bounce_materials [ node.name ] or 0 ;
if bounce_direction == 0 then
2016-05-26 16:35:43 +02:00
if v.y >= 0 then n.y = - 1 else n.y = 1 end
2016-05-24 19:49:24 +02:00
elseif bounce_direction == 1 then
2016-05-26 16:35:43 +02:00
if v.x >= 0 then n.x = - 1 else n.x = 1 end
2016-05-23 23:26:02 +02:00
n.y = 0 ;
2016-05-24 19:49:24 +02:00
elseif bounce_direction == 2 then
2016-05-26 16:35:43 +02:00
if v.z >= 0 then n.z = - 1 else n.z = 1 end
2016-05-24 19:49:24 +02:00
n.y = 0 ;
2016-05-23 23:26:02 +02:00
end
2016-05-24 19:49:24 +02:00
2016-05-26 16:35:43 +02:00
else -- algorithm to determine bounce direction - problem: with lag its impossible to determine reliable which node was hit and which face ..
2016-05-12 18:07:45 +02:00
2016-05-26 16:35:43 +02:00
if v.x <= 0 then n.x = 1 else n.x = - 1 end -- possible bounce directions
if v.y <= 0 then n.y = 1 else n.y = - 1 end
if v.z <= 0 then n.z = 1 else n.z = - 1 end
2016-05-23 23:26:02 +02:00
2016-05-26 16:35:43 +02:00
local dpos = { } ;
dpos.x = 0.5 * n.x ; dpos.y = 0 ; dpos.z = 0 ; -- calculate distance to bounding surface midpoints
2016-05-23 23:26:02 +02:00
2016-05-26 16:35:43 +02:00
local d1 = ( bpos.x - dpos.x ) ^ 2 + ( bpos.y ) ^ 2 + ( bpos.z ) ^ 2 ;
dpos.x = 0 ; dpos.y = 0.5 * n.y ; dpos.z = 0 ;
local d2 = ( bpos.x ) ^ 2 + ( bpos.y - dpos.y ) ^ 2 + ( bpos.z ) ^ 2 ;
dpos.x = 0 ; dpos.y = 0 ; dpos.z = 0.5 * n.z ;
local d3 = ( bpos.x ) ^ 2 + ( bpos.y ) ^ 2 + ( bpos.z - dpos.z ) ^ 2 ;
local d = math.min ( d1 , d2 , d3 ) ; -- we obtain bounce direction from minimal distance
2016-05-23 23:26:02 +02:00
2016-05-26 16:35:43 +02:00
if d1 == d then --x
n.y = 0 ; n.z = 0
elseif d2 == d then --y
n.x = 0 ; n.z = 0
elseif d3 == d then --z
n.x = 0 ; n.y = 0
2016-05-23 23:26:02 +02:00
end
2016-05-26 16:35:43 +02:00
nodename = minetest.get_node ( { x = opos.x + n.x , y = opos.y + n.y , z = opos.z + n.z } ) . name -- verify normal
walkable = nodename ~= " air " ;
2016-05-23 23:26:02 +02:00
if walkable then -- problem, nonempty node - incorrect normal, fix it
2016-05-26 16:35:43 +02:00
if n.x ~= 0 then -- x direction is wrong, try something else
2016-05-23 23:26:02 +02:00
n.x = 0 ;
2016-05-26 16:35:43 +02:00
if v.y >= 0 then n.y = - 1 else n.y = 1 end -- try y
nodename = minetest.get_node ( { x = opos.x + n.x , y = opos.y + n.y , z = opos.z + n.z } ) . name -- verify normal
walkable = nodename ~= " air " ;
if walkable then -- still problem, only remaining is z
n.y = 0 ;
if v.z >= 0 then n.z = - 1 else n.z = 1 end
nodename = minetest.get_node ( { x = opos.x + n.x , y = opos.y + n.y , z = opos.z + n.z } ) . name -- verify normal
walkable = nodename ~= " air " ;
if walkable then -- messed up, just remove the ball
self.object : remove ( )
return
end
end
2016-05-23 23:26:02 +02:00
end
2016-05-26 16:35:43 +02:00
end
2016-05-26 21:12:05 +02:00
end
2016-05-12 20:37:16 +02:00
2016-05-13 19:11:55 +02:00
local elasticity = self.elasticity ;
2016-05-12 20:37:16 +02:00
-- bounce
if n.x ~= 0 then
2016-05-13 19:11:55 +02:00
v.x =- elasticity * v.x
2016-05-12 20:37:16 +02:00
elseif n.y ~= 0 then
2016-05-13 19:11:55 +02:00
v.y =- elasticity * v.y
2016-05-12 20:37:16 +02:00
elseif n.z ~= 0 then
2016-05-13 19:11:55 +02:00
v.z =- elasticity * v.z
2016-05-12 15:42:02 +02:00
end
2016-05-12 20:37:16 +02:00
local r = 0.2
bpos = { x = pos.x + n.x * r , y = pos.y + n.y * r , z = pos.z + n.z * r } ; -- point placed a bit further away from box
2016-05-26 16:35:43 +02:00
self.object : setpos ( bpos ) -- place object at last known outside point
2016-05-13 19:11:55 +02:00
2016-05-12 13:48:22 +02:00
self.object : setvelocity ( v ) ;
2016-05-12 18:07:45 +02:00
2016-05-13 19:11:55 +02:00
minetest.sound_play ( " default_dig_cracky " , { pos = pos , gain = 1.0 , max_hear_distance = 8 , } )
2016-05-12 12:46:39 +02:00
end
2016-05-12 12:23:42 +02:00
end
2016-05-26 16:35:43 +02:00
return
2016-05-12 12:23:42 +02:00
end ,
} )
minetest.register_node ( " basic_machines:ball_spawner " , {
description = " Spawns energy ball one block above " ,
tiles = { " basic_machines_ball.png " } ,
groups = { oddly_breakable_by_hand = 2 , mesecon_effector_on = 1 } ,
2016-05-14 23:08:34 +02:00
drawtype = " allfaces " ,
paramtype = " light " ,
param1 = 1 ,
2016-05-12 12:23:42 +02:00
walkable = false ,
alpha = 150 ,
sounds = default.node_sound_wood_defaults ( ) ,
after_place_node = function ( pos , placer )
local meta = minetest.env : get_meta ( pos )
meta : set_string ( " owner " , placer : get_player_name ( ) ) ;
2016-05-24 19:49:24 +02:00
local privs = minetest.get_player_privs ( placer : get_player_name ( ) ) ; if privs.privs then meta : set_int ( " admin " , 1 ) end
2016-05-21 20:01:14 +02:00
2016-06-12 20:30:32 +02:00
if privs.machines then meta : set_int ( " machines " , 1 ) end
2016-05-26 16:35:43 +02:00
meta : set_float ( " hurt " , 0 ) ;
2016-05-26 21:12:05 +02:00
meta : set_string ( " texture " , " basic_machines_ball.png " ) ;
2016-05-26 16:35:43 +02:00
meta : set_float ( " hp " , 100 ) ;
2016-05-21 20:01:14 +02:00
meta : set_float ( " speed " , 5 ) ; -- if positive sets initial ball speed
meta : set_float ( " energy " , 1 ) ; -- if positive activates, negative deactivates, 0 does nothing
meta : set_int ( " bounce " , 0 ) ; -- if nonzero bounces when hit obstacle, 0 gets absorbed
meta : set_float ( " gravity " , 0 ) ; -- gravity
meta : set_int ( " puncheable " , 0 ) ; -- if 0 not puncheable, if 1 can be punched by players in protection, if 2 can be punched by anyone
ball_spawner_update_form ( pos ) ;
2016-05-12 12:23:42 +02:00
end ,
mesecons = { effector = {
action_on = function ( pos , node , ttl )
if ttl < 0 then return end
2016-05-23 23:26:02 +02:00
local meta = minetest.get_meta ( pos ) ;
local t0 = meta : get_int ( " t " ) ;
local t1 = minetest.get_gametime ( ) ;
local T = meta : get_int ( " T " ) ; -- temperature
2016-05-26 16:35:43 +02:00
if t0 > t1 - 2 then -- activated before natural time
2016-05-23 23:26:02 +02:00
T = T + 1 ;
else
2016-06-12 20:30:32 +02:00
if T > 0 then
T = T - 1
if t1 - t0 > 5 then T = 0 end
end
2016-05-23 23:26:02 +02:00
end
meta : set_int ( " T " , T ) ;
meta : set_int ( " t " , t1 ) ; -- update last activation time
if T > 2 then -- overheat
minetest.sound_play ( " default_cool_lava " , { pos = pos , max_hear_distance = 16 , gain = 0.25 } )
meta : set_string ( " infotext " , " overheat: temperature " .. T )
return
end
2016-06-12 20:30:32 +02:00
if meta : get_int ( " machines " ) ~= 1 then -- no machines priv, limit ball count
local owner = meta : get_string ( " owner " ) ;
local count = ballcount [ owner ] ;
if not count or count < 0 then count = 0 end
if count >= 2 then
if t1 - t0 > 20 then count = 0
else return
end
end
count = count + 1 ;
ballcount [ owner ] = count ;
--minetest.chat_send_all("count " .. count);
end
2016-05-23 23:26:02 +02:00
2016-05-26 16:35:43 +02:00
pos.x = round ( pos.x ) ; pos.y = round ( pos.y ) ; pos.z = round ( pos.z ) ;
2016-05-12 12:46:39 +02:00
local obj = minetest.add_entity ( { x = pos.x , y = pos.y , z = pos.z } , " basic_machines:ball " ) ;
local luaent = obj : get_luaentity ( ) ;
2016-05-21 20:01:14 +02:00
local meta = minetest.get_meta ( pos ) ;
local speed , energy , bounce , gravity , puncheable ;
speed = meta : get_float ( " speed " ) ;
energy = meta : get_float ( " energy " ) ; -- if positive activates, negative deactivates, 0 does nothing
bounce = meta : get_int ( " bounce " ) ; -- if nonzero bounces when hit obstacle, 0 gets absorbed
gravity = meta : get_float ( " gravity " ) ; -- gravity
puncheable = meta : get_int ( " puncheable " ) ; -- if 1 can be punched by players in protection, if 2 can be punched by anyone
if energy < 0 then
obj : set_properties ( { textures = { " basic_machines_ball.png^[colorize:blue:120 " } } )
end
luaent.bounce = bounce ;
luaent.energy = energy ;
if gravity > 0 then
obj : setacceleration ( { x = 0 , y =- gravity , z = 0 } ) ;
end
luaent.puncheable = puncheable ;
2016-05-26 16:35:43 +02:00
luaent.owner = meta : get_string ( " owner " ) ;
luaent.hurt = meta : get_float ( " hurt " ) ;
obj : set_hp ( meta : get_float ( " hp " ) ) ;
2016-05-21 20:01:14 +02:00
local x0 , y0 , z0 ;
2016-05-24 19:49:24 +02:00
if speed > 0 then luaent.speed = speed end
2016-05-21 20:01:14 +02:00
x0 = meta : get_int ( " x0 " ) ; y0 = meta : get_int ( " y0 " ) ; z0 = meta : get_int ( " z0 " ) ; -- direction of velocity
if speed ~= 0 and ( x0 ~= 0 or y0 ~= 0 or z0 ~= 0 ) then -- set velocity direction
local velocity = { x = x0 , y = y0 , z = z0 } ;
local v = math.sqrt ( velocity.x ^ 2 + velocity.y ^ 2 + velocity.z ^ 2 ) ; if v == 0 then v = 1 end
v = v / speed ;
velocity.x = velocity.x / v ; velocity.y = velocity.y / v ; velocity.z = velocity.z / v ;
obj : setvelocity ( velocity ) ;
end
2016-05-24 19:49:24 +02:00
if meta : get_int ( " admin " ) == 1 then
luaent.lifetime = meta : get_float ( " lifetime " ) ;
end
2016-05-21 20:01:14 +02:00
2016-05-26 21:12:05 +02:00
obj : set_properties ( { textures = { meta : get_string ( " texture " ) } } )
2016-05-12 12:46:39 +02:00
end ,
action_off = function ( pos , node , ttl )
if ttl < 0 then return end
2016-05-26 16:35:43 +02:00
pos.x = round ( pos.x ) ; pos.y = round ( pos.y ) ; pos.z = round ( pos.z ) ;
2016-05-12 12:46:39 +02:00
local obj = minetest.add_entity ( { x = pos.x , y = pos.y , z = pos.z } , " basic_machines:ball " ) ;
local luaent = obj : get_luaentity ( ) ;
luaent.energy = - 1 ;
2016-05-12 13:07:46 +02:00
obj : set_properties ( { textures = { " basic_machines_ball.png^[colorize:blue:120 " } } )
2016-05-12 12:23:42 +02:00
end
}
} ,
2016-05-21 20:01:14 +02:00
on_receive_fields = function ( pos , formname , fields , sender )
local name = sender : get_player_name ( ) ; if minetest.is_protected ( pos , name ) then return end
if fields.OK then
local privs = minetest.get_player_privs ( sender : get_player_name ( ) ) ;
local meta = minetest.get_meta ( pos ) ;
local x0 = 0 ; local y0 = 0 ; local z0 = 0 ;
--minetest.chat_send_all("form at " .. dump(pos) .. " fields " .. dump(fields))
if fields.x0 then x0 = tonumber ( fields.x0 ) or 0 end
if fields.y0 then y0 = tonumber ( fields.y0 ) or 0 end
if fields.z0 then z0 = tonumber ( fields.z0 ) or 0 end
if not privs.privs and ( math.abs ( x0 ) > 10 or math.abs ( y0 ) > 10 or math.abs ( z0 ) > 10 ) then return end
meta : set_int ( " x0 " , x0 ) ; meta : set_int ( " y0 " , y0 ) ; meta : set_int ( " z0 " , z0 ) ;
2016-05-26 21:12:05 +02:00
local speed , energy , bounce , gravity , puncheable ;
2016-05-21 20:01:14 +02:00
energy = meta : get_float ( " energy " ) ; -- if positive activates, negative deactivates, 0 does nothing
bounce = meta : get_int ( " bounce " ) ; -- if nonzero bounces when hit obstacle, 0 gets absorbed
gravity = meta : get_float ( " gravity " ) ; -- gravity
puncheable = meta : get_int ( " puncheable " ) ; -- if 1 can be punched by players in protection, if 2 can be punched by anyone
if fields.speed then
local speed = tonumber ( fields.speed ) or 0 ;
if ( speed > 10 or speed < 0 ) and not privs.privs then return end
meta : set_float ( " speed " , speed )
end
if fields.energy then
local energy = tonumber ( fields.energy ) or 1 ;
meta : set_float ( " energy " , energy )
end
if fields.bounce then
local bounce = tonumber ( fields.bounce ) or 1 ;
meta : set_int ( " bounce " , bounce )
end
if fields.gravity then
local gravity = tonumber ( fields.gravity ) or 1 ;
if ( gravity < 0 or gravity > 30 ) and not privs.privs then return end
meta : set_float ( " gravity " , gravity )
end
if fields.puncheable then
meta : set_int ( " puncheable " , tonumber ( fields.puncheable ) or 0 )
end
2016-05-24 19:49:24 +02:00
if fields.lifetime then
meta : set_int ( " lifetime " , tonumber ( fields.lifetime ) or 0 )
end
2016-05-26 16:35:43 +02:00
if fields.hurt then
meta : set_float ( " hurt " , tonumber ( fields.hurt ) or 0 )
end
if fields.hp then
meta : set_float ( " hp " , math.abs ( tonumber ( fields.hp ) ) or 0 )
end
2016-05-26 21:12:05 +02:00
if fields.texture then
meta : set_string ( " texture " , fields.texture ) ;
end
2016-05-21 20:01:14 +02:00
ball_spawner_update_form ( pos ) ;
end
end
2016-05-12 12:23:42 +02:00
} )
minetest.register_craft ( {
output = " basic_machines:ball_spawner " ,
recipe = {
{ " basic_machines:power_cell " } ,
{ " basic_machines:keypad " }
}
} )