forked from Mineclonia/Mineclonia
Merge branch 'stuck_arrow' of http://repo.or.cz/MineClone/MineClone2 into stuck_arrow
This commit is contained in:
commit
76356ed1e5
|
@ -17,6 +17,20 @@ local boxes_on = {
|
||||||
wall_top = { -4/16, 7/16, -2/16, 4/16, 8/16, 2/16 },
|
wall_top = { -4/16, 7/16, -2/16, 4/16, 8/16, 2/16 },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- Push the button
|
||||||
|
mesecon.push_button = function(pos, node)
|
||||||
|
-- No-op if button is already pushed
|
||||||
|
if mesecon.is_receptor_on(node) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local def = minetest.registered_nodes[node.name]
|
||||||
|
minetest.set_node(pos, {name="mesecons_button:button_"..def._mcl_button_basename.."_on", param2=node.param2})
|
||||||
|
mesecon.receptor_on(pos, button_get_output_rules(node))
|
||||||
|
minetest.sound_play("mesecons_button_push", {pos=pos})
|
||||||
|
local timer = minetest.get_node_timer(pos)
|
||||||
|
timer:start(def._mcl_button_timer)
|
||||||
|
end
|
||||||
|
|
||||||
local on_button_place = function(itemstack, placer, pointed_thing)
|
local on_button_place = function(itemstack, placer, pointed_thing)
|
||||||
if pointed_thing.type ~= "node" then
|
if pointed_thing.type ~= "node" then
|
||||||
-- no interaction possible with entities
|
-- no interaction possible with entities
|
||||||
|
@ -66,7 +80,7 @@ end
|
||||||
|
|
||||||
local buttonuse = "Rightclick the button to push it."
|
local buttonuse = "Rightclick the button to push it."
|
||||||
|
|
||||||
mesecon.register_button = function(basename, description, texture, recipeitem, sounds, plusgroups, button_timer, longdesc)
|
mesecon.register_button = function(basename, description, texture, recipeitem, sounds, plusgroups, button_timer, push_by_arrow, longdesc)
|
||||||
local groups_off = table.copy(plusgroups)
|
local groups_off = table.copy(plusgroups)
|
||||||
groups_off.attached_node=1
|
groups_off.attached_node=1
|
||||||
groups_off.dig_by_water=1
|
groups_off.dig_by_water=1
|
||||||
|
@ -78,6 +92,11 @@ mesecon.register_button = function(basename, description, texture, recipeitem, s
|
||||||
groups_on.not_in_creative_inventory=1
|
groups_on.not_in_creative_inventory=1
|
||||||
groups_on.button=2 -- button (on)
|
groups_on.button=2 -- button (on)
|
||||||
|
|
||||||
|
if push_by_arrow then
|
||||||
|
groups_off.button_push_by_arrow = 1
|
||||||
|
groups_on.button_push_by_arrow = 1
|
||||||
|
end
|
||||||
|
|
||||||
minetest.register_node("mesecons_button:button_"..basename.."_off", {
|
minetest.register_node("mesecons_button:button_"..basename.."_off", {
|
||||||
drawtype = "nodebox",
|
drawtype = "nodebox",
|
||||||
tiles = {texture},
|
tiles = {texture},
|
||||||
|
@ -98,17 +117,16 @@ mesecon.register_button = function(basename, description, texture, recipeitem, s
|
||||||
on_place = on_button_place,
|
on_place = on_button_place,
|
||||||
node_placement_prediction = "",
|
node_placement_prediction = "",
|
||||||
on_rightclick = function (pos, node)
|
on_rightclick = function (pos, node)
|
||||||
minetest.set_node(pos, {name="mesecons_button:button_"..basename.."_on", param2=node.param2})
|
mesecon.push_button(pos, node)
|
||||||
mesecon.receptor_on(pos, button_get_output_rules(node))
|
|
||||||
minetest.sound_play("mesecons_button_push", {pos=pos})
|
|
||||||
local timer = minetest.get_node_timer(pos)
|
|
||||||
timer:start(button_timer)
|
|
||||||
end,
|
end,
|
||||||
sounds = sounds,
|
sounds = sounds,
|
||||||
mesecons = {receptor = {
|
mesecons = {receptor = {
|
||||||
state = mesecon.state.off,
|
state = mesecon.state.off,
|
||||||
rules = button_get_output_rules,
|
rules = button_get_output_rules,
|
||||||
}},
|
}},
|
||||||
|
_mcl_button_basename = basename,
|
||||||
|
_mcl_button_timer = button_timer,
|
||||||
|
|
||||||
_mcl_blast_resistance = 2.5,
|
_mcl_blast_resistance = 2.5,
|
||||||
_mcl_hardness = 0.5,
|
_mcl_hardness = 0.5,
|
||||||
})
|
})
|
||||||
|
@ -134,14 +152,33 @@ mesecon.register_button = function(basename, description, texture, recipeitem, s
|
||||||
state = mesecon.state.on,
|
state = mesecon.state.on,
|
||||||
rules = button_get_output_rules
|
rules = button_get_output_rules
|
||||||
}},
|
}},
|
||||||
|
_mcl_button_basename = basename,
|
||||||
|
_mcl_button_timer = button_timer,
|
||||||
on_timer = function(pos, elapsed)
|
on_timer = function(pos, elapsed)
|
||||||
local node = minetest.get_node(pos)
|
local node = minetest.get_node(pos)
|
||||||
if node.name=="mesecons_button:button_"..basename.."_on" then --has not been dug
|
if node.name=="mesecons_button:button_"..basename.."_on" then --has not been dug
|
||||||
|
-- Is button pushable by arrow?
|
||||||
|
if push_by_arrow then
|
||||||
|
-- If there's an arrow stuck in the button, keep it pressed and check
|
||||||
|
-- it again later.
|
||||||
|
local objs = minetest.get_objects_inside_radius(pos, 1)
|
||||||
|
for o=1, #objs do
|
||||||
|
local entity = objs[o]:get_luaentity()
|
||||||
|
if entity and entity.name == "mcl_bows:arrow_entity" then
|
||||||
|
local timer = minetest.get_node_timer(pos)
|
||||||
|
timer:start(button_timer)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Normal operation: Un-press the button
|
||||||
minetest.set_node(pos, {name="mesecons_button:button_"..basename.."_off",param2=node.param2})
|
minetest.set_node(pos, {name="mesecons_button:button_"..basename.."_off",param2=node.param2})
|
||||||
minetest.sound_play("mesecons_button_pop", {pos=pos})
|
minetest.sound_play("mesecons_button_pop", {pos=pos})
|
||||||
mesecon.receptor_off(pos, button_get_output_rules(node))
|
mesecon.receptor_off(pos, button_get_output_rules(node))
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
_mcl_blast_resistance = 2.5,
|
_mcl_blast_resistance = 2.5,
|
||||||
_mcl_hardness = 0.5,
|
_mcl_hardness = 0.5,
|
||||||
})
|
})
|
||||||
|
@ -160,6 +197,7 @@ mesecon.register_button(
|
||||||
mcl_sounds.node_sound_stone_defaults(),
|
mcl_sounds.node_sound_stone_defaults(),
|
||||||
{material_stone=1,handy=1,pickaxey=1},
|
{material_stone=1,handy=1,pickaxey=1},
|
||||||
1,
|
1,
|
||||||
|
false,
|
||||||
"A stone button is a redstone component made out of stone which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1 second. It can only be placed on solid opaque full cubes (like cobblestone).")
|
"A stone button is a redstone component made out of stone which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1 second. It can only be placed on solid opaque full cubes (like cobblestone).")
|
||||||
|
|
||||||
local woods = {
|
local woods = {
|
||||||
|
@ -180,7 +218,8 @@ for w=1, #woods do
|
||||||
mcl_sounds.node_sound_wood_defaults(),
|
mcl_sounds.node_sound_wood_defaults(),
|
||||||
{material_wood=1,handy=1,axey=1},
|
{material_wood=1,handy=1,axey=1},
|
||||||
1.5,
|
1.5,
|
||||||
"A wooden button is a redstone component made out of wood which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1.5 seconds. It can only be placed on solid opaque full cubes (like cobblestone).")
|
true,
|
||||||
|
"A wooden button is a redstone component made out of wood which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1.5 seconds. It can only be placed on solid opaque full cubes (like cobblestone). Wooden buttons may also be pushed by arrows.")
|
||||||
|
|
||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
type = "fuel",
|
type = "fuel",
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
-- Time in seconds after which a stuck arrow is deleted
|
||||||
|
local ARROW_TIMEOUT = 60
|
||||||
|
|
||||||
local mod_mcl_hunger = minetest.get_modpath("mcl_hunger")
|
local mod_mcl_hunger = minetest.get_modpath("mcl_hunger")
|
||||||
local mod_awards = minetest.get_modpath("awards") and minetest.get_modpath("mcl_achievements")
|
local mod_awards = minetest.get_modpath("awards") and minetest.get_modpath("mcl_achievements")
|
||||||
|
|
||||||
|
@ -43,25 +46,60 @@ minetest.register_node("mcl_bows:arrow_box", {
|
||||||
groups = {not_in_creative_inventory=1},
|
groups = {not_in_creative_inventory=1},
|
||||||
})
|
})
|
||||||
|
|
||||||
local THROWING_ARROW_ENTITY={
|
-- FIXME: Arrow velocity is a bit strange. If the arrow flies VERY long, the acceleration can cause the velocity to become negative
|
||||||
physical = false,
|
-- and the arrow flies backwards.
|
||||||
|
local ARROW_ENTITY={
|
||||||
|
physical = true,
|
||||||
visual = "wielditem",
|
visual = "wielditem",
|
||||||
visual_size = {x=0.4, y=0.4},
|
visual_size = {x=0.4, y=0.4},
|
||||||
textures = {"mcl_bows:arrow_box"},
|
textures = {"mcl_bows:arrow_box"},
|
||||||
collisionbox = {0,0,0,0,0,0},
|
collisionbox = {-0.1, -0.1, -0.1, 0.1, 0.1, 0.1},
|
||||||
|
collide_with_objects = false,
|
||||||
|
|
||||||
_lastpos={},
|
_lastpos={},
|
||||||
_startpos=nil,
|
_startpos=nil,
|
||||||
_damage=1, -- Damage on impact
|
_damage=1, -- Damage on impact
|
||||||
|
_stuck=false, -- Whether arrow is stuck
|
||||||
|
_stucktimer=nil,-- Amount of time (in seconds) the arrow has been stuck so far
|
||||||
_shooter=nil, -- ObjectRef of player or mob who shot it
|
_shooter=nil, -- ObjectRef of player or mob who shot it
|
||||||
}
|
}
|
||||||
|
|
||||||
THROWING_ARROW_ENTITY.on_step = function(self, dtime)
|
ARROW_ENTITY.on_step = function(self, dtime)
|
||||||
local pos = self.object:getpos()
|
local pos = self.object:getpos()
|
||||||
local node = minetest.get_node(pos)
|
local dpos = table.copy(pos) -- digital pos
|
||||||
|
dpos = vector.round(dpos)
|
||||||
|
local node = minetest.get_node(dpos)
|
||||||
|
|
||||||
|
if self._stuck then
|
||||||
|
self._stucktimer = self._stucktimer + dtime
|
||||||
|
if self._stucktimer > ARROW_TIMEOUT then
|
||||||
|
self.object:remove()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local objects = minetest.get_objects_inside_radius(pos, 2)
|
||||||
|
for _,obj in ipairs(objects) do
|
||||||
|
if obj:is_player() then
|
||||||
|
if not minetest.settings:get_bool("creative_mode") then
|
||||||
|
-- Pickup arrow if player is nearby
|
||||||
|
if obj:get_inventory():room_for_item("main", "mcl_bows:arrow") then
|
||||||
|
obj:get_inventory():add_item("main", "mcl_bows:arrow")
|
||||||
|
minetest.sound_play("item_drop_pickup", {
|
||||||
|
pos = pos,
|
||||||
|
max_hear_distance = 16,
|
||||||
|
gain = 1.0,
|
||||||
|
})
|
||||||
|
self.object:remove()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self.object:remove()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Check for object collision. Done every tick (hopefully this is not too stressing)
|
-- Check for object collision. Done every tick (hopefully this is not too stressing)
|
||||||
do
|
else
|
||||||
local objs = minetest.get_objects_inside_radius(pos, 2)
|
local objs = minetest.get_objects_inside_radius(pos, 2)
|
||||||
local closest_object
|
local closest_object
|
||||||
local closest_distance
|
local closest_distance
|
||||||
|
@ -123,18 +161,27 @@ THROWING_ARROW_ENTITY.on_step = function(self, dtime)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self.object:remove()
|
self.object:remove()
|
||||||
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check for node collision
|
-- Check for node collision
|
||||||
if self._lastpos.x~=nil then
|
-- FIXME: Also collides with ignore
|
||||||
|
if self._lastpos.x~=nil and not self._stuck then
|
||||||
local def = minetest.registered_nodes[node.name]
|
local def = minetest.registered_nodes[node.name]
|
||||||
if (def and def.walkable) or not def then
|
local vel = self.object:get_velocity()
|
||||||
if not minetest.settings:get_bool("creative_mode") then
|
-- Arrow has stopped
|
||||||
minetest.add_item(self._lastpos, 'mcl_bows:arrow')
|
if (math.abs(vel.x) < 0.0001) or (math.abs(vel.z) < 0.0001) or (math.abs(vel.y) < 0.00001) then
|
||||||
|
-- Arrow is stuck and no longer moves
|
||||||
|
self._stuck = true
|
||||||
|
self._stucktimer = 0
|
||||||
|
self.object:set_velocity({x=0, y=0, z=0})
|
||||||
|
self.object:set_acceleration({x=0, y=0, z=0})
|
||||||
|
-- Push the button
|
||||||
|
if minetest.get_modpath("mesecons_button") and minetest.get_item_group(node.name, "button") > 0 and minetest.get_item_group(node.name, "button_push_by_arrow") == 1 then
|
||||||
|
mesecon.push_button(dpos, node)
|
||||||
end
|
end
|
||||||
self.object:remove()
|
|
||||||
elseif (def and def.liquidtype ~= "none") then
|
elseif (def and def.liquidtype ~= "none") then
|
||||||
-- Slow down arrow in liquids
|
-- Slow down arrow in liquids
|
||||||
local v = def.liquid_viscosity
|
local v = def.liquid_viscosity
|
||||||
|
@ -142,7 +189,6 @@ THROWING_ARROW_ENTITY.on_step = function(self, dtime)
|
||||||
v = 0
|
v = 0
|
||||||
end
|
end
|
||||||
local vpenalty = math.max(0.1, 0.98 - 0.1 * v)
|
local vpenalty = math.max(0.1, 0.98 - 0.1 * v)
|
||||||
local vel = self.object:get_velocity()
|
|
||||||
if math.abs(vel.x) > 0.001 then
|
if math.abs(vel.x) > 0.001 then
|
||||||
vel.x = vel.x * vpenalty
|
vel.x = vel.x * vpenalty
|
||||||
end
|
end
|
||||||
|
@ -157,7 +203,38 @@ THROWING_ARROW_ENTITY.on_step = function(self, dtime)
|
||||||
self._lastpos={x=pos.x, y=pos.y, z=pos.z}
|
self._lastpos={x=pos.x, y=pos.y, z=pos.z}
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_entity("mcl_bows:arrow_entity", THROWING_ARROW_ENTITY)
|
ARROW_ENTITY.get_staticdata = function(self)
|
||||||
|
local out = {
|
||||||
|
lastpos = self._lastpos,
|
||||||
|
startpos = self._startpos,
|
||||||
|
damage = self._damage,
|
||||||
|
stuck = self._stuck,
|
||||||
|
stucktimer = self._stucktimer,
|
||||||
|
}
|
||||||
|
if self._shooter and self._shooter:is_player() then
|
||||||
|
out.shootername = self._shooter:get_player_name()
|
||||||
|
end
|
||||||
|
return minetest.serialize(out)
|
||||||
|
end
|
||||||
|
|
||||||
|
ARROW_ENTITY.on_activate = function(self, staticdata, dtime_s)
|
||||||
|
local data = minetest.deserialize(staticdata)
|
||||||
|
if data then
|
||||||
|
self._lastpos = data.lastpos
|
||||||
|
self._startpos = data.startpos
|
||||||
|
self._damage = data.damage
|
||||||
|
self._stuck = data.stuck
|
||||||
|
self._stucktimer = data.stucktimer
|
||||||
|
if data.shootername then
|
||||||
|
local shooter = minetest.get_player_by_name(data.shootername)
|
||||||
|
if shooter and shooter:is_player() then
|
||||||
|
self._shooter = shooter
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_entity("mcl_bows:arrow_entity", ARROW_ENTITY)
|
||||||
|
|
||||||
if minetest.get_modpath("mcl_core") and minetest.get_modpath("mcl_mobitems") then
|
if minetest.get_modpath("mcl_core") and minetest.get_modpath("mcl_mobitems") then
|
||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
|
|
|
@ -6,3 +6,4 @@ mcl_core?
|
||||||
mcl_mobitems?
|
mcl_mobitems?
|
||||||
mcl_playerphysics?
|
mcl_playerphysics?
|
||||||
doc?
|
doc?
|
||||||
|
mesecons_button?
|
||||||
|
|
Loading…
Reference in New Issue