Split utils.lua in two

This commit is contained in:
marco_a 2024-03-18 22:10:57 +01:00
parent 1c46e62cd8
commit 12ea3900b2
3 changed files with 236 additions and 239 deletions

View File

@ -11,6 +11,7 @@ weapons_lib.mods = {}
dofile(srcpath .. "/api/bullets.lua")
dofile(srcpath .. "/api/mods.lua")
dofile(srcpath .. "/api/weapons.lua")
dofile(srcpath .. "/api/weapons_utils.lua")
dofile(srcpath .. "/player_manager.lua")
dofile(srcpath .. "/utils.lua")
dofile(srcpath .. "/HUD/hud_crosshair.lua")

234
src/api/weapons_utils.lua Normal file
View File

@ -0,0 +1,234 @@
local function cast_raycast() end
local function get_shooter_left_dir() end
local function get_shooter_up_dir() end
local function debug_particles() end
-- per bloccare fisica
local dummy = {
initial_properties = {
physical = true,
pointable = false,
collide_with_objects = false,
visual = "sprite",
visual_size = {x = 0, y = 0, z = 0},
textures = { "blank.png" }
},
-- quando sbuca, se non ha prole, cancellala
on_activate = function(self, staticdata, dtime_s)
minetest.after(0.1, function()
if #self.object:get_children() == 0 then
self.object:remove()
end
end)
end
}
minetest.register_entity("weapons_lib:dummy", dummy)
-- I cast a 2x2 grid (assisted aim) to prevent the 0.1 delay. The grid value is
-- actually hardcoded because:
-- 1. it works and I don't need more features from it
-- 2. I haven't got enough knowledge about vectors and rotations anyway
function weapons_lib.get_pointed_objects(shooter, range, has_piercing, entity_table)
local height, look_dir
if entity_table then
height = entity_table.height
look_dir = entity_table.dir
else
height = 1.475
look_dir = shooter:get_look_dir()
end
local hit_pointed_things = {}
local left_dir = get_shooter_left_dir(shooter)
local head_up_dir = get_shooter_up_dir(shooter, look_dir)
local center = shooter:get_pos() + look_dir + {x=0, y=height, z=0}
local grid_width = 0.25
local r_amount = 2
local x_step = (grid_width / r_amount) * (-left_dir)
local y_step = (grid_width / r_amount) * head_up_dir
local ray_pos = center + (x_step / r_amount) + (y_step / r_amount)
for row = 1, r_amount do
for column = 1, r_amount do
local pthings = cast_raycast(shooter, ray_pos, look_dir, range, has_piercing)
--debug_particles(look_dir, ray_pos, 30)
if pthings then
-- rimuovo giocator3 già colpit3 da altro raggio
for k, possible_target in pairs(pthings) do
local object = possible_target.object
local target_name = possible_target.object:get_player_name() or possible_target.object:get_luaentity().name
for _, target in pairs(hit_pointed_things) do
local hit_target_name = target.object:get_player_name() or target.object:get_luaentity().name
if target_name == hit_target_name then
pthings[k] = nil
break
end
end
end
table.insert_all(hit_pointed_things, pthings)
end
ray_pos = ray_pos - x_step
end
ray_pos = ray_pos - y_step
ray_pos = ray_pos + x_step * r_amount
end
return hit_pointed_things
end
----------------------------------------------
---------------FUNZIONI LOCALI----------------
----------------------------------------------
-- ritorna un array di giocatori con il numero di giocatori trovati a indice 1.
-- Se non trova giocatori diversi da se stesso ritorna nil
function cast_raycast(user, origin, dir, range, has_piercing)
local a = vector.add(origin, vector.multiply(dir, 0))
local b = vector.add(origin, vector.multiply(dir, range))
local ray = minetest.raycast(a, b)
local objects = {}
-- controllo su ogni cosa attraversata dal raycast (da a a b)
for hit in ray do
-- se è un oggetto
if hit.type == "object" then
-- se è un'entità
if not hit.ref:is_player() then
local entity = hit.ref:get_luaentity()
-- se collide con un proiettile, lo distrugge, sennò salva l'entità per il danno
if entity._is_bullet then
entity:_destroy()
else
table.insert(objects, {object=hit.ref, headshot=false})
end
-- se è un giocatore (e non chi spara)
elseif hit.ref ~= user then
if (hit.intersection_point.y - hit.ref:get_pos().y) > 1.275 then
table.insert(objects, {object=hit.ref, headshot=true})
else
table.insert(objects, {object=hit.ref, headshot=false})
end
end
local is_player = hit.ref:is_player()
local t_name = is_player and hit.ref:get_player_name() or hit.ref:get_luaentity().name
if not has_piercing then return objects end
else
-- se è un nodo mi fermo, e ritorno l'array se > 0 (ovvero ha trovato obiettivi)
if hit.type == "node" then
if #objects > 0 then
return has_piercing and objects or {objects[1]}
else
return
end
end
end
end
-- se ho sparato a un obiettivo senza incrociare blocchi
if #objects > 0 then
return has_piercing and objects or {objects[1]}
else
return
end
end
function get_shooter_left_dir(shooter)
local yaw = shooter:get_look_horizontal() or shooter:get_yaw()
local pl_left_dir = vector.new(math.cos(yaw), 0, math.sin(yaw))
return vector.normalize(pl_left_dir)
end
function get_shooter_up_dir(shooter, dir)
return vector.rotate_around_axis(dir, get_shooter_left_dir(shooter), math.pi/2)
end
function debug_particles(dir, origin, range)
minetest.add_particlespawner({
amount = 5,
time = 0.3,
pos = vector.new(origin),
vel = vector.multiply(dir, range),
size = 2,
texture = "bl_smg_trail.png"
})
end
------------------------------
-- not my code, don't know, don't ask
------------------------------
weapons_lib.grenade_explode = function(self)
local explosion_range = self._explosion_range
local explosion_damage = self._explosion_damage
local origin = self.object:get_pos()
local p_name = self._p_name
if origin == nil then return end
if origin.x == nil or origin.y == nil or origin.z == nil then return end
local objs = minetest.env:get_objects_inside_radius(origin, explosion_range)
local entities = {}
-- Se ho colpito qualcosa
if objs then
for _, obj in ipairs(objs) do
if obj:is_player() then
local p_pos = obj:get_pos()
local lenx = math.abs(p_pos.x - origin.x)
local leny = math.abs(p_pos.y - origin.y)
local lenz = math.abs(p_pos.z - origin.z)
local hypot = math.sqrt((lenx * lenx) + (lenz * lenz))
local dist = math.sqrt((hypot * hypot) + (leny * leny))
local damage = explosion_damage - (explosion_damage * dist / explosion_range)
local target_name = obj:get_player_name()
-- TODO: non funziona, la funzione è stata cambiata. Bisogna far passare l'arma
weapons_lib.apply_damage(minetest.get_player_by_name(p_name), {object = obj}, damage, 0, false)
elseif obj ~= self.object and obj:get_luaentity() then
table.insert(entities, obj:get_luaentity())
end
end
end
if #entities == 0 then return end
self.object:remove()
for _,entity in pairs(entities) do
if entity.initial_properties ~= nil then
if entity._is_bullet then
entity:_destroy()
end
end
end
end

View File

@ -1,245 +1,7 @@
local function cast_raycast() end
local function get_shooter_left_dir() end
local function get_shooter_up_dir() end
local function debug_particles() end
-- per bloccare fisica
local dummy = {
initial_properties = {
physical = true,
pointable = false,
collide_with_objects = false,
visual = "sprite",
visual_size = {x = 0, y = 0, z = 0},
textures = { "blank.png" }
},
-- quando sbuca, se non ha prole, cancellala
on_activate = function(self, staticdata, dtime_s)
minetest.after(0.1, function()
if #self.object:get_children() == 0 then
self.object:remove()
end
end)
end
}
minetest.register_entity("weapons_lib:dummy", dummy)
function weapons_lib.is_in_the_air(obj_ref)
local obj_pos = obj_ref:get_pos()
local node_beneath = vector.new(obj_pos.x, obj_pos.y - 0.4, obj_pos.z)
local is_in_the_air = minetest.get_node(node_beneath).name == "air"
return is_in_the_air
end
-- I cast a 2x2 grid (assisted aim) to prevent the 0.1 delay. The grid value is
-- actually hardcoded because:
-- 1. it works and I don't need more features from it
-- 2. I haven't got enough knowledge about vectors and rotations anyway
function weapons_lib.get_pointed_objects(shooter, range, has_piercing, entity_table)
local height, look_dir
if entity_table then
height = entity_table.height
look_dir = entity_table.dir
else
height = 1.475
look_dir = shooter:get_look_dir()
end
local hit_pointed_things = {}
local left_dir = get_shooter_left_dir(shooter)
local head_up_dir = get_shooter_up_dir(shooter, look_dir)
local center = shooter:get_pos() + look_dir + {x=0, y=height, z=0}
local grid_width = 0.25
local r_amount = 2
local x_step = (grid_width / r_amount) * (-left_dir)
local y_step = (grid_width / r_amount) * head_up_dir
local ray_pos = center + (x_step / r_amount) + (y_step / r_amount)
for row = 1, r_amount do
for column = 1, r_amount do
local pthings = cast_raycast(shooter, ray_pos, look_dir, range, has_piercing)
--debug_particles(look_dir, ray_pos, 30)
if pthings then
-- rimuovo giocator3 già colpit3 da altro raggio
for k, possible_target in pairs(pthings) do
local object = possible_target.object
local target_name = possible_target.object:get_player_name() or possible_target.object:get_luaentity().name
for _, target in pairs(hit_pointed_things) do
local hit_target_name = target.object:get_player_name() or target.object:get_luaentity().name
if target_name == hit_target_name then
pthings[k] = nil
break
end
end
end
table.insert_all(hit_pointed_things, pthings)
end
ray_pos = ray_pos - x_step
end
ray_pos = ray_pos - y_step
ray_pos = ray_pos + x_step * r_amount
end
return hit_pointed_things
end
----------------------------------------------
---------------FUNZIONI LOCALI----------------
----------------------------------------------
-- ritorna un array di giocatori con il numero di giocatori trovati a indice 1.
-- Se non trova giocatori diversi da se stesso ritorna nil
function cast_raycast(user, origin, dir, range, has_piercing)
local a = vector.add(origin, vector.multiply(dir, 0))
local b = vector.add(origin, vector.multiply(dir, range))
local ray = minetest.raycast(a, b)
local objects = {}
-- controllo su ogni cosa attraversata dal raycast (da a a b)
for hit in ray do
-- se è un oggetto
if hit.type == "object" then
-- se è un'entità
if not hit.ref:is_player() then
local entity = hit.ref:get_luaentity()
-- se collide con un proiettile, lo distrugge, sennò salva l'entità per il danno
if entity._is_bullet then
entity:_destroy()
else
table.insert(objects, {object=hit.ref, headshot=false})
end
-- se è un giocatore (e non chi spara)
elseif hit.ref ~= user then
if (hit.intersection_point.y - hit.ref:get_pos().y) > 1.275 then
table.insert(objects, {object=hit.ref, headshot=true})
else
table.insert(objects, {object=hit.ref, headshot=false})
end
end
local is_player = hit.ref:is_player()
local t_name = is_player and hit.ref:get_player_name() or hit.ref:get_luaentity().name
if not has_piercing then return objects end
else
-- se è un nodo mi fermo, e ritorno l'array se > 0 (ovvero ha trovato obiettivi)
if hit.type == "node" then
if #objects > 0 then
return has_piercing and objects or {objects[1]}
else
return
end
end
end
end
-- se ho sparato a un obiettivo senza incrociare blocchi
if #objects > 0 then
return has_piercing and objects or {objects[1]}
else
return
end
end
function get_shooter_left_dir(shooter)
local yaw = shooter:get_look_horizontal() or shooter:get_yaw()
local pl_left_dir = vector.new(math.cos(yaw), 0, math.sin(yaw))
return vector.normalize(pl_left_dir)
end
function get_shooter_up_dir(shooter, dir)
return vector.rotate_around_axis(dir, get_shooter_left_dir(shooter), math.pi/2)
end
function debug_particles(dir, origin, range)
minetest.add_particlespawner({
amount = 5,
time = 0.3,
pos = vector.new(origin),
vel = vector.multiply(dir, range),
size = 2,
texture = "bl_smg_trail.png"
})
end
------------------------------
-- not my code, don't know, don't ask
------------------------------
weapons_lib.grenade_explode = function(self)
local explosion_range = self._explosion_range
local explosion_damage = self._explosion_damage
local origin = self.object:get_pos()
local p_name = self._p_name
if origin == nil then return end
if origin.x == nil or origin.y == nil or origin.z == nil then return end
local objs = minetest.env:get_objects_inside_radius(origin, explosion_range)
local entities = {}
-- Se ho colpito qualcosa
if objs then
for _, obj in ipairs(objs) do
if obj:is_player() then
local p_pos = obj:get_pos()
local lenx = math.abs(p_pos.x - origin.x)
local leny = math.abs(p_pos.y - origin.y)
local lenz = math.abs(p_pos.z - origin.z)
local hypot = math.sqrt((lenx * lenx) + (lenz * lenz))
local dist = math.sqrt((hypot * hypot) + (leny * leny))
local damage = explosion_damage - (explosion_damage * dist / explosion_range)
local target_name = obj:get_player_name()
-- TODO: non funziona, la funzione è stata cambiata. Bisogna far passare l'arma
weapons_lib.apply_damage(minetest.get_player_by_name(p_name), {object = obj}, damage, 0, false)
elseif obj ~= self.object and obj:get_luaentity() then
table.insert(entities, obj:get_luaentity())
end
end
end
if #entities == 0 then return end
self.object:remove()
for _,entity in pairs(entities) do
if entity.initial_properties ~= nil then
if entity._is_bullet then
entity:_destroy()
end
end
end
end
end