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 },
|
||||
}
|
||||
|
||||
-- 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)
|
||||
if pointed_thing.type ~= "node" then
|
||||
-- no interaction possible with entities
|
||||
|
@ -66,7 +80,7 @@ end
|
|||
|
||||
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)
|
||||
groups_off.attached_node=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.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", {
|
||||
drawtype = "nodebox",
|
||||
tiles = {texture},
|
||||
|
@ -98,17 +117,16 @@ mesecon.register_button = function(basename, description, texture, recipeitem, s
|
|||
on_place = on_button_place,
|
||||
node_placement_prediction = "",
|
||||
on_rightclick = function (pos, node)
|
||||
minetest.set_node(pos, {name="mesecons_button: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(button_timer)
|
||||
mesecon.push_button(pos, node)
|
||||
end,
|
||||
sounds = sounds,
|
||||
mesecons = {receptor = {
|
||||
state = mesecon.state.off,
|
||||
rules = button_get_output_rules,
|
||||
}},
|
||||
_mcl_button_basename = basename,
|
||||
_mcl_button_timer = button_timer,
|
||||
|
||||
_mcl_blast_resistance = 2.5,
|
||||
_mcl_hardness = 0.5,
|
||||
})
|
||||
|
@ -134,14 +152,33 @@ mesecon.register_button = function(basename, description, texture, recipeitem, s
|
|||
state = mesecon.state.on,
|
||||
rules = button_get_output_rules
|
||||
}},
|
||||
_mcl_button_basename = basename,
|
||||
_mcl_button_timer = button_timer,
|
||||
on_timer = function(pos, elapsed)
|
||||
local node = minetest.get_node(pos)
|
||||
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.sound_play("mesecons_button_pop", {pos=pos})
|
||||
mesecon.receptor_off(pos, button_get_output_rules(node))
|
||||
end
|
||||
end,
|
||||
|
||||
_mcl_blast_resistance = 2.5,
|
||||
_mcl_hardness = 0.5,
|
||||
})
|
||||
|
@ -160,6 +197,7 @@ mesecon.register_button(
|
|||
mcl_sounds.node_sound_stone_defaults(),
|
||||
{material_stone=1,handy=1,pickaxey=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).")
|
||||
|
||||
local woods = {
|
||||
|
@ -180,7 +218,8 @@ for w=1, #woods do
|
|||
mcl_sounds.node_sound_wood_defaults(),
|
||||
{material_wood=1,handy=1,axey=1},
|
||||
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({
|
||||
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_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},
|
||||
})
|
||||
|
||||
local THROWING_ARROW_ENTITY={
|
||||
physical = false,
|
||||
-- FIXME: Arrow velocity is a bit strange. If the arrow flies VERY long, the acceleration can cause the velocity to become negative
|
||||
-- and the arrow flies backwards.
|
||||
local ARROW_ENTITY={
|
||||
physical = true,
|
||||
visual = "wielditem",
|
||||
visual_size = {x=0.4, y=0.4},
|
||||
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={},
|
||||
_startpos=nil,
|
||||
_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
|
||||
}
|
||||
|
||||
THROWING_ARROW_ENTITY.on_step = function(self, dtime)
|
||||
ARROW_ENTITY.on_step = function(self, dtime)
|
||||
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)
|
||||
do
|
||||
else
|
||||
local objs = minetest.get_objects_inside_radius(pos, 2)
|
||||
local closest_object
|
||||
local closest_distance
|
||||
|
@ -123,18 +161,27 @@ THROWING_ARROW_ENTITY.on_step = function(self, dtime)
|
|||
end
|
||||
end
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- 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]
|
||||
if (def and def.walkable) or not def then
|
||||
if not minetest.settings:get_bool("creative_mode") then
|
||||
minetest.add_item(self._lastpos, 'mcl_bows:arrow')
|
||||
local vel = self.object:get_velocity()
|
||||
-- Arrow has stopped
|
||||
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
|
||||
self.object:remove()
|
||||
elseif (def and def.liquidtype ~= "none") then
|
||||
-- Slow down arrow in liquids
|
||||
local v = def.liquid_viscosity
|
||||
|
@ -142,7 +189,6 @@ THROWING_ARROW_ENTITY.on_step = function(self, dtime)
|
|||
v = 0
|
||||
end
|
||||
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
|
||||
vel.x = vel.x * vpenalty
|
||||
end
|
||||
|
@ -157,7 +203,38 @@ THROWING_ARROW_ENTITY.on_step = function(self, dtime)
|
|||
self._lastpos={x=pos.x, y=pos.y, z=pos.z}
|
||||
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
|
||||
minetest.register_craft({
|
||||
|
|
|
@ -6,3 +6,4 @@ mcl_core?
|
|||
mcl_mobitems?
|
||||
mcl_playerphysics?
|
||||
doc?
|
||||
mesecons_button?
|
||||
|
|
Loading…
Reference in New Issue