Merge branch 'stuck_arrow' of http://repo.or.cz/MineClone/MineClone2 into stuck_arrow

This commit is contained in:
Wuzzy 2018-05-09 00:06:29 +02:00
commit 76356ed1e5
3 changed files with 137 additions and 20 deletions

View file

@ -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",

View file

@ -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({

View file

@ -6,3 +6,4 @@ mcl_core?
mcl_mobitems?
mcl_playerphysics?
doc?
mesecons_button?