From e1feec9a3027e5e57ada570da7352da8ccf6f9fe Mon Sep 17 00:00:00 2001 From: epCode <64379263+epCode@users.noreply.github.com> Date: Mon, 6 Jun 2022 13:42:24 -0700 Subject: [PATCH 1/5] Add Raytracing arrows --- mods/ITEMS/mcl_bows/arrow.lua | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/mods/ITEMS/mcl_bows/arrow.lua b/mods/ITEMS/mcl_bows/arrow.lua index 1816184bb..b15e20a7d 100644 --- a/mods/ITEMS/mcl_bows/arrow.lua +++ b/mods/ITEMS/mcl_bows/arrow.lua @@ -188,7 +188,8 @@ function ARROW_ENTITY.on_step(self, dtime) -- The radius of 3 is fairly liberal, but anything lower than than will cause -- arrow to hilariously go through mobs often. -- TODO: Implement an ACTUAL collision detection (engine support needed). - local objs = minetest.get_objects_inside_radius(pos, 1.5) + + local closest_object local closest_distance @@ -196,32 +197,26 @@ function ARROW_ENTITY.on_step(self, dtime) self._deflection_cooloff = self._deflection_cooloff - dtime end - -- Iterate through all objects and remember the closest attackable object - for k, obj in pairs(objs) do - local ok = false - -- Arrows can only damage players and mobs - if obj:is_player() then - ok = true - elseif obj:get_luaentity() then - if (obj:get_luaentity().is_mob or obj:get_luaentity()._hittable_by_projectile) then + local arrow_dir = vector.rotate(vector.new(0,0,1), self.object:get_rotation()) + local raycast = minetest.raycast(pos, vector.add(pos, vector.multiply(arrow_dir, 6)), true, false) + for hitpoint in raycast do + if hitpoint.type == "object" and hitpoint.ref ~= self._shooter then + local ok = false + if hitpoint.ref:is_player() then ok = true + elseif hitpoint.ref:get_luaentity() then + if (hitpoint.ref:get_luaentity().is_mob or hitpoint.ref:get_luaentity()._hittable_by_projectile) then + ok = true + end end - end - - if ok then - local dist = vector.distance(pos, obj:get_pos()) - if not closest_object or not closest_distance then - closest_object = obj - closest_distance = dist - elseif dist < closest_distance then - closest_object = obj + if ok then + local dist = vector.distance(hitpoint.ref:get_pos(), pos) + closest_object = hitpoint.ref closest_distance = dist end end end - -- If an attackable object was found, we will damage the closest one only - if closest_object then local obj = closest_object local is_player = obj:is_player() From f2c2f4106bf10a035ca647664387a89feb62145d Mon Sep 17 00:00:00 2001 From: epCode <64379263+epCode@users.noreply.github.com> Date: Mon, 6 Jun 2022 13:55:28 -0700 Subject: [PATCH 2/5] fix arrows not disapearing after mob hit, and self damaging --- mods/ITEMS/mcl_bows/arrow.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_bows/arrow.lua b/mods/ITEMS/mcl_bows/arrow.lua index b15e20a7d..d0af738a1 100644 --- a/mods/ITEMS/mcl_bows/arrow.lua +++ b/mods/ITEMS/mcl_bows/arrow.lua @@ -200,7 +200,7 @@ function ARROW_ENTITY.on_step(self, dtime) local arrow_dir = vector.rotate(vector.new(0,0,1), self.object:get_rotation()) local raycast = minetest.raycast(pos, vector.add(pos, vector.multiply(arrow_dir, 6)), true, false) for hitpoint in raycast do - if hitpoint.type == "object" and hitpoint.ref ~= self._shooter then + if hitpoint.type == "object" then local ok = false if hitpoint.ref:is_player() then ok = true @@ -299,6 +299,8 @@ function ARROW_ENTITY.on_step(self, dtime) minetest.after(150, function() self.object:remove() end) + else + self.object:remove() end end end From fdb7d5bfadc80cc3a9fe77b138d3e831cafa50b3 Mon Sep 17 00:00:00 2001 From: epCode <64379263+epCode@users.noreply.github.com> Date: Mon, 6 Jun 2022 14:32:07 -0700 Subject: [PATCH 3/5] fixed Badly calculated arrow direction --- mods/ITEMS/mcl_bows/arrow.lua | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/mods/ITEMS/mcl_bows/arrow.lua b/mods/ITEMS/mcl_bows/arrow.lua index d0af738a1..cd32f5392 100644 --- a/mods/ITEMS/mcl_bows/arrow.lua +++ b/mods/ITEMS/mcl_bows/arrow.lua @@ -197,8 +197,8 @@ function ARROW_ENTITY.on_step(self, dtime) self._deflection_cooloff = self._deflection_cooloff - dtime end - local arrow_dir = vector.rotate(vector.new(0,0,1), self.object:get_rotation()) - local raycast = minetest.raycast(pos, vector.add(pos, vector.multiply(arrow_dir, 6)), true, false) + local arrow_dir = self.object:get_velocity() + local raycast = minetest.raycast(pos, vector.add(pos, vector.multiply(arrow_dir, 0.2)), true, false) for hitpoint in raycast do if hitpoint.type == "object" then local ok = false @@ -211,8 +211,13 @@ function ARROW_ENTITY.on_step(self, dtime) end if ok then local dist = vector.distance(hitpoint.ref:get_pos(), pos) - closest_object = hitpoint.ref - closest_distance = dist + if not closest_object or not closest_distance then + closest_object = hitpoint.ref + closest_distance = dist + elseif dist < closest_distance then + closest_object = hitpoint.ref + closest_distance = dist + end end end end From 78940e109c82ad5e93abc180da9cd14cd7924f13 Mon Sep 17 00:00:00 2001 From: epCode <64379263+epCode@users.noreply.github.com> Date: Mon, 6 Jun 2022 14:38:18 -0700 Subject: [PATCH 4/5] fix critical hit displaying in the wrong place --- mods/ITEMS/mcl_bows/arrow.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/ITEMS/mcl_bows/arrow.lua b/mods/ITEMS/mcl_bows/arrow.lua index cd32f5392..fb5874982 100644 --- a/mods/ITEMS/mcl_bows/arrow.lua +++ b/mods/ITEMS/mcl_bows/arrow.lua @@ -198,7 +198,7 @@ function ARROW_ENTITY.on_step(self, dtime) end local arrow_dir = self.object:get_velocity() - local raycast = minetest.raycast(pos, vector.add(pos, vector.multiply(arrow_dir, 0.2)), true, false) + local raycast = minetest.raycast(pos, vector.add(pos, vector.multiply(arrow_dir, 0.1)), true, false) for hitpoint in raycast do if hitpoint.type == "object" then local ok = false @@ -249,7 +249,7 @@ function ARROW_ENTITY.on_step(self, dtime) -- Punch target object but avoid hurting enderman. if not lua or lua.name ~= "mobs_mc:enderman" then if not self._in_player then - damage_particles(self.object:get_pos(), self._is_critical) + damage_particles(vector.add(pos, vector.multiply(self.object:get_velocity(), 0.1)), self._is_critical) end if mcl_burning.is_burning(self.object) then mcl_burning.set_on_fire(obj, 5) From 6c804f44d55b7e2f4efc07949807ab26b51a61f6 Mon Sep 17 00:00:00 2001 From: epCode <64379263+epCode@users.noreply.github.com> Date: Mon, 6 Jun 2022 18:43:50 -0700 Subject: [PATCH 5/5] add a small bit of doc --- mods/ITEMS/mcl_bows/arrow.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mods/ITEMS/mcl_bows/arrow.lua b/mods/ITEMS/mcl_bows/arrow.lua index fb5874982..8edf75011 100644 --- a/mods/ITEMS/mcl_bows/arrow.lua +++ b/mods/ITEMS/mcl_bows/arrow.lua @@ -198,9 +198,11 @@ function ARROW_ENTITY.on_step(self, dtime) end local arrow_dir = self.object:get_velocity() + --create a raycast from the arrow based on the velocity of the arrow to deal with lag local raycast = minetest.raycast(pos, vector.add(pos, vector.multiply(arrow_dir, 0.1)), true, false) for hitpoint in raycast do if hitpoint.type == "object" then + -- find the closest object that is in the way of the arrow local ok = false if hitpoint.ref:is_player() then ok = true