255 lines
9.8 KiB
Lua
255 lines
9.8 KiB
Lua
-- Registra item ed entità
|
|
function quake.register_grenade(name, def)
|
|
|
|
if not def.entity.throw_speed then return end
|
|
|
|
minetest.register_node(name, {
|
|
description = def.description,
|
|
drawtype = "mesh",
|
|
mesh = def.mesh,
|
|
tiles = def.tiles,
|
|
wield_scale = def.wield_scale,
|
|
inventory_image = def.inventory_image,
|
|
stack_max = def.stack_max,
|
|
on_drop = function() end,
|
|
on_place = function(itemstack, user, pointed_thing)
|
|
-- lancia la granata
|
|
grenade_throw(itemstack, user, pointed_thing)
|
|
-- Toglie la granata se non si è in creative
|
|
-- momentaneamente disattivato perchè il server è in creative
|
|
--[[
|
|
if not minetest.setting_getbool("creative_mode") then
|
|
itemstack:take_item()
|
|
end
|
|
]]
|
|
itemstack:take_item()
|
|
return
|
|
end,
|
|
on_secondary_use = function(itemstack, user, pointed_thing)
|
|
-- lancia la granata
|
|
grenade_throw(itemstack, user, pointed_thing)
|
|
-- Toglie la granata se non si è in creative
|
|
-- momentaneamente disattivato perchè il server è in creative
|
|
--[[
|
|
if not minetest.setting_getbool("creative_mode") then
|
|
itemstack:take_item()
|
|
end
|
|
]]
|
|
itemstack:take_item()
|
|
return
|
|
end,
|
|
|
|
})
|
|
|
|
-- Ottiene la definizione dell'entità
|
|
local grenade_entity = grenade_set_entity(name, def)
|
|
-- Registra l'entità
|
|
minetest.register_entity(name .. "_entity", grenade_entity)
|
|
|
|
end
|
|
|
|
--Lancia la granata
|
|
function grenade_throw(itemstack, player, pointed_thing)
|
|
|
|
local dir = player:get_look_dir()
|
|
local yaw = player:get_look_horizontal()
|
|
local pitch = player:get_look_vertical()
|
|
local pos = player:get_pos()
|
|
local grenade = itemstack:get_name() .. '_entity' -- Nome dell'entità
|
|
local obj = minetest.add_entity({x = pos.x, y = pos.y + player:get_properties().eye_height, z = pos.z}, grenade, player:get_player_name()) -- add_entity(posizione, nome_entità, staticdata)
|
|
|
|
local throw_speed = obj:get_luaentity().initial_properties.throw_speed -- Velocità a cui viene lanciata la granta di base
|
|
local player_vel = player:get_player_velocity() -- Velocità del player
|
|
obj:set_velocity(vector.add(player_vel, vector.multiply(dir, throw_speed))) -- Imposta la velocità alla granata in base alla velocità del player ed alla velocità default
|
|
|
|
local rotation = vector.new(0, yaw + math.pi/2, pitch + math.pi/6) -- Calcola la rotazione
|
|
obj:set_rotation(rotation) --Imposta la rotazione della granata così che sia sempre orientata correttamente
|
|
|
|
return true
|
|
end
|
|
|
|
|
|
function grenade_set_entity(name, def)
|
|
local grenade_entity = {
|
|
initial_properties = {
|
|
name = name,
|
|
throw_speed = def.entity.throw_speed,
|
|
explosion_damage = def.entity.explosion_damage, --danno dell'esplosione
|
|
physical = def.entity.physical, --se è fisica
|
|
collide_with_objects = def.entity.collide_with_objects, --se collide con gli oggetti
|
|
visual = def.entity.visual, --che tipo di visualizzazione fare
|
|
--wield_item = def.entity.wield_item, --apparenza della granata
|
|
visual_size = def.entity.visual_size, --grandezza visiva della granata
|
|
mesh = def.entity.mesh,
|
|
explosion_texture = def.entity.explosion_texture, --texture dell'esplosione
|
|
textures = def.entity.textures,
|
|
collisionbox = def.entity.collisionbox, --grandezza della collisionbox
|
|
explosion_range = def.entity.explosion_range, --in che raggio fa danno l'esplosione
|
|
duration = def.entity.duration, --quanto dura il volo
|
|
gravity = def.entity.gravity, --se la gravità è attiva o no
|
|
on_destroy = def.entity.on_destroy, --cosa succede alla distruzione
|
|
particle = def.entity.particle,
|
|
is_grenade = true,
|
|
},
|
|
}
|
|
|
|
function grenade_entity:_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
|
|
|
|
-- Ottiene gli staticdata ogni 18 secondi circa
|
|
function grenade_entity:get_staticdata(self)
|
|
if self == nil or self.p_name == nil then return end
|
|
return self.p_name
|
|
end
|
|
|
|
-- L'entità esplode quando colpita
|
|
function grenade_entity:on_punch()
|
|
self:_destroy()
|
|
return
|
|
end
|
|
|
|
-- quando si istanzia un'entità
|
|
function grenade_entity:on_activate(staticdata)
|
|
|
|
if staticdata ~= "" and staticdata ~= nil then
|
|
self.p_name = staticdata -- nome utente come staticdata
|
|
self.lifetime = 0 -- tempo in aria
|
|
self.sliding = 0 -- se sta scivolando
|
|
self.particle = 0 -- contatore di buffer per le particelle della granata
|
|
self.object:set_armor_groups({immortal = 1}) -- lo imposta come immortale
|
|
else -- se non ci sono gli staticdata necessari allora rimuove l'entità
|
|
self.object:remove()
|
|
return
|
|
end
|
|
end
|
|
|
|
function grenade_entity:on_step(dtime, moveresult)
|
|
self.lifetime = self.lifetime + dtime
|
|
|
|
if self.initial_properties.gravity then
|
|
local obj = self.object
|
|
local velocity = obj:get_velocity()
|
|
|
|
local pos = obj:getpos()
|
|
|
|
if moveresult.collides and moveresult.collisions[1] and not vector.equals(moveresult.collisions[1].old_velocity, velocity) and vector.distance(moveresult.collisions[1].old_velocity, velocity) > 4 then
|
|
if math.abs(moveresult.collisions[1].old_velocity.x - velocity.x) > 5 then -- Controlla se c'è stata una grande riduzione di velocità
|
|
velocity.x = moveresult.collisions[1].old_velocity.x * -0.5 -- Inverte la velocità e la riduce
|
|
end
|
|
|
|
if math.abs(moveresult.collisions[1].old_velocity.y - velocity.y) > 5 then -- Controlla se c'è stata una grande riduzione di velocità
|
|
velocity.y = moveresult.collisions[1].old_velocity.y * -0.3 -- Inverte la velocità e la riduce
|
|
end
|
|
|
|
if math.abs(moveresult.collisions[1].old_velocity.z - velocity.z) > 5 then -- Controlla se c'è stata una grande riduzione di velocità
|
|
velocity.z = moveresult.collisions[1].old_velocity.z * -0.5 -- Inverte la velocità e la riduce
|
|
end
|
|
|
|
obj:set_velocity(velocity)
|
|
end
|
|
|
|
if self.sliding == 0 and velocity.y == 0 then -- Controlla se la granata sta scivolando
|
|
self.sliding = 1 -- Attiva l'attrito
|
|
elseif self.sliding > 0 and velocity.y ~= 0 then
|
|
self.sliding = 0 -- Non influisce sull'attrito
|
|
end
|
|
|
|
if self.sliding > 1 then -- Sta scivolando?
|
|
if vector.distance(vector.new(), velocity) <= 1 and not vector.equals(velocity, vector.new()) then -- Se la granata si muove a malapena
|
|
obj:set_velocity(vector.new(0, -9.8, 0)) -- Si assicura sia ferma
|
|
obj:set_acceleration(vector.new())
|
|
end
|
|
end
|
|
|
|
local direction = vector.normalize(velocity)
|
|
local node = minetest.get_node(pos)
|
|
local speed = vector.length(velocity)
|
|
local drag = math.max(minetest.registered_nodes[node.name].liquid_viscosity, 0.1) * self.sliding -- Ottiene l'attrito generato dal liquido che attraversa
|
|
local yaw = minetest.dir_to_yaw(direction)
|
|
local pitch = math.acos(velocity.y/speed) - math.pi/3
|
|
-- Controlla che il pitch sia un numero
|
|
if tostring(pitch) ~= 'nan' then
|
|
obj:set_rotation({x = 0, y = yaw + math.pi/2, z = pitch}) -- Imposta la rotazione
|
|
end
|
|
|
|
local acceleration = vector.multiply(velocity, -drag)
|
|
|
|
acceleration.x = acceleration.x * (self.sliding * 10 * 2 + 1) -- Modifica la x in base a se sta scivolando o meno
|
|
acceleration.y = acceleration.y - 10 * ((7 - drag) / 7) -- Perdita in altezza del proiettile in base all' attrito
|
|
acceleration.z = acceleration.z * (self.sliding * 10 * 2 + 1) -- Modifica la Z in base a se sta scivolando o meno
|
|
|
|
-- Controlla che l'accelerazione sia un numero
|
|
if tostring(acceleration) ~= 'nan' then
|
|
obj:set_acceleration(acceleration) -- Imposta l'accelerazione
|
|
end
|
|
|
|
-- Controlla che il timer per mostrare le particelle che tracciano la granata sia superiore al valore definito e che eista una definizione delle particelle da creare
|
|
if self.initial_properties.particle and self.particle >= self.initial_properties.particle.interval then
|
|
-- Imposta il timer a 0
|
|
self.particle = 0
|
|
-- Aggiunge le particelle di tracciamento
|
|
minetest.add_particle({
|
|
pos = obj:get_pos(),
|
|
velocity = vector.divide(velocity, 2),
|
|
acceleration = vector.divide(obj:get_acceleration(), -5),
|
|
expirationtime = self.initial_properties.particle.life,
|
|
size = self.initial_properties.particle.size,
|
|
collisiondetection = false,
|
|
collision_removal = false,
|
|
vertical = false,
|
|
texture = self.initial_properties.particle.image,
|
|
glow = self.initial_properties.particle.glow
|
|
})
|
|
-- Controlla che il timer per mostrare le particelle che tracciano la granata sia inferiore al valore definito e che eista una definizione delle particelle da creare
|
|
elseif self.initial_properties.particle and self.particle < self.initial_properties.particle.interval then
|
|
-- Incrementa il timer
|
|
self.particle = self.particle + 1
|
|
end
|
|
|
|
-- Se ha raggiunto la durata di vita massima
|
|
if self.lifetime >= self.initial_properties.duration then
|
|
-- ESPLODE
|
|
self:_destroy()
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Restituisce la definizione dell'entità
|
|
return grenade_entity
|
|
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
|