mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 21:53:46 +03:00
Upload
This commit is contained in:
250
lua/entities/lvs_base/sv_physics_damagesystem.lua
Normal file
250
lua/entities/lvs_base/sv_physics_damagesystem.lua
Normal file
@@ -0,0 +1,250 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
ENT._pdsParts = {}
|
||||
|
||||
ENT.PDSDamageVelocity = 100
|
||||
ENT.PDSDamageMultiplier = 0.05
|
||||
|
||||
function ENT:ClearPDS()
|
||||
if not istable( self._pdsParts ) then return end
|
||||
|
||||
table.Empty( self._pdsParts )
|
||||
end
|
||||
|
||||
function ENT:PDSHealthValueChanged( name, old, new)
|
||||
if new == old then return end
|
||||
|
||||
if not self:IsInitialized() or not istable( self._pdsParts ) or new ~= self:GetMaxHP() then return end
|
||||
|
||||
for _, part in pairs( self._pdsParts ) do
|
||||
part:SetStage( 0 )
|
||||
|
||||
if not part._group or not part._subgroup then continue end
|
||||
|
||||
self:SetBodygroup( part._group, part._subgroup )
|
||||
|
||||
part._group = nil
|
||||
part._subgroup = nil
|
||||
end
|
||||
end
|
||||
|
||||
local function DamagePart( ent, part, speed )
|
||||
if not speed then
|
||||
speed = 0
|
||||
end
|
||||
|
||||
local stage = part:GetStage() + 1
|
||||
|
||||
part:SetStage( stage )
|
||||
|
||||
local data = part:GetStageData()
|
||||
|
||||
if isfunction( data.Callback ) then
|
||||
data:Callback( ent, part, speed )
|
||||
end
|
||||
|
||||
if istable( data.bodygroup ) then
|
||||
for group, subgroup in pairs( data.bodygroup ) do
|
||||
if not part._group or not part._subgroup then
|
||||
part._group = group
|
||||
part._subgroup = ent:GetBodygroup( group )
|
||||
end
|
||||
|
||||
ent:SetBodygroup( group, subgroup )
|
||||
end
|
||||
end
|
||||
|
||||
if isstring( data.sound ) then
|
||||
ent:EmitSound( data.sound, 75, 100, math.min(0.1 + speed / 700,1) )
|
||||
end
|
||||
|
||||
if isstring( data.effect ) then
|
||||
local effectdata = EffectData()
|
||||
effectdata:SetOrigin( ent:LocalToWorld( part.pos ) )
|
||||
util.Effect( data.effect, effectdata, true, true )
|
||||
end
|
||||
|
||||
if not istable( data.gib ) or not data.gib.mdl then return end
|
||||
|
||||
timer.Simple(0, function()
|
||||
if not IsValid( ent ) then return end
|
||||
|
||||
local InvAttach = isstring( data.gib.target )
|
||||
|
||||
local pos
|
||||
local ang
|
||||
|
||||
if InvAttach then
|
||||
pos = vector_origin
|
||||
ang = angle_zero
|
||||
else
|
||||
if isvector( data.gib.pos ) and isangle( data.gib.ang ) then
|
||||
pos = ent:LocalToWorld( data.gib.pos )
|
||||
ang = ent:LocalToWorldAngles( data.gib.ang )
|
||||
end
|
||||
end
|
||||
|
||||
local gib = ents.Create( "prop_physics" )
|
||||
gib:SetModel( data.gib.mdl )
|
||||
gib:SetPos( pos )
|
||||
gib:SetAngles( ang )
|
||||
gib:Spawn()
|
||||
gib:Activate()
|
||||
gib:SetCollisionGroup( COLLISION_GROUP_DEBRIS )
|
||||
gib:SetSkin( ent:GetSkin() )
|
||||
|
||||
if InvAttach then
|
||||
local att = gib:GetAttachment( gib:LookupAttachment( data.gib.target ) )
|
||||
|
||||
if att then
|
||||
local newpos = ent:LocalToWorld( -att.Pos )
|
||||
local newang = ent:LocalToWorldAngles( -att.Ang )
|
||||
|
||||
gib:SetPos( newpos )
|
||||
gib:SetAngles( newang )
|
||||
end
|
||||
end
|
||||
|
||||
gib:SetOwner( ent )
|
||||
gib:SetColor( ent:GetColor() )
|
||||
gib:SetRenderMode( RENDERMODE_TRANSALPHA )
|
||||
|
||||
ent:DeleteOnRemove( gib )
|
||||
ent:TransferCPPI( gib )
|
||||
|
||||
timer.Simple( 59.5, function()
|
||||
if not IsValid( gib ) then return end
|
||||
gib:SetRenderFX( kRenderFxFadeFast )
|
||||
end)
|
||||
|
||||
timer.Simple( 60, function()
|
||||
if not IsValid( gib ) then return end
|
||||
gib:Remove()
|
||||
end)
|
||||
|
||||
local PhysObj = gib:GetPhysicsObject()
|
||||
|
||||
if not IsValid( PhysObj ) then return end
|
||||
|
||||
PhysObj:SetVelocityInstantaneous( ent:GetVelocity() + Vector(0,0,250) )
|
||||
PhysObj:AddAngleVelocity( VectorRand() * 500 )
|
||||
end)
|
||||
end
|
||||
|
||||
function ENT:AddPDS( data )
|
||||
if not data then return end
|
||||
|
||||
if self._pdsPartsID then
|
||||
self._pdsPartsID = self._pdsPartsID + 1
|
||||
else
|
||||
self._pdsPartsID = 1
|
||||
end
|
||||
|
||||
data.pos = data.pos or Vector(0,0,0)
|
||||
data.ang = data.ang or Angle(0,0,0)
|
||||
data.mins = data.mins or Vector(-1,-1,-1)
|
||||
data.maxs = data.maxs or Vector(1,1,1)
|
||||
data.stages = data.stages or {}
|
||||
data.GetStage = function( self )
|
||||
if not self._curstage then
|
||||
self._curstage = 0
|
||||
end
|
||||
|
||||
return self._curstage
|
||||
end
|
||||
data.SetStage = function( self, stage )
|
||||
self._curstage = stage
|
||||
end
|
||||
|
||||
data.GetStageData = function( self, stage )
|
||||
return self.stages[ self:GetStage() ] or {}
|
||||
end
|
||||
|
||||
debugoverlay.BoxAngles( self:LocalToWorld( data.pos ), data.mins, data.maxs, self:LocalToWorldAngles( data.ang ), 8, Color( 50, 50, 0, 150 ) )
|
||||
|
||||
self._pdsParts[ self._pdsPartsID ] = data
|
||||
|
||||
if data.allow_damage then
|
||||
local id = self._pdsPartsID
|
||||
|
||||
self:AddDS( {
|
||||
pos = data.pos,
|
||||
ang = data.ang,
|
||||
mins = data.mins,
|
||||
maxs = data.maxs,
|
||||
Callback = function( tbl, ent, dmginfo )
|
||||
if not IsValid( ent ) then return end
|
||||
|
||||
local part = ent._pdsParts[ id ]
|
||||
|
||||
if not part then return end
|
||||
|
||||
DamagePart( ent, part, 1000 )
|
||||
end
|
||||
} )
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:FindPDS( PosToCheck, RadiusAdd )
|
||||
if not isnumber( RadiusAdd ) then
|
||||
RadiusAdd = 1
|
||||
end
|
||||
|
||||
local Parts = {}
|
||||
|
||||
debugoverlay.Cross( PosToCheck, 50, 4, Color( 255, 255, 0 ) )
|
||||
|
||||
for index, part in ipairs( self._pdsParts ) do
|
||||
local mins = part.mins
|
||||
local maxs = part.maxs
|
||||
local pos = self:LocalToWorld( part.pos )
|
||||
local ang = self:LocalToWorldAngles( part.ang )
|
||||
local dir = (pos - PosToCheck):GetNormalized()
|
||||
|
||||
local HitPos, HitNormal, Fraction = util.IntersectRayWithOBB( PosToCheck, dir * RadiusAdd, pos, ang, mins, maxs )
|
||||
|
||||
if HitPos then
|
||||
table.insert( Parts, part )
|
||||
end
|
||||
end
|
||||
|
||||
for _, closestPart in ipairs( Parts ) do
|
||||
local mins = closestPart.mins
|
||||
local maxs = closestPart.maxs
|
||||
local pos = self:LocalToWorld( closestPart.pos )
|
||||
local ang = self:LocalToWorldAngles( closestPart.ang )
|
||||
debugoverlay.BoxAngles( pos, mins, maxs, ang, 1, Color( 255, 255, 0, 150 ) )
|
||||
end
|
||||
|
||||
return Parts
|
||||
end
|
||||
|
||||
function ENT:CalcPDS( physdata )
|
||||
local VelDif = math.abs( physdata.OurOldVelocity:Length() - physdata.OurNewVelocity:Length() )
|
||||
|
||||
if VelDif < self.PDSDamageVelocity then return end
|
||||
|
||||
local parts = self:FindPDS( physdata.HitPos, (VelDif - self.PDSDamageVelocity) * self.PDSDamageMultiplier )
|
||||
|
||||
if #parts == 0 then return end
|
||||
|
||||
local HP = self:GetHP()
|
||||
local MaxHP = self:GetMaxHP()
|
||||
|
||||
if HP == MaxHP then
|
||||
self:SetHP( math.max( MaxHP - 0.1, 1 ) )
|
||||
end
|
||||
|
||||
for _, part in pairs( parts ) do
|
||||
DamagePart( self, part, VelDif )
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user