Files
wnsrc/lua/arccw/server/sv_doors.lua
lifestorm 9c918c46e5 Upload
2024-08-04 23:12:27 +03:00

110 lines
4.3 KiB
Lua

--[[
| 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/
--]]
if CLIENT then return end
function ArcCW.DoorBust(ent, vel)
local cvar = ArcCW.ConVars["doorbust"]:GetInt()
local t = ArcCW.ConVars["doorbust_time"]:GetFloat()
if cvar == 0 or ent.ArcCW_DoorBusted then return end
ent.ArcCW_DoorBusted = true
local oldSpeed = ent:GetInternalVariable("m_flSpeed")
ent:Fire("SetSpeed", tostring(oldSpeed * 5), 0)
ent:Fire("Open", "", 0)
ent:Fire("SetSpeed", oldSpeed, 0.3)
if ent:GetPhysicsObject():IsValid() and cvar == 1 then
-- Don't remove the door, that's a silly thing to do
ent.ArcCW_DoorOldPos = ent:GetPos()
ent:SetNoDraw(true)
ent:SetNotSolid(true)
-- Make a busted door prop and fling it
local prop = ents.Create("prop_physics")
prop:SetModel(ent:GetModel())
prop:SetPos(ent:GetPos())
prop:SetAngles(ent:GetAngles())
prop:SetSkin(ent:GetSkin())
prop:Spawn()
prop:GetPhysicsObject():SetVelocity(vel)
ent:SetPos(ent:GetPos() - Vector(0, 0, 10000))
-- Make it not collide with players after a bit cause that's annoying
timer.Create("ArcCW_DoorBust_" .. prop:EntIndex(), 2, 1, function()
if IsValid(prop) then
prop:SetCollisionGroup(COLLISION_GROUP_WEAPON)
end
end)
-- Reset it after a while
SafeRemoveEntityDelayed(prop, t)
timer.Create("ArcCW_DoorBust_" .. ent:EntIndex(), t, 1, function()
if IsValid(ent) then
ent:SetNoDraw(false)
ent:SetNotSolid(false)
ent.ArcCW_DoorBusted = false
ent:SetPos(ent.ArcCW_DoorOldPos)
ent.ArcCW_DoorOldPos = nil
end
end)
else
timer.Create("ArcCW_DoorBust_" .. ent:EntIndex(), 0.5, 1, function()
if IsValid(ent) then
ent.ArcCW_DoorBusted = false
end
end)
end
end
function ArcCW.TryBustDoor(ent, dmginfo)
if ArcCW.ConVars["doorbust"]:GetInt() == 0 or !IsValid(ent) or !string.find(ent:GetClass(), "door") then return end
local wep = IsValid(dmginfo:GetAttacker()) and ((dmginfo:GetInflictor():IsWeapon() and dmginfo:GetInflictor()) or dmginfo:GetAttacker():GetActiveWeapon())
if !wep or !wep:IsWeapon() or !wep.ArcCW or !dmginfo:IsDamageType(DMG_BUCKSHOT) then return end
if ent:GetNoDraw() or ent.ArcCW_NoBust or ent.ArcCW_DoorBusted then return end
--- TTT may choose for some doors to not be openable by a crowbar, let's respect that
if GAMEMODE.crowbar_unlocks and GAMEMODE.crowbar_unlocks[ent] != true then return end
-- Magic number: 119.506 is the size of door01_left
-- The bigger the door is, the harder it is to bust
local threshold = ArcCW.ConVars["doorbust_threshold"]:GetInt() * math.pow((ent:OBBMaxs() - ent:OBBMins()):Length() / 119.506, 2)
-- Because shotgun damage is done per pellet, we must count them together
if ent.ArcCW_BustCurTime and (ent.ArcCW_BustCurTime + 0.1 < CurTime()) then
ent.ArcCW_BustCurTime = nil
ent.ArcCW_BustDamage = 0
end
if dmginfo:GetDamage() < (threshold - (ent.ArcCW_BustDamage or 0)) then
ent.ArcCW_BustCurTime = ent.ArcCW_BustCurTime or CurTime()
ent.ArcCW_BustDamage = (ent.ArcCW_BustDamage or 0) + dmginfo:GetDamage()
return
else
ent.ArcCW_BustCurTime = nil
ent.ArcCW_BustDamage = nil
end
ArcCW.DoorBust(ent, dmginfo:GetDamageForce() * 0.5)
-- Double doors are usually linked to the same areaportal. We must destroy the second half of the double door no matter what
for _, otherDoor in pairs(ents.FindInSphere(ent:GetPos(), 64)) do
if ent != otherDoor and otherDoor:GetClass() == ent:GetClass() and !otherDoor:GetNoDraw() then
ArcCW.DoorBust(otherDoor, dmginfo:GetDamageForce() * 0.5)
break
end
end
end
hook.Add("PlayerUse", "ArcCW_DoorBust", function(ply, ent)
if ent.ArcCW_DoorBusted then return false end
end)
-- This hook is not called on brush doors. Let's call this, uhh, intended behavior.
-- hook.Add("EntityTakeDamage", "ArcCW_DoorBust", ArcCW.TryBustDoor)