234 lines
7.1 KiB
Lua
234 lines
7.1 KiB
Lua
local function calc_dir_from_pos() end
|
|
local function jump() end
|
|
local function spawn_particles_sphere() end
|
|
local function get_dist() end
|
|
|
|
|
|
|
|
-- definisco le proprietà e i costruttori delle entità 'proiettili' e le registro alla fine
|
|
function quake.register_bullet(name, def)
|
|
|
|
if not def.speed then return end
|
|
|
|
-- definizione proprietà iniziali: uguali per tutte le istanze dello stesso tipo
|
|
local bulletentity = {
|
|
initial_properties = {
|
|
name = name,
|
|
physical = def.physical,
|
|
collide_with_objects = def.collide_with_objects,
|
|
visual = def.visual,
|
|
visual_size = def.visual_size,
|
|
mesh = def.mesh,
|
|
explosion_texture = def.explosion_texture,
|
|
textures = def.textures,
|
|
collisionbox = def.collisionbox,
|
|
speed = def.speed,
|
|
damage = def.damage,
|
|
explosion_range = def.explosion_range,
|
|
duration = def.duration,
|
|
jump = def.jump,
|
|
explosion_damage = def.explosion_damage,
|
|
on_destroy = def.on_destroy,
|
|
is_bullet = true,
|
|
},
|
|
}
|
|
|
|
-- cosa succede alla distruzione del proiettile. In pratica prende il metodo impostato
|
|
-- nella creazione del proiettile e lo usa alla distruzione. Comodo perchè così è astratta anche quella
|
|
function bulletentity:_destroy()
|
|
-- Crea le particelle dell'esplosione
|
|
spawn_particles_sphere(self.object:get_pos(), self.initial_properties.explosion_texture)
|
|
-- Se ha una funzione apposita da usare quando esplode la esegue
|
|
if self.initial_properties.on_destroy then
|
|
self.initial_properties.on_destroy(self)
|
|
end
|
|
-- Distrugge l'entità
|
|
self.object:remove()
|
|
|
|
|
|
end
|
|
|
|
|
|
function bulletentity:get_staticdata(self)
|
|
if self == nil or self.p_name == nil then return end
|
|
return self.p_name
|
|
end
|
|
|
|
-- quando si istanzia un'entità
|
|
function bulletentity:on_activate(staticdata)
|
|
|
|
if staticdata ~= "" and staticdata ~= nil then
|
|
-- variabili assegnate alla SINGOLA entity quando istanziata. Non rimangono in memoria al riavvio
|
|
self.p_name = staticdata -- nome utente come staticdata
|
|
self.shooter = minetest.get_player_by_name(staticdata)
|
|
self.lifetime = 0
|
|
else
|
|
self.object:remove()
|
|
return
|
|
end
|
|
|
|
end
|
|
|
|
|
|
--moveresult è una metatabella dove vengono passati i dati delle collisioni della collisionbox
|
|
|
|
--TODO fare che si possa colpire più di un player in quanto la collisione può avvenire con 2 player contemporaneamente
|
|
--ed in quel caso moveresult.collisions ha dentro anche l'altra collisione.
|
|
function bulletentity:on_step(dtime, moveresult)
|
|
-- incremento tempo di vita
|
|
self.lifetime = self.lifetime + dtime
|
|
|
|
-- se ha raggiunto la durata di vita massima
|
|
if self.lifetime >= self.initial_properties.duration then
|
|
self:_destroy()
|
|
return
|
|
end
|
|
|
|
-- controlla se collide con qualcosa
|
|
if moveresult.collides == true then
|
|
--collisions è una tabella dentro moveresult dove al primo indice c'è una tabella
|
|
--con vari dati in certi casi di collisione (solitamente se collide con oggetti)
|
|
if moveresult.collisions[1] then
|
|
--object è l'oggetto(player/entità) con cui collide il proiettile
|
|
if moveresult.collisions[1].object then
|
|
--controlla se è un player
|
|
if moveresult.collisions[1].object:is_player() then
|
|
|
|
if moveresult.collisions[1].object:get_player_name() ~= self.p_name then
|
|
quake.shoot(self.p_name, moveresult.collisions[1].object, self.initial_properties.damage, false)
|
|
self:_destroy()
|
|
return
|
|
|
|
elseif moveresult.collisions[1].object:get_player_name() == self.p_name then
|
|
|
|
if self.lifetime < (15 / self.initial_properties.speed) then
|
|
self.object:set_velocity({
|
|
x=(moveresult.collisions[1].old_velocity.x),
|
|
y=(moveresult.collisions[1].old_velocity.y),
|
|
z=(moveresult.collisions[1].old_velocity.z),
|
|
})
|
|
return
|
|
end
|
|
|
|
else
|
|
self:_destroy()
|
|
return
|
|
end
|
|
|
|
end
|
|
--quando non è un player allora è una entity quindi la memorizzo per alleggerire il numero di accessi
|
|
local entity = moveresult.collisions[1].object:get_luaentity()
|
|
--i prossimi 2 check servono a verificare l'entità sia un proiettile
|
|
if entity and entity.initial_properties ~= nil then
|
|
|
|
if entity.initial_properties.is_bullet or entity.initial_properties.is_grenade then
|
|
--distrugge sia il proiettile con cui collide che se stesso
|
|
entity:_destroy()
|
|
self:_destroy()
|
|
return
|
|
end
|
|
|
|
end
|
|
else
|
|
--se non è presente il campo object distrugge comunque il proiettile per prevenire crash ed errori
|
|
self:_destroy()
|
|
return
|
|
end
|
|
|
|
end
|
|
--quando non esiste collisions[1] distrugge comunque perchè sta collidendo con qualcosa
|
|
self:_destroy()
|
|
return
|
|
end
|
|
end
|
|
|
|
--registra l'entità
|
|
minetest.register_entity(name, bulletentity)
|
|
|
|
end
|
|
|
|
|
|
function quake.shoot_bullet(shooter, bullet, pos_head, dir)
|
|
|
|
local username = shooter:get_player_name()
|
|
local bullet = minetest.add_entity(pos_head, bullet, username) -- spawna il proiettile dalla testa e passo il nick come staticdata
|
|
local yaw = shooter:get_look_horizontal()
|
|
local pitch = shooter:get_look_vertical()
|
|
|
|
bullet:set_rotation({x = -pitch, y = yaw, z = 0})
|
|
|
|
local speed = bullet:get_luaentity().initial_properties.speed
|
|
bullet:set_velocity({
|
|
x=(dir.x * speed),
|
|
y=(dir.y * speed),
|
|
z=(dir.z * speed),
|
|
})
|
|
--bullet:set_acceleration({ x=dir.x, y=dir.y, z=dir.z })
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
----------------------------------------------
|
|
---------------FUNZIONI LOCALI----------------
|
|
----------------------------------------------
|
|
|
|
function calc_dir_from_pos(p1,p2)
|
|
local dir = vector.subtract(p1,p2)
|
|
return dir
|
|
end
|
|
|
|
|
|
|
|
function jump(shooter, amount, dir)
|
|
local knockback = vector.multiply(dir,-(amount))
|
|
shooter:add_player_velocity(knockback)
|
|
end
|
|
|
|
|
|
|
|
--aggiunge le particelle dell'esplosione
|
|
function spawn_particles_sphere(pos, particle_texture)
|
|
if not pos then return end
|
|
minetest.add_particlespawner({
|
|
amount = 80,
|
|
time = .1,
|
|
minpos = {x=pos.x,y=pos.y,z=pos.z},
|
|
maxpos = {x=pos.x,y=pos.y,z=pos.z},
|
|
minvel = {x=-4, y=-4, z=-4},
|
|
maxvel = {x=4, y=4, z=4},
|
|
minacc = {x=0, y=-0.4, z=0},
|
|
maxacc = {x=0, y=-0.8, z=0},
|
|
minexptime = .5,
|
|
maxexptime = .5,
|
|
minsize = 1,
|
|
maxsize = 5,
|
|
collisiondetection = false,
|
|
vertical = false,
|
|
texture = particle_texture,
|
|
})
|
|
|
|
end
|
|
|
|
|
|
|
|
-- ottiene la distanza tra proiettile e che cosa sta puntando
|
|
function get_dist(hit_pos, pos_ent)
|
|
local lenx = math.abs(hit_pos.x - pos_ent.x)
|
|
local leny = math.abs(hit_pos.y + 0.975 - pos_ent.y)
|
|
local lenz = math.abs(hit_pos.z - pos_ent.z)
|
|
local hypot = math.sqrt((lenx * lenx) + (lenz * lenz))
|
|
local dist = math.sqrt((hypot * hypot) + (leny * leny))
|
|
return dist
|
|
end
|
|
|
|
|
|
local function get_nodedef_field(nodename, fieldname)
|
|
if not minetest.registered_nodes[nodename] then
|
|
return nil
|
|
end
|
|
return minetest.registered_nodes[nodename][fieldname]
|
|
end
|