140 lines
4.4 KiB
Lua
140 lines
4.4 KiB
Lua
|
|
local function draw_debug()
|
|
return (CLIENT or game.SinglePlayer()) and TacRP.Developer(2)
|
|
end
|
|
|
|
local function IsPenetrating(ptr, ptrent)
|
|
if ptrent:IsWorld() then
|
|
return ptr.Contents != CONTENTS_EMPTY
|
|
elseif IsValid(ptrent) then
|
|
|
|
local withinbounding = false
|
|
local hboxset = ptrent:GetHitboxSet()
|
|
local hitbone = ptrent:GetHitBoxBone(ptr.HitBox, hboxset)
|
|
if hitbone then
|
|
-- If we hit a hitbox, compare against that hitbox only
|
|
local mins, maxs = ptrent:GetHitBoxBounds(ptr.HitBox, hboxset)
|
|
local bonepos, boneang = ptrent:GetBonePosition(hitbone)
|
|
mins = mins * 1.1
|
|
maxs = maxs * 1.1
|
|
local lpos = WorldToLocal(ptr.HitPos, ptr.HitNormal:Angle(), bonepos, boneang)
|
|
|
|
withinbounding = lpos:WithinAABox(mins, maxs)
|
|
if draw_debug() then
|
|
debugoverlay.BoxAngles(bonepos, mins, maxs, boneang, 5, Color(255, 255, 255, 10))
|
|
end
|
|
elseif util.PointContents(ptr.HitPos) != CONTENTS_EMPTY then
|
|
-- Otherwise default to rotated OBB
|
|
local mins, maxs = ptrent:OBBMins(), ptrent:OBBMaxs()
|
|
withinbounding = ptrent:WorldToLocal(ptr.HitPos):WithinAABox(mins, maxs)
|
|
if draw_debug() then
|
|
debugoverlay.BoxAngles(ptrent:GetPos(), mins, maxs, ptrent:GetAngles(), 5, Color(255, 255, 255, 10))
|
|
end
|
|
end
|
|
if draw_debug() then
|
|
debugoverlay.Cross(ptr.HitPos, withinbounding and 4 or 6, 5, withinbounding and Color(255, 255, 0) or Color(128, 255, 0), true)
|
|
end
|
|
|
|
return withinbounding
|
|
end
|
|
return false
|
|
end
|
|
|
|
function SWEP:Penetrate(tr, range, penleft, alreadypenned)
|
|
if !TacRP.ConVars["penetration"]:GetBool() then return end
|
|
|
|
if !IsValid(self:GetOwner()) then return end
|
|
|
|
local hitpos, startpos = tr.HitPos, tr.StartPos
|
|
local dir = (hitpos - startpos):GetNormalized()
|
|
|
|
if tr.HitSky then return end
|
|
|
|
if penleft <= 0 then return end
|
|
|
|
alreadypenned = alreadypenned or {}
|
|
|
|
local skip = false
|
|
|
|
local trent = tr.Entity
|
|
|
|
local penmult = TacRP.PenTable[tr.MatType] or 1
|
|
|
|
local pentracelen = math.max(penleft * penmult / 2, 2)
|
|
local curr_ent = trent
|
|
|
|
if !tr.HitWorld then penmult = penmult * 0.5 end
|
|
if trent.Impenetrable then penmult = 100000 end
|
|
if trent.mmRHAe then penmult = trent.mmRHAe end
|
|
|
|
-- penmult = penmult * math.Rand(0.9, 1.1) * math.Rand(0.9, 1.1)
|
|
|
|
local endpos = hitpos
|
|
|
|
local td = {}
|
|
td.start = endpos
|
|
td.endpos = endpos + (dir * pentracelen)
|
|
td.mask = MASK_SHOT
|
|
|
|
local ptr = util.TraceLine(td)
|
|
|
|
local ptrent = ptr.Entity
|
|
|
|
while !skip and penleft > 0 and IsPenetrating(ptr, ptrent) and ptr.Fraction < 1 and ptrent == curr_ent do
|
|
penleft = penleft - (pentracelen * penmult)
|
|
|
|
td.start = endpos
|
|
td.endpos = endpos + (dir * pentracelen)
|
|
td.mask = MASK_SHOT
|
|
|
|
ptr = util.TraceLine(td)
|
|
|
|
if TacRP.Developer() then
|
|
local pdeltap = penleft / self:GetValue("Penetration")
|
|
local colorlr = Lerp(pdeltap, 0, 255)
|
|
|
|
debugoverlay.Line(endpos, endpos + (dir * pentracelen), 10, Color(255, colorlr, colorlr), true)
|
|
end
|
|
|
|
endpos = endpos + (dir * pentracelen)
|
|
range = range + pentracelen
|
|
|
|
ptrent = ptr.Entity
|
|
end
|
|
|
|
if penleft > 0 then
|
|
if (dir:Length() == 0) then return end
|
|
|
|
self:GetOwner():FireBullets({
|
|
Damage = self:GetValue("Damage_Max"),
|
|
Force = 4,
|
|
Tracer = 0,
|
|
Num = 1,
|
|
Dir = dir,
|
|
Src = endpos,
|
|
Callback = function(att, btr, dmg)
|
|
range = range + (btr.HitPos - btr.StartPos):Length()
|
|
self:AfterShotFunction(btr, dmg, range, penleft, alreadypenned)
|
|
|
|
if TacRP.Developer() then
|
|
if SERVER then
|
|
debugoverlay.Cross(btr.HitPos, 4, 5, Color(255, 0, 0), false)
|
|
else
|
|
debugoverlay.Cross(btr.HitPos, 4, 5, Color(255, 255, 255), false)
|
|
end
|
|
end
|
|
end
|
|
})
|
|
|
|
self:GetOwner():FireBullets({
|
|
Damage = 0,
|
|
Force = 0,
|
|
Tracer = 0,
|
|
Num = 1,
|
|
Distance = 1,
|
|
Dir = -dir,
|
|
Src = endpos,
|
|
})
|
|
end
|
|
end
|