diff --git a/mods/ENTITIES/mcl_mobs/combat.lua b/mods/ENTITIES/mcl_mobs/combat.lua index 608209ee2..2bb19fb34 100644 --- a/mods/ENTITIES/mcl_mobs/combat.lua +++ b/mods/ENTITIES/mcl_mobs/combat.lua @@ -1236,13 +1236,14 @@ function mob_class:do_states_attack (dtime) minetest.after(1, function() self.firing = false end) - arrow = minetest.add_entity(p, self.arrow) + + arrow = vl_projectile.create(self.arrow, { + pos = p, + owner = self, + }) ent = arrow:get_luaentity() - if ent.velocity then - v = ent.velocity - end ent.switch = 1 - ent.owner_id = tostring(self.object) -- add unique owner id to arrow + v = ent.velocity or 1 -- important for mcl_shields ent._shooter = self.object @@ -1252,12 +1253,10 @@ function mob_class:do_states_attack (dtime) end end - local amount = (vec.x * vec.x + vec.y * vec.y + vec.z * vec.z) ^ 0.5 -- offset makes shoot aim accurate - vec.y = vec.y + self.shoot_offset - vec.x = vec.x * (v / amount) - vec.y = vec.y * (v / amount) - vec.z = vec.z * (v / amount) + local amount = vector.length(vec) + vec = vector.multiply(vec, v / vector.length(vec)) + if self.shoot_arrow then vec = vector.normalize(vec) self:shoot_arrow(p, vec) diff --git a/mods/ENTITIES/mcl_mobs/init.lua b/mods/ENTITIES/mcl_mobs/init.lua index d8f8491d5..d5f0b71d5 100644 --- a/mods/ENTITIES/mcl_mobs/init.lua +++ b/mods/ENTITIES/mcl_mobs/init.lua @@ -386,8 +386,15 @@ function mcl_mobs.register_arrow(name, def) if not name or not def then return end -- errorcheck - minetest.register_entity(name, { + local behaviors = {} + if def.hit_node then + table.insert(behaviors, vl_projectile.collides_with_solids) + end + if def.hit_player or def.hit_mob or def.hit_object then + table.insert(behaviors, vl_projectile.collides_with_entities) + end + vl_projectile.register(name, { physical = false, visual = def.visual, visual_size = def.visual_size, @@ -405,6 +412,53 @@ function mcl_mobs.register_arrow(name, def) _lifetime = def._lifetime or 7, owner_id = def.owner_id, rotate = def.rotate, + _vl_projectile = { + behaviors = behaviors, + ignore_gravity = true, + damages_players = true, + allow_punching = function(self, entity_def, projectile_def, object) + if self._owner and object == self._owner.object then return false end + return true + end, + on_collide_with_solid = function(self, pos, node, nodedef) + if nodedef or not nodedef.walkable then return end + + self.hit_node(self, pos, node) + if self.drop == true then + pos.y = pos.y + 1 + self.lastpos = self.lastpos or pos + + minetest.add_item(self.lastpos, self.object:get_luaentity().name) + end + + self._removed = true + self.object:remove(); + end, + on_collide_with_entity = function(self, pos, object) + if self.hit_player and object:is_player() then + self.hit_player(self, object) + self._removed = true + self.object:remove() + return + end + + local entity = object:get_luaentity() + if not entity or entity.name == self.object:get_luaentity().name then return end + if self.timer <= 2 then return end + + if self.hit_mob and entity.is_mob == true then + self.hit_mob(self, object) + self._removed = true + self.object:remove() + return + elseif self.hit_object then + self.hit_object(self, object) + self._removed = true + self.object:remove() + return + end + end + }, on_punch = def.on_punch or function(self, puncher, time_from_last_punch, tool_capabilities, dir, damage) local vel = self.object:get_velocity():length() self.object:set_velocity(dir * vel) @@ -417,25 +471,21 @@ function mcl_mobs.register_arrow(name, def) on_activate = def.on_activate, on_step = def.on_step or function(self, dtime) - - self.timer = self.timer + dtime + -- Projectile behavior processing + vl_projectile.update_projectile(self, dtime) local pos = self.object:get_pos() + if not pos then return end - if self.switch == 0 - or self.timer > self._lifetime - or not within_limits(pos, 0) then + if self.switch == 0 or self.timer > self._lifetime or not within_limits(pos, 0) then mcl_burning.extinguish(self.object) + self._removed = true self.object:remove(); - return end -- does arrow have a tail (fireball) - if def.tail - and def.tail == 1 - and def.tail_texture then - + if def.tail and def.tail == 1 and def.tail_texture then minetest.add_particle({ pos = pos, velocity = {x = 0, y = 0, z = 0}, @@ -448,29 +498,6 @@ function mcl_mobs.register_arrow(name, def) }) end - if self.hit_node then - - local node = node_ok(pos).name - - if minetest.registered_nodes[node].walkable then - - self.hit_node(self, pos, node) - - if self.drop == true then - - pos.y = pos.y + 1 - - self.lastpos = (self.lastpos or pos) - - minetest.add_item(self.lastpos, self.object:get_luaentity().name) - end - - self.object:remove(); - - return - end - end - if self.homing and self._target then local p = self._target:get_pos() if p then @@ -482,42 +509,6 @@ function mcl_mobs.register_arrow(name, def) end end - if self.hit_player or self.hit_mob or self.hit_object then - - for _,object in pairs(minetest.get_objects_inside_radius(pos, 1.5)) do - - if self.hit_player - and object:is_player() then - - self.hit_player(self, object) - self.object:remove(); - return - end - - local entity = object:get_luaentity() - - if entity - and self.hit_mob - and entity.is_mob == true - and (tostring(object) ~= self.owner_id or self.timer > 2) - and entity.name ~= self.object:get_luaentity().name then - self.hit_mob(self, object) - self.object:remove(); - return - end - - if entity - and self.hit_object - and (not entity.is_mob) - and (tostring(object) ~= self.owner_id or self.timer > 2) - and entity.name ~= self.object:get_luaentity().name then - self.hit_object(self, object) - self.object:remove(); - return - end - end - end - self.lastpos = pos end }) diff --git a/mods/ITEMS/vl_projectile/init.lua b/mods/ITEMS/vl_projectile/init.lua index 091394ab1..970c57c19 100644 --- a/mods/ITEMS/vl_projectile/init.lua +++ b/mods/ITEMS/vl_projectile/init.lua @@ -386,10 +386,11 @@ function mod.create(entity_id, options) end function mod.register(name, def) - assert(def._vl_projectile) + assert(def._vl_projectile, "vl_projectile.register() requires definition to define _vl_projectile") + assert(def._vl_projectile.behaviors, "vl_projectile.register() requires definition to define _vl_projectile.behaviors") local behaviors = def._vl_projectile.behaviors for i = 1,#behaviors do - assert(behaviors[i]) + assert(behaviors[i] and type(behaviors[i]) == "function", "def._vl_projectile.behaviors["..i.." is malformed") end if not def.on_step then