dobrograd-13-06-2022/garrysmod/addons/feature-cars/lua/simfphys/server/damage.lua
Jonny_Bro (Nikita) e4d5311906 first commit
2023-11-16 15:01:19 +05:00

320 lines
8.3 KiB
Lua

util.AddNetworkString('simfphys_spritedamage')
util.AddNetworkString('simfphys_lightsfixall')
util.AddNetworkString('simfphys_backfire')
local function Spark(pos , normal , snd)
local effectdata = EffectData()
effectdata:SetOrigin(pos - normal)
effectdata:SetNormal(-normal)
util.Effect('stunstickimpact', effectdata, true, true)
if snd then
sound.Play(Sound(snd), pos, 75)
end
end
local function DestroyVehicle(ent)
if not IsValid(ent) then return end
if ent.destroyed then return end
ent:OnDestroyed()
ent.destroyed = true
local ply = ent.EntityOwner
local skin = ent:GetSkin()
local Col = ent:GetColor()
Col.r = Col.r * 0.8
Col.g = Col.g * 0.8
Col.b = Col.b * 0.8
local bprop = ents.Create('gmod_sent_vehicle_fphysics_gib')
bprop:SetModel(ent:GetModel())
bprop:SetPos(ent:GetPos())
bprop:SetAngles(ent:GetAngles())
bprop:Spawn()
bprop:Activate()
bprop:GetPhysicsObject():SetVelocity(ent:GetVelocity() + Vector(math.random(-5,5),math.random(-5,5),math.random(150,250)))
bprop:GetPhysicsObject():SetMass(ent.Mass * 0.75)
bprop.DoNotDuplicate = true
bprop.MakeSound = true
bprop:SetColor(Col)
bprop:SetSkin(skin)
simfphys.SetOwner(ply , bprop)
if IsValid(ply) then
undo.Create('Gib')
undo.SetPlayer(ply)
undo.AddEntity(bprop)
undo.SetCustomUndoText('Undone Gib')
undo.Finish('Gib')
ply:AddCleanup('Gibs', bprop)
end
if ent.CustomWheels == true and not ent.NoWheelGibs then
for i = 1, table.Count(ent.GhostWheels) do
local Wheel = ent.GhostWheels[i]
if IsValid(Wheel) then
local prop = ents.Create('gmod_sent_vehicle_fphysics_gib')
prop:SetModel(Wheel:GetModel())
prop:SetPos(Wheel:LocalToWorld(Vector(0,0,0)))
prop:SetAngles(Wheel:LocalToWorldAngles(Angle(0,0,0)))
prop:SetOwner(bprop)
prop:Spawn()
prop:Activate()
prop:GetPhysicsObject():SetVelocity(ent:GetVelocity() + Vector(math.random(-5,5),math.random(-5,5),math.random(0,25)))
prop:GetPhysicsObject():SetMass(20)
prop.DoNotDuplicate = true
bprop:DeleteOnRemove(prop)
simfphys.SetOwner(ply , prop)
end
end
end
local Driver = ent:GetDriver()
if IsValid(Driver) and ent.RemoteDriver ~= Driver then
Driver:Kill()
end
if ent.PassengerSeats then
for i = 1, table.Count(ent.PassengerSeats) do
local Passenger = ent.pSeat[i]:GetDriver()
if IsValid(Passenger) then
Passenger:Kill()
end
end
end
ent:Extinguish()
ent:Remove()
end
local function DamageVehicle(ent , damage, type, allowExplode)
if not simfphys.DamageEnabled then return end
local MaxHealth = ent:GetMaxHealth()
local CurHealth = ent:GetCurHealth()
local NewHealth = math.max(math.Round(CurHealth - damage, 0), allowedExplode and 0 or 10)
ent:SetCurHealth(NewHealth)
if NewHealth <= (MaxHealth * 0.5) then
if NewHealth <= (MaxHealth * 0.175) then
ent:SetOnFire(true)
ent:SetOnSmoke(false)
else
ent:SetOnSmoke(true)
end
end
if MaxHealth > 30 and NewHealth <= 30 and ent:EngineActive() then
ent:DamagedStall()
end
if NewHealth <= 0 then
if type ~= DMG_GENERIC and type ~= DMG_CRUSH or damage > 400 then
hook.Run('VehicleDestroyed', ent)
DestroyVehicle(ent)
return
end
if ent:EngineActive() then
ent:DamagedStall()
end
return
end
end
simfphys.DamageVehicle = DamageVehicle
local function HurtPlayers(ent, damage)
-- if not simfphys.pDamageEnabled then return end
local Driver = ent:GetDriver()
if IsValid(Driver) then
Driver:TakeDamage(damage * (Driver:GetNetVar('belted') and 0.4 or 1), Entity(0), ent)
end
if ent.PassengerSeats then
for i = 1, table.Count(ent.PassengerSeats) do
local Passenger = ent.pSeat[i]:GetDriver()
if IsValid(Passenger) then
Passenger:TakeDamage(damage * (Passenger:GetNetVar('belted') and 0.4 or 1), Entity(0), ent)
end
end
end
end
local function bcDamage(vehicle , position , cdamage)
if not simfphys.DamageEnabled then return end
cdamage = cdamage or false
net.Start('simfphys_spritedamage')
net.WriteEntity(vehicle)
net.WriteVector(position)
net.WriteBool(cdamage)
net.Broadcast()
end
hook.Add('PhysgunDrop', 'dbg-cars.damage', function(ply, ent) ent.lastUnfreeze = CurTime() end)
hook.Add('PlayerSpawnedProp', 'dbg-cars.damage', function(ply, mdl, ent) ent.lastUnfreeze = CurTime() end)
local propClasses = octolib.array.toKeys({'prop_physics'})
local function onCollide(ent, data)
if ent._nodmg then return end
local ent2 = data.HitEntity
if IsValid(ent2) then
if ent2:GetClass():StartWith('npc_') then
Spark(data.HitPos , data.HitNormal , 'MetalVehicle.ImpactSoft')
return
end
if ent2.APG_Picked and propClasses[ent2:GetClass()] then
ent2:Remove()
return
end
if CurTime() - (ent2.lastUnfreeze or 0) < 5 then
ent._nodmg = true
timer.Simple(0.5, function()
if IsValid(ent) then ent._nodmg = nil end
end)
return
end
end
-- local vec
-- if ent2 == Entity(0) or not data.HitObject:IsMotionEnabled() then
-- vec = data.OurOldVelocity
-- else
-- vec = data.OurOldVelocity - data.TheirOldVelocity
-- end
-- local imp = vec:Length() * math.abs(vec:GetNormalized():Dot(data.HitNormal))
-- local mass = data.HitObject:GetMass()
-- if ent2 ~= Entity(0) and mass ~= 0 then
-- imp = imp / math.max(500 / mass, 1)
-- end
local imp = data.OurNewVelocity:Distance(data.OurOldVelocity)
if ent2:GetClass() == 'gmod_sent_vehicle_fphysics_base' then
imp = imp / math.Clamp(data.OurOldVelocity:LengthSqr() / data.TheirOldVelocity:LengthSqr(), 0.7, 1)
end
local pos = data.HitPos
local plyDmg, carDmg
if imp > 1200 then
Spark(pos , data.HitNormal , 'MetalVehicle.ImpactHard')
bcDamage(ent , ent:WorldToLocal(pos) , true)
plyDmg = imp * 0.07
carDmg = imp * 0.75
elseif imp > 800 then
Spark(pos , data.HitNormal , 'MetalVehicle.ImpactHard')
bcDamage(ent , ent:WorldToLocal(pos) , true)
plyDmg = imp * 0.05
carDmg = imp * 0.6
elseif imp > 400 then
bcDamage(ent , ent:WorldToLocal(pos) , true)
plyDmg = imp * 0.04
carDmg = imp * 0.45
elseif imp > 200 then
local hitent = ent2:IsPlayer()
if not hitent then
bcDamage(ent, ent:WorldToLocal(pos) , true)
carDmg = imp * 0.25
end
end
if plyDmg then HurtPlayers(ent, plyDmg) end
if carDmg and imp > 400 then
ent:TakeDamage(carDmg * simfphys.DamageMul, Entity(0), Entity(0))
-- reduce chance to not stall as we approach imp = 1500
local dontStallChance = octolib.math.remap(imp, 400, 1500, ent.police and 10 or 2, 0)
if math.random(10) > dontStallChance then
ent:DamagedStall()
end
end
if ent2:IsPlayer() and imp > 100 then
local ply = ent2
local dmg = DamageInfo()
dmg:SetDamage(math.Clamp(imp / 1.25, 0, ply:Health() - 10))
dmg:SetAttacker(ent:GetDriver() or Entity(0))
dmg:SetInflictor(ent)
dmg:SetDamageType(DMG_VEHICLE)
ply:TakeDamageInfo(dmg)
end
end
local function OnDamage(ent, dmginfo)
ent:TakePhysicsDamage(dmginfo)
if not ent:IsInitialized() then return end
local Damage = dmginfo:GetDamage()
local DamagePos = dmginfo:GetDamagePosition()
local Type = dmginfo:GetDamageType()
local Driver = ent:GetDriver()
bcDamage(ent , ent:WorldToLocal(DamagePos))
local Mul = 1
if Type == DMG_BLAST then
Mul = 10
end
if Type == DMG_BULLET then
Mul = 2
end
DamageVehicle(ent , Damage * Mul, Type)
-- if ent.IsArmored then return end
--
-- if IsValid(Driver) then
-- local Distance = (DamagePos - Driver:GetPos()):Length()
-- if (Distance < 40) then
-- local Damage = (40 - Distance) / 22
-- dmginfo:ScaleDamage(Damage)
-- Driver:TakeDamageInfo(dmginfo)
-- BloodEffect(DamagePos)
-- end
-- end
--
-- if ent.PassengerSeats then
-- for i = 1, table.Count(ent.PassengerSeats) do
-- local Passenger = ent.pSeat[i]:GetDriver()
--
-- if IsValid(Passenger) then
-- local Distance = (DamagePos - Passenger:GetPos()):Length()
-- local Damage = (40 - Distance) / 22
-- if (Distance < 40) then
-- dmginfo:ScaleDamage(Damage)
-- Passenger:TakeDamageInfo(dmginfo)
-- BloodEffect(DamagePos)
-- end
-- end
-- end
-- end
end
hook.Add('OnEntityCreated', 'simfphys_damagestuff', function(ent)
if simfphys.IsCar(ent) then
timer.Simple(0.2, function()
if not IsValid(ent) then return end
local Health = math.floor(ent.MaxHealth and ent.MaxHealth or (1000 + ent:GetPhysicsObject():GetMass() / 3))
ent:SetMaxHealth(Health)
ent:SetCurHealth(Health)
ent.PhysicsCollide = onCollide
ent.OnTakeDamage = OnDamage
end)
end
end)