minetest-quake/_weapons/throwables.lua

319 lines
11 KiB
Lua

-- definisco le proprietà e i costruttori delle entità 'proiettili' e le registro alla fine
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,
on_drop = function() end,
on_place = function(itemstack, user, pointed_thing)
grenade_throw(itemstack, user, pointed_thing)
if not minetest.setting_getbool("creative_mode") then
itemstack:take_item()
end
return itemstack
end,
on_secondary_use = function(itemstack, user, pointed_thing)
grenade_throw(itemstack, user, pointed_thing)
if not minetest.setting_getbool("creative_mode") then
itemstack:take_item()
end
return itemstack
end,
})
local grenade_entity = grenade_set_entity(name, def)
minetest.register_entity(name .. "_entity", grenade_entity)
end
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'
local obj = minetest.add_entity({x = pos.x, y = pos.y + player:get_properties().eye_height, z = pos.z}, grenade, player:get_player_name())
local throw_speed = obj:get_luaentity().initial_properties.throw_speed
local player_vel = player:get_player_velocity()
obj:set_velocity(vector.add(player_vel, vector.multiply(dir, throw_speed)))
--obj:set_velocity({x = dir.x * throw_speed, y = dir.y * throw_speed/1.5, z = dir.z * throw_speed})
--obj:set_acceleration({x = 0, y = -13, z = 0})
local rotation = vector.new(0, yaw + math.pi/2, pitch + math.pi/6)
obj:set_rotation(rotation)
--[[
local grenade = itemstack:get_name() .. '_entity'
local player_pos = player:get_pos()
local head_pos = vector.new(player_pos.x, player_pos.y + player:get_properties().eye_height, player_pos.z)
local direction = player:get_look_dir()
local throw_pos = vector.add(head_pos, vector.multiply(direction,0.5))
local pitch = player:get_look_vertical()
local yaw = player:get_look_horizontal()
local rotation = vector.new(0, yaw + math.pi/2, pitch + math.pi/6)
local grenade_object = minetest.add_entity(throw_pos, grenade, player:get_player_name())
local throw_speed = grenade_object:get_luaentity().initial_properties.throw_speed
local player_vel = player:get_player_velocity()
grenade_object:set_velocity(vector.add(player_vel, vector.multiply(direction, throw_speed)))
grenade_object:set_rotation(rotation)
grenade_object:set_rotation(vector.new(0, 0, 0))
]]
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,
acceleration = def.entity.acceleration,
is_grenade = true,
},
}
function grenade_entity:_destroy()
spawn_particles_sphere(self.object:get_pos(), self.initial_properties.explosion_texture)
if self.initial_properties.on_destroy then
self.initial_properties.on_destroy(self)
end
-- spawna le particelle
self.object:remove()
end
function grenade_entity:get_staticdata(self)
if self == nil or self.p_name == nil then return end
return self.p_name
end
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
self.sliding = 0
self.particle = 0
self.object:set_armor_groups({immortal = 1})
else
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 -- Check for a large reduction in velocity
velocity.x = moveresult.collisions[1].old_velocity.x * -0.5 -- Invert velocity and reduce it a bit
end
if math.abs(moveresult.collisions[1].old_velocity.y - velocity.y) > 5 then -- Check for a large reduction in velocity
velocity.y = moveresult.collisions[1].old_velocity.y * -0.3 -- Invert velocity and reduce it a bit
end
if math.abs(moveresult.collisions[1].old_velocity.z - velocity.z) > 5 then -- Check for a large reduction in velocity
velocity.z = moveresult.collisions[1].old_velocity.z * -0.5 -- Invert velocity and reduce it a bit
end
obj:set_velocity(velocity)
end
--[[
print("#########################")
print(dump(velocity))
print("#########################")
]]
if self.sliding == 0 and velocity.y == 0 then -- Check if grenade is sliding
self.sliding = 1 -- Multiplies drag by 2
elseif self.sliding > 0 and velocity.y ~= 0 then
self.sliding = 0 -- Doesn't affect drag
end
if self.sliding > 1 then -- Is the grenade sliding?
if vector.distance(vector.new(), velocity) <= 1 and not vector.equals(velocity, vector.new()) then -- Grenade is barely moving
obj:set_velocity(vector.new(0, -9.8, 0)) -- Make sure it stays unmoving
obj:set_acceleration(vector.new())
end
end
--else
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
local yaw = minetest.dir_to_yaw(direction)
local speed = vector.length(velocity)
local pitch = math.acos(velocity.y/speed) - math.pi/3
if tostring(pitch) ~= 'nan' then
obj:set_rotation({x = 0, y = yaw + math.pi/2, z = pitch})
end
--print(drag)
local acceleration = vector.multiply(velocity, -drag)
--local acceleration = vector.multiply(direction, -drag)
--print(acceleration.y)
acceleration.x = acceleration.x * (self.sliding * 5 * 2 + 1)
acceleration.y = acceleration.y - 10 * ((7 - drag) / 7)
acceleration.z = acceleration.z * (self.sliding * 5 * 2 + 1)
--[[
print("XXXXXXXXXXXXXXXXXXXXXXXXXXXX")
print(acceleration.x * (self.sliding * 5 * 2 + 1))
print(-direction.x * 13 * (self.sliding + 1))
print("XXXXXXXXXXXXXXXXXXXXXXXXXXXX")
print("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZ")
print(acceleration.z * (self.sliding * 5 * 2 + 1))
print(-direction.z * 13 * (self.sliding + 1))
print("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZ")
]]
if tostring(acceleration) ~= 'nan' then
obj:set_acceleration(acceleration)
end
--[[
obj:set_acceleration({
x = -direction.x * (self.initial_properties.throw_speed/2) * self.sliding,
y = -9.8 * drag,
z = -direction.z * (self.initial_properties.throw_speed/2) * self.sliding,
})
]]
--[[
local direction = vector.normalize(velocity)
obj:set_acceleration({
x = -direction.x * self.initial_properties.acceleration * self.sliding,
y = -9.8,
z = -direction.z * self.initial_properties.acceleration * self.sliding,
})]]
--end
if self.initial_properties.particle and self.particle >= 4 then
self.particle = 0
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
})
elseif self.initial_properties.particle and self.particle < self.initial_properties.particle.interval then
self.particle = self.particle + 1
end
if self.lifetime >= self.initial_properties.duration then
self:_destroy()
return
end
--[[
local speed = vector.length(velocity)
local direction = vector.normalize(velocity)
local yaw = minetest.dir_to_yaw(direction)
local pitch = math.acos(velocity.y/speed) - math.pi/3
local pos = self.object:get_pos()
local node = minetest.get_node(pos)
local drag = math.max(minetest.registered_nodes[node.name].liquid_viscosity, 0.1)
if velocity.y == 0 then
drag = drag * 2
end
local acceleration = vector.multiply(velocity, -drag)
acceleration.y = acceleration.y - 10 * ((7 - drag) / 7)
if tostring(acceleration) ~= 'nan' then
self.object:set_acceleration(acceleration)
end
if tostring(yaw) ~= 'nan' and tostring(pitch) ~= 'nan' then
self.object:set_rotation({x = 0, y = yaw + math.pi/2, z = pitch})
end
]]
end
end
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