minetest-mm/mods/bows/arrow.lua

158 lines
3.1 KiB
Lua
Raw Normal View History

2020-10-26 17:38:53 +01:00
2024-12-19 12:55:40 +01:00
local math_random = math.random
2020-10-26 17:38:53 +01:00
2024-12-19 12:55:40 +01:00
-- helper to remove or maybe drop arrow item
2020-10-26 17:38:53 +01:00
2024-12-19 12:55:40 +01:00
local function on_hit_remove(self)
2020-10-26 17:38:53 +01:00
minetest.sound_play(
2024-12-19 12:55:40 +01:00
bows.registered_arrows[self.name].on_hit_sound, {
2020-10-26 17:38:53 +01:00
pos = self.object:get_pos(),
gain = 1.0,
2024-12-19 12:55:40 +01:00
max_hear_distance = 12
}, true)
2020-10-26 17:38:53 +01:00
-- chance of dropping arrow
2024-12-19 12:55:40 +01:00
local chance = minetest.registered_items[self.name].drop_chance or 10
local pos = self.object:get_pos()
if pos and math_random(chance) == 1 then
pos.y = pos.y + 0.5
2020-10-26 17:38:53 +01:00
2024-12-19 12:55:40 +01:00
minetest.add_item(pos, self.name)
2020-10-26 17:38:53 +01:00
end
self.object:remove()
return self
end
2024-12-19 12:55:40 +01:00
-- when arrow hits an entity
2020-10-26 17:38:53 +01:00
2024-12-19 12:55:40 +01:00
local function on_hit_object(self, target, hp, user, lastpos)
2020-10-26 17:38:53 +01:00
2024-12-19 12:55:40 +01:00
target:punch(user, 1.0, {
--full_punch_interval = 1.0,
2020-10-26 17:38:53 +01:00
damage_groups = {fleshy = hp},
}, nil)
2024-12-19 12:55:40 +01:00
if bows.registered_arrows[self.name].on_hit_object then
2020-10-26 17:38:53 +01:00
2024-12-19 12:55:40 +01:00
bows.registered_arrows[self.name].on_hit_object(
self, target, hp, user, lastpos)
2020-10-26 17:38:53 +01:00
end
on_hit_remove(self)
return self
end
2024-12-19 12:55:40 +01:00
-- arrow entity
2020-10-26 17:38:53 +01:00
minetest.register_entity("bows:arrow",{
2024-12-19 12:55:40 +01:00
initial_properties = {
hp_max = 10,
visual = "wielditem",
visual_size = {x = .20, y = .20},
collisionbox = {-0.1, -0.1, -0.1, 0.1, 0.1, 0.1},
physical = false,
textures = {"air"}
},
2020-10-26 17:38:53 +01:00
_is_arrow = true,
timer = 10,
on_activate = function(self, staticdata)
if not self then
2024-12-19 12:55:40 +01:00
self.object:remove() ; return
2020-10-26 17:38:53 +01:00
end
if bows.tmp and bows.tmp.arrow ~= nil then
self.arrow = bows.tmp.arrow
self.user = bows.tmp.user
self.name = bows.tmp.name
2024-12-19 12:55:40 +01:00
self.dmg = bows.registered_arrows[self.name].damage
2020-10-26 17:38:53 +01:00
bows.tmp = nil
self.object:set_properties({textures = {self.arrow}})
else
self.object:remove()
end
end,
on_step = function(self, dtime, ...)
self.timer = self.timer - dtime
if self.timer < 0 then
2024-12-19 12:55:40 +01:00
self.object:remove() ; return
2020-10-26 17:38:53 +01:00
end
2024-12-19 12:55:40 +01:00
local pos = self.object:get_pos() ; self.oldpos = self.oldpos or pos
local cast = minetest.raycast(self.oldpos, pos, true, true)
local thing = cast:next()
local ok = true
2020-10-26 17:38:53 +01:00
2024-12-19 12:55:40 +01:00
-- loop through things
while thing do
2020-10-26 17:38:53 +01:00
2024-12-19 12:55:40 +01:00
-- ignore the object that is the arrow
if thing.type == "object" and thing.ref ~= self.object then
2020-10-26 17:38:53 +01:00
2024-12-19 12:55:40 +01:00
-- add entity name to thing table (if not player)
if not thing.ref:is_player() then
thing.name = thing.ref:get_luaentity() and thing.ref:get_luaentity().name
2020-10-26 17:38:53 +01:00
end
2024-12-19 12:55:40 +01:00
-- check if dropped item or yourself
if thing.name == "__builtin:item"
or (not thing.name
and thing.ref:get_player_name() == self.user:get_player_name()) then
ok = false
end
2020-10-26 17:38:53 +01:00
2024-12-19 12:55:40 +01:00
-- can we hit entity ?
if ok then
2020-10-26 17:38:53 +01:00
2024-12-19 12:55:40 +01:00
--print("-- hit entity", thing.name)
2020-10-26 17:38:53 +01:00
2024-12-19 12:55:40 +01:00
on_hit_object(self, thing.ref, self.dmg, self.user, pos)
2020-10-26 17:38:53 +01:00
return self
end
2024-12-19 12:55:40 +01:00
-- are we inside a node ?
elseif thing.type == "node" then
2020-10-26 17:38:53 +01:00
2024-12-19 12:55:40 +01:00
self.node = minetest.get_node(pos)
2020-10-26 17:38:53 +01:00
2024-12-19 12:55:40 +01:00
local def = minetest.registered_nodes[self.node.name]
2020-10-26 17:38:53 +01:00
2024-12-19 12:55:40 +01:00
if def and def.walkable then
2020-10-26 17:38:53 +01:00
2024-12-19 12:55:40 +01:00
--print("-- hit node", self.node.name)
2020-10-26 17:38:53 +01:00
2024-12-19 12:55:40 +01:00
if bows.registered_arrows[self.name].on_hit_node then
2020-10-26 17:38:53 +01:00
2024-12-19 12:55:40 +01:00
bows.registered_arrows[self.name].on_hit_node(
self, pos, self.user, self.oldpos)
end
2020-10-26 17:38:53 +01:00
2024-12-19 12:55:40 +01:00
on_hit_remove(self)
2020-10-26 17:38:53 +01:00
2024-12-19 12:55:40 +01:00
return self
end
end
thing = cast:next()
2020-10-26 17:38:53 +01:00
end
2024-12-19 12:55:40 +01:00
self.oldpos = pos
end
2020-10-26 17:38:53 +01:00
})