basic_machines/ball.lua
2016-05-12 15:42:02 +02:00

129 lines
3.7 KiB
Lua

-- BALL: energy ball that flies around, can bounce and activate stuff
-- rnd 2016:
minetest.register_entity("basic_machines:ball",{
timer = 0,
lifetime = 20, -- how long it exists before disappearing
energy = 1, -- if negative it will deactivate stuff
owner = "",
origin = {x=0,y=0,z=0},
hp_max = 1,
visual="sprite",
visual_size={x=.50,y=.50},
collisionbox = {0,0,0,0,0,0},
physical=false,
--textures={"basic_machines_ball"},
on_punch=function(self, puncher, time_from_last_punch, tool_capabilities, dir) -- ball is punched
end,
on_activate = function(self, staticdata)
self.object:set_properties({textures={"basic_machines_ball.png"}})
self.object:setvelocity({x=0,y=0,z=0})
self.timer = 0;self.owner = "";
self.origin = self.object:getpos();
end,
on_step = function(self, dtime)
self.timer=self.timer+dtime
if self.timer>self.lifetime then
self.object:remove()
return
end
local pos=self.object:getpos()
local origin = self.origin;
local r = 20;
if math.abs(pos.x-origin.x)>r or math.abs(pos.y-origin.y)>r or math.abs(pos.z-origin.z)>r then -- remove if it goes too far
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;
end
if walkable then -- we hit a node
--minetest.chat_send_all(" hit node at " .. minetest.pos_to_string(pos))
if minetest.is_protected(pos,self.owner) then return end
local node = minetest.get_node(pos);
local table = minetest.registered_nodes[node.name];
if table and table.mesecons and table.mesecons.effector then
local effector = table.mesecons.effector;
if self.energy>0 then
if not effector.action_on then return end
effector.action_on(pos,node,16);
elseif self.energy<0 then
if not effector.action_off then return end
effector.action_off(pos,node,16);
end
self.object:remove()
else -- bounce
local v = self.object:getvelocity();
local opos = {x=math.modf(pos.x),y=math.modf(pos.y), z=math.modf(pos.z)}; -- obstacle
opos.x=math.abs(pos.x-opos.x);
opos.y=math.abs(pos.y-opos.y);
opos.z=math.abs(pos.z-opos.z);
local maxo = math.max(opos.x,opos.y,opos.z);
--minetest.chat_send_all(minetest.pos_to_string(opos))
if opos.x == maxo then
v.x=-v.x
elseif opos.y == maxo then
v.y=-v.y
else
v.z=-v.z
end
self.object:setvelocity(v);
if maxo<0.25 then self.object:remove() end -- too deep inside block, just remove
end
return
end
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},
drawtype = "liquid",
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());
end,
mesecons = {effector = {
action_on = function (pos, node,ttl)
if ttl<0 then return end
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;
end,
action_off = function (pos, node,ttl)
if ttl<0 then return end
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;
obj:set_properties({textures={"basic_machines_ball.png^[colorize:blue:120"}})
end
}
},
})
minetest.register_craft({
output = "basic_machines:ball_spawner",
recipe = {
{"basic_machines:power_cell"},
{"basic_machines:keypad"}
}
})