123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- -- Localise functions
- local floor, min, max = math.floor, math.min, math.max
- --Should we use new collisionbox detection
- local colbox = false
- local radius = colbox and 3.0 or 1.0
- --= Functions inspired from Kaeza's Firearms mod
- local function minmax(x, y)
- return min(x, y), max(x, y)
- end
- local function pos_in_box(p, b1, b2)
- local xmin, xmax = minmax(b1.x, b2.x)
- local ymin, ymax = minmax(b1.y, b2.y)
- local zmin, zmax = minmax(b1.z, b2.z)
- return p.x >= xmin and p.x <= xmax
- and p.y >= ymin and p.y <= ymax
- and p.z >= zmin and p.z <= zmax
- end
- local function get_obj_box(obj)
- local box
- if obj:is_player() then
- box = {-.5, -.5, -.5, .5, 1.5, .5}
- else
- box = obj:get_luaentity().collisionbox
- or {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}
- end
- local p = obj:get_pos()
- local x1, y1, z1, x2, y2, z2 = unpack(box)
- return {x = x1 + p.x, y = y1 + p.y, z = z1 + p.z},
- {x = x2 + p.x, y = y2 + p.y, z = z2 + p.z}
- end
- --= END (Thanks Kaeza :)
- local on_hit_remove = function(self)
- minetest.sound_play(
- bows.registed_arrows[self.name].on_hit_sound, {
- pos = self.object:get_pos(),
- gain = 1.0,
- max_hear_distance = 7
- })
- -- chance of dropping arrow
- local chance = minetest.registered_items[self.name].drop_chance
- if math.random(chance) == 1 then
- minetest.add_item(self.object:get_pos(), self.name)
- end
- self.object:remove()
- return self
- end
- local on_hit_object = function(self, target, hp, user, lastpos)
- target:punch(user, 0.1, {
- full_punch_interval = 0.1,
- damage_groups = {fleshy = hp},
- }, nil)
- if bows.registed_arrows[self.name].on_hit_object then
- bows.registed_arrows[self.name].on_hit_object(
- self, target, hp, user, lastpos)
- end
- on_hit_remove(self)
- return self
- end
- minetest.register_entity("bows:arrow",{
- hp_max = 10,
- visual = "wielditem",
- visual_size = {x = .20, y = .20},
- collisionbox = {0,0,0,0,0,0},
- physical = true,
- textures = {"air"},
- _is_arrow = true,
- timer = 10,
- oldvel = {x = 0, y = 0, z = 0},
- on_activate = function(self, staticdata)
- if not self then
- self.object:remove()
- return
- 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
- self.dmg = bows.registed_arrows[self.name].damage
- 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
- self.object:remove()
- return
- end
- local what_is, what_obj, ent
- for i, ob in pairs(minetest.get_objects_inside_radius(
- self.object:get_pos(), radius)) do
- what_obj = nil
- what_is = ""
- -- player
- if ob
- and bows.pvp
- and ob:is_player()
- and ob:get_player_name() ~= self.user:get_player_name() then
- what_obj = ob
- what_is = "player"
- end
- -- entity/mob
- if ob and not what_obj then
- ent = ob:get_luaentity()
- if ent
- and ent.physical
- and not ent._is_arrow
- and ent.name ~= "__builtin:item" then
- what_obj = ob
- what_is = "entity"
- end
- end
- if what_obj then
- if colbox then
- -- Object specific collision detection
- local p1, p2 = get_obj_box(what_obj)
- if pos_in_box(self.object:get_pos(), p1, p2) then
- on_hit_object(self, what_obj, self.dmg, self.user,
- self.object:get_pos())
- return self
- end
- else
- on_hit_object(self, what_obj, self.dmg, self.user,
- self.object:get_pos())
- return self
- end
- end
- end
- local vel = self.object:get_velocity()
- if vel.x == 0 or vel.y == 0 or vel.z == 0 then
- if bows.registed_arrows[self.name].on_hit_node then
- local pos = self.object:get_pos()
- local lastpos = {x = pos.x, y = pos.y, z = pos.z}
- pos.x = pos.x + (self.oldvel.x / 100)
- pos.y = pos.y + (self.oldvel.y / 100)
- pos.z = pos.z + (self.oldvel.z / 100)
- self.node = minetest.get_node(pos)
- bows.registed_arrows[self.name].on_hit_node(
- self, pos, self.user, lastpos)
- end
- on_hit_remove(self)
- return self
- end
- self.oldvel = vel
- end,
- })
|