327 lines
8.2 KiB
Lua
327 lines
8.2 KiB
Lua
--[[
|
|
This file is part of Ice Lua Components.
|
|
|
|
Ice Lua Components is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Lesser General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Ice Lua Components is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
along with Ice Lua Components. If not, see <http://www.gnu.org/licenses/>.
|
|
]]
|
|
|
|
if client then
|
|
mdl_nade = model_load({
|
|
kv6={bdir=DIR_PKG_KV6, name="nade.kv6", scale=6.0/128.0},
|
|
pmf={bdir=DIR_PKG_PMF, name="nade.pmf"},
|
|
}, {"kv6","pmf"})
|
|
mdl_nade_inst = mdl_nade {}
|
|
end
|
|
|
|
function nade_add(nade)
|
|
nades.tail = nades.tail + 1
|
|
nades[nades.tail] = nade
|
|
end
|
|
|
|
function nade_prune(sec_current)
|
|
local i
|
|
for i=nades.head,nades.tail do
|
|
if nades[i] and nades[i].dead then
|
|
nades[i] = nil
|
|
if i == nades.head then
|
|
nades.head = nades.head + 1
|
|
end
|
|
end
|
|
end
|
|
if nades.head > nades.tail then
|
|
nades.head = 1
|
|
nades.tail = 0
|
|
end
|
|
end
|
|
|
|
function new_nade(settings)
|
|
local this = {
|
|
x = settings.x,
|
|
y = settings.y,
|
|
z = settings.z,
|
|
x0 = settings.x,
|
|
y0 = settings.y,
|
|
z0 = settings.z,
|
|
x1 = settings.x,
|
|
y1 = settings.y,
|
|
z1 = settings.z,
|
|
|
|
vx = settings.vx,
|
|
vy = settings.vy,
|
|
vz = settings.vz,
|
|
|
|
pid = settings.pid,
|
|
|
|
trem = 0.0,
|
|
fuse = settings.fuse,
|
|
dead = false
|
|
} this.this = this
|
|
|
|
local function prv_advance()
|
|
local d,x1,y1,z1,x2,y2,z2,_
|
|
this.x0 = this.x1
|
|
this.y0 = this.y1
|
|
this.z0 = this.z1
|
|
local db = math.sqrt(this.vx*this.vx+this.vy*this.vy+this.vz*this.vz)
|
|
--print("a",this.x0,this.y0,this.z0,this.vx,this.vy,this.vz)
|
|
--print("db",db)
|
|
d,x1,y1,z1,x2,y2,z2 = trace_map_ray_dist(
|
|
this.x0,this.y0,this.z0,
|
|
this.vx/db,this.vy/db,this.vz/db,
|
|
db)
|
|
|
|
local df = 1.0
|
|
if d then
|
|
df = math.max(0,d/db-0.001)
|
|
--print("df",df,d,db)
|
|
end
|
|
|
|
this.x1 = this.x0 + this.vx*df
|
|
this.y1 = this.y0 + this.vy*df
|
|
this.z1 = this.z0 + this.vz*df
|
|
|
|
if x1 then
|
|
local bounce_vel = 0
|
|
if x1 ~= x2 then
|
|
this.vx = -this.vx*MODE_NADE_BDAMP
|
|
bounce_vel = math.max(bounce_vel, math.abs(this.vx))
|
|
end
|
|
if y1 ~= y2 then
|
|
this.vy = -this.vy*MODE_NADE_BDAMP
|
|
bounce_vel = math.max(bounce_vel, math.abs(this.vy))
|
|
end
|
|
if z1 ~= z2 then
|
|
this.vz = -this.vz*MODE_NADE_BDAMP
|
|
bounce_vel = math.max(bounce_vel, math.abs(this.vz))
|
|
end
|
|
this.vx = this.vx * MODE_NADE_ADAMP
|
|
this.vy = this.vy * MODE_NADE_ADAMP
|
|
this.vz = this.vz * MODE_NADE_ADAMP
|
|
|
|
if client and bounce_vel >= MODE_NADE_BOUNCE_SOUND_MIN then
|
|
local vol = 1.0
|
|
if bounce_vel < MODE_NADE_BOUNCE_SOUND_FADE then
|
|
vol = rescale_value(MODE_NADE_BOUNCE_SOUND_MIN, MODE_NADE_BOUNCE_SOUND_FADE, 0, 1, bounce_vel)
|
|
end
|
|
client.wav_play_global(wav_nade_bounce, this.x, this.y, this.z, vol)
|
|
end
|
|
end
|
|
|
|
this.vy = this.vy + 5*MODE_GRAVITY*MODE_NADE_STEP*MODE_NADE_STEP
|
|
end
|
|
|
|
function this.explode_dmg()
|
|
local hplr = this.pid and players[this.pid]
|
|
if hplr and not hplr.has_permission("kill") then return end
|
|
|
|
local x,y,z
|
|
local x0,y0,z0
|
|
x0,y0,z0 = math.floor(this.x)
|
|
, math.floor(this.y)
|
|
, math.floor(this.z)
|
|
|
|
local xlen,ylen,zlen
|
|
xlen,ylen,zlen = common.map_get_dims()
|
|
|
|
local vpls = nil
|
|
if MODE_NADE_VPL_ENABLE then
|
|
vpls = vpl_gen_from_sphere(this.x, this.y, this.z,
|
|
MODE_NADE_VPL_MAX_COUNT, MODE_NADE_VPL_MAX_RANGE, MODE_NADE_VPL_MAX_TRIES)
|
|
end
|
|
|
|
local i
|
|
for i=1,players.max do
|
|
local plr = players[i]
|
|
if plr and ((not hplr) or plr == hplr or plr.team ~= hplr.team) then
|
|
if MODE_NADE_VPL_ENABLE then
|
|
local dmg_acc = 0
|
|
local j
|
|
vpls[#vpls+1] = {x = this.x, y = this.y, z = this.z,
|
|
s = MODE_NADE_VPL_DIRECT_STRENGTH, d = 0.0, special = true}
|
|
--print(#vpls)
|
|
for j=1,#vpls do
|
|
-- Get the VPL.
|
|
local v = vpls[j]
|
|
|
|
-- Get the delta vector to the player's head.
|
|
local dx,dy,dz
|
|
dx = plr.x-v.x
|
|
dy = (plr.y+((plr.crouching and 0.6) or 0.9))-v.y
|
|
dz = plr.z-v.z
|
|
|
|
-- Get the distance.
|
|
local dd = dx*dx+dy*dy+dz*dz
|
|
dd = math.sqrt(dd)
|
|
|
|
-- Compare it against the maximum distance.
|
|
-- Incorporate the already-travelled distance of the VPL.
|
|
if dd + v.d < MODE_NADE_VPL_MAX_RANGE then
|
|
-- Normalise the delta vector.
|
|
dx = dx/dd
|
|
dy = dy/dd
|
|
dz = dz/dd
|
|
|
|
-- See if there's anything between you and the game^H^H^H^H VPL.
|
|
local nd
|
|
nd = trace_map_ray_dist(v.x,v.y,v.z, dx,dy,dz, dd)
|
|
if not nd then
|
|
-- Didn't hit anything. Calculate damage.
|
|
dd = dd + v.d
|
|
local dmg = MODE_NADE_VPL_DAMAGE_1*v.s/(dd*dd)
|
|
dmg_acc = math.max(dmg_acc, dmg)
|
|
end
|
|
end
|
|
end
|
|
--print(dmg_acc)
|
|
dmg_acc = math.floor(dmg_acc + 0.8)
|
|
if dmg_acc >= 1 then
|
|
plr.explosive_damage(dmg_acc, hplr)
|
|
end
|
|
else
|
|
local dx,dy,dz
|
|
dx = plr.x-this.x
|
|
dy = (plr.y+0.9)-this.y
|
|
dz = plr.z-this.z
|
|
|
|
local dd = dx*dx+dy*dy+dz*dz
|
|
if dd < MODE_NADE_RANGE*MODE_NADE_RANGE then
|
|
dd = math.sqrt(dd)
|
|
dx = dx/dd
|
|
dy = dy/dd
|
|
dz = dz/dd
|
|
local nd
|
|
nd = trace_map_ray_dist(this.x,this.y,this.z, dx,dy,dz, dd)
|
|
if not nd then
|
|
local dmg = (-(math.pow(dd / MODE_NADE_RANGE, 4)) + 1) * MODE_NADE_DAMAGE
|
|
|
|
plr.explosive_damage(dmg, hplr)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if hplr and not hplr.has_permission("build") then return end
|
|
|
|
if map_block_get(x0,y0,z0) ~= nil then
|
|
if y0 < ylen-2 then
|
|
map_block_break(x0,y0,z0)
|
|
net_broadcast(nil, common.net_pack("BHHH"
|
|
, PKT_BLK_RM1, x0,y0,z0))
|
|
end
|
|
else
|
|
for z=z0-1,z0+1 do
|
|
for x=x0-1,x0+1 do
|
|
for y=y0-1,y0+1 do
|
|
if y < ylen-2 and map_block_break(x,y,z) then
|
|
net_broadcast(nil, common.net_pack("BHHH"
|
|
, PKT_BLK_RM1, x,y,z))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if MODE_NADE_VPL_ENABLE then
|
|
local dmg_blks = {}
|
|
for j=1,#vpls do
|
|
local v = vpls[j]
|
|
local x = v.cx --math.floor(v.x+0.5)
|
|
local y = v.cy --math.floor(v.y+0.5)
|
|
local z = v.cz --math.floor(v.z+0.5)
|
|
local blk = {x,y,z}
|
|
if y and y < ylen-2 then
|
|
if not dmg_blks[blk] then
|
|
dmg_blks[blk] = 0
|
|
end
|
|
dmg_blks[blk] = dmg_blks[blk] + MODE_NADE_VPL_BLK_DAMAGE
|
|
end
|
|
end
|
|
for blk,dmg in pairs(dmg_blks) do
|
|
bhealth_damage(blk[1],blk[2],blk[3], dmg)
|
|
net_broadcast(nil, common.net_pack("BHHHH", PKT_BLK_DAMAGE, blk[1],blk[2],blk[3], dmg))
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
end
|
|
|
|
function this.tick(sec_current, sec_delta)
|
|
if this.dead then return end
|
|
|
|
this.trem = this.trem - sec_delta
|
|
local i = 10
|
|
while this.trem < 0 do
|
|
prv_advance()
|
|
this.trem = this.trem + MODE_NADE_STEP
|
|
i = i - 1
|
|
if i <= 0 then break end
|
|
end
|
|
|
|
local lerp = 1-this.trem/MODE_NADE_STEP
|
|
this.x = this.x1*lerp+this.x0*(1-lerp)
|
|
this.y = this.y1*lerp+this.y0*(1-lerp)
|
|
this.z = this.z1*lerp+this.z0*(1-lerp)
|
|
|
|
this.fuse = this.fuse - sec_delta
|
|
if this.fuse <= 0 then
|
|
if client then
|
|
client.wav_play_global(wav_nade_boom, this.x, this.y, this.z)
|
|
if MODE_DEBUG_VPLTEST then
|
|
VPLPOINT = {x = this.x, y = this.y, z = this.z}
|
|
v(true)
|
|
end
|
|
local i
|
|
local nade_particlecount = (
|
|
MODE_NADE_VPL_ENABLE and 1
|
|
) or (math.random() * 10 + 20)
|
|
local pvel = 2
|
|
nade_part_mdl = nade_part_mdl or new_particle_model(70, 70, 70)
|
|
local mdl = nade_part_mdl
|
|
--[[
|
|
local mdl = new_particle_model(
|
|
60 + math.random() * 20,
|
|
60 + math.random() * 20,
|
|
60 + math.random() * 20)
|
|
]]
|
|
|
|
for i=1,nade_particlecount do
|
|
particles_add(new_particle{
|
|
x = this.x,
|
|
y = this.y-0.1,
|
|
z = this.z,
|
|
vx = pvel*(2*math.random()-1),
|
|
vy = pvel*(2*math.random()-1.8),
|
|
vz = pvel*(2*math.random()-1),
|
|
size = 16 + math.random() * 32,
|
|
model = mdl,
|
|
})
|
|
end
|
|
end
|
|
if server then
|
|
this.explode_dmg()
|
|
end
|
|
this.dead = true
|
|
end
|
|
end
|
|
|
|
function this.render()
|
|
if this.dead then return end
|
|
|
|
mdl_nade_inst.render_global(
|
|
this.x, this.y, this.z,
|
|
0.0, 0.0, 0.0, 1.0)
|
|
end
|
|
|
|
return this
|
|
end
|