mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-16 21:33:46 +03:00
446 lines
16 KiB
Lua
446 lines
16 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
|
|
ArcCW.LastWeapon = nil
|
|
end
|
|
|
|
local vec1 = Vector(1, 1, 1)
|
|
local vec0 = vec1 * 0
|
|
local ang0 = Angle(0, 0, 0)
|
|
|
|
local lastUBGL = 0
|
|
function SWEP:Think()
|
|
if IsValid(self:GetOwner()) and self:GetClass() == "arccw_base" then
|
|
self:Remove()
|
|
return
|
|
end
|
|
|
|
local owner = self:GetOwner()
|
|
|
|
if !IsValid(owner) or owner:IsNPC() then return end
|
|
|
|
if self:GetState() == ArcCW.STATE_DISABLE and !self:GetPriorityAnim() then
|
|
self:SetState(ArcCW.STATE_IDLE)
|
|
|
|
if CLIENT and self.UnReady then
|
|
self.UnReady = false
|
|
end
|
|
end
|
|
|
|
for i, v in ipairs(self.EventTable) do
|
|
for ed, bz in pairs(v) do
|
|
if ed <= CurTime() then
|
|
if bz.AnimKey and (bz.AnimKey != self.LastAnimKey or bz.StartTime != self.LastAnimStartTime) then
|
|
continue
|
|
end
|
|
self:PlayEvent(bz)
|
|
self.EventTable[i][ed] = nil
|
|
--print(CurTime(), "Event completed at " .. i, ed)
|
|
if table.IsEmpty(v) and i != 1 then self.EventTable[i] = nil --[[print(CurTime(), "No more events at " .. i .. ", killing")]] end
|
|
end
|
|
end
|
|
end
|
|
|
|
if CLIENT and (!game.SinglePlayer() and IsFirstTimePredicted() or true)
|
|
and self:GetOwner() == LocalPlayer() and ArcCW.InvHUD
|
|
and !ArcCW.Inv_Hidden and ArcCW.Inv_Fade == 0 then
|
|
ArcCW.InvHUD:Remove()
|
|
ArcCW.Inv_Fade = 0.01
|
|
end
|
|
|
|
local vm = owner:GetViewModel()
|
|
|
|
self.BurstCount = self:GetBurstCount()
|
|
|
|
local sg = self:GetShotgunReloading()
|
|
if (sg == 2 or sg == 4) and owner:KeyPressed(IN_ATTACK) then
|
|
self:SetShotgunReloading(sg + 1)
|
|
elseif (sg >= 2) and self:GetReloadingREAL() <= CurTime() then
|
|
self:ReloadInsert((sg >= 4) and true or false)
|
|
end
|
|
|
|
self:InBipod()
|
|
|
|
if self:GetNeedCycle() and !self.Throwing and !self:GetReloading() and self:GetWeaponOpDelay() < CurTime() and self:GetNextPrimaryFire() < CurTime() and -- Adding this delays bolting if the RPM is too low, but removing it may reintroduce the double pump bug. Increasing the RPM allows you to shoot twice on many multiplayer servers. Sure would be convenient if everything just worked nicely
|
|
(!ArcCW.ConVars["clicktocycle"]:GetBool() and (self:GetCurrentFiremode().Mode == 2 or !owner:KeyDown(IN_ATTACK))
|
|
or ArcCW.ConVars["clicktocycle"]:GetBool() and (self:GetCurrentFiremode().Mode == 2 or owner:KeyPressed(IN_ATTACK))) then
|
|
local anim = self:SelectAnimation("cycle")
|
|
anim = self:GetBuff_Hook("Hook_SelectCycleAnimation", anim) or anim
|
|
local mult = self:GetBuff_Mult("Mult_CycleTime")
|
|
local p = self:PlayAnimation(anim, mult, true, 0, true)
|
|
if p then
|
|
self:SetNeedCycle(false)
|
|
self:SetPriorityAnim(CurTime() + self:GetAnimKeyTime(anim, true) * mult)
|
|
end
|
|
end
|
|
|
|
if self:GetGrenadePrimed() and !(owner:KeyDown(IN_ATTACK) or owner:KeyDown(IN_ATTACK2)) and (!game.SinglePlayer() or SERVER) then
|
|
self:Throw()
|
|
end
|
|
|
|
if self:GetGrenadePrimed() and self.GrenadePrimeTime > 0 and self.isCooked then
|
|
local heldtime = (CurTime() - self.GrenadePrimeTime)
|
|
|
|
local ft = self:GetBuff_Override("Override_FuseTime") or self.FuseTime
|
|
|
|
if ft and (heldtime >= ft) and (!game.SinglePlayer() or SERVER) then
|
|
self:Throw()
|
|
end
|
|
end
|
|
|
|
if IsFirstTimePredicted() and self:GetNextPrimaryFire() < CurTime() and owner:KeyReleased(IN_USE) then
|
|
if self:InBipod() then
|
|
self:ExitBipod()
|
|
else
|
|
self:EnterBipod()
|
|
end
|
|
end
|
|
|
|
if ((game.SinglePlayer() and SERVER) or (!game.SinglePlayer() and true)) and self:GetBuff_Override("Override_TriggerDelay", self.TriggerDelay) then
|
|
if owner:KeyReleased(IN_ATTACK) and self:GetBuff_Override("Override_TriggerCharge", self.TriggerCharge) and self:GetTriggerDelta(true) >= 1 then
|
|
self:PrimaryAttack()
|
|
else
|
|
self:DoTriggerDelay()
|
|
end
|
|
end
|
|
|
|
if self:GetCurrentFiremode().RunawayBurst then
|
|
|
|
if self:GetBurstCount() > 0 and ((game.SinglePlayer() and SERVER) or (!game.SinglePlayer() and true)) then
|
|
self:PrimaryAttack()
|
|
end
|
|
|
|
if self:Clip1() < self:GetBuff("AmmoPerShot") or self:GetBurstCount() == self:GetBurstLength() then
|
|
self:SetBurstCount(0)
|
|
if !self:GetCurrentFiremode().AutoBurst then
|
|
self.Primary.Automatic = false
|
|
end
|
|
end
|
|
end
|
|
|
|
if owner:KeyReleased(IN_ATTACK) then
|
|
|
|
if !self:GetCurrentFiremode().RunawayBurst then
|
|
self:SetBurstCount(0)
|
|
self.LastTriggerTime = -1 -- Cannot fire again until trigger released
|
|
self.LastTriggerDuration = 0
|
|
end
|
|
|
|
if self:GetCurrentFiremode().Mode < 0 and !self:GetCurrentFiremode().RunawayBurst then
|
|
local postburst = self:GetCurrentFiremode().PostBurstDelay or 0
|
|
|
|
if (CurTime() + postburst) > self:GetWeaponOpDelay() then
|
|
--self:SetNextPrimaryFire(CurTime() + postburst)
|
|
self:SetWeaponOpDelay(CurTime() + postburst * self:GetBuff_Mult("Mult_PostBurstDelay") + self:GetBuff_Add("Add_PostBurstDelay"))
|
|
end
|
|
end
|
|
end
|
|
|
|
if owner and owner:GetInfoNum("arccw_automaticreload", 0) == 1 and self:Clip1() == 0 and !self:GetReloading() and CurTime() > self:GetNextPrimaryFire() + 0.2 then
|
|
self:Reload()
|
|
end
|
|
|
|
if (!(self:GetBuff_Override("Override_ReloadInSights") or self.ReloadInSights) and (self:GetReloading() or owner:KeyDown(IN_RELOAD))) then
|
|
if !(self:GetBuff_Override("Override_ReloadInSights") or self.ReloadInSights) and self:GetReloading() then
|
|
self:ExitSights()
|
|
end
|
|
end
|
|
|
|
|
|
if self:GetBuff_Hook("Hook_ShouldNotSight") and (self.Sighted or self:GetState() == ArcCW.STATE_SIGHTS) then
|
|
self:ExitSights()
|
|
elseif self:GetHolster_Time() > 0 then
|
|
self:ExitSights()
|
|
else
|
|
|
|
-- no it really doesn't, past me
|
|
local sighted = self:GetState() == ArcCW.STATE_SIGHTS
|
|
local toggle = owner:GetInfoNum("arccw_toggleads", 0) >= 1
|
|
local suitzoom = owner:KeyDown(IN_ZOOM)
|
|
local sp_cl = game.SinglePlayer() and CLIENT
|
|
|
|
-- if in singleplayer, client realm should be completely ignored
|
|
if toggle and !sp_cl then
|
|
if owner:KeyPressed(IN_ATTACK2) then
|
|
if sighted then
|
|
self:ExitSights()
|
|
elseif !suitzoom then
|
|
self:EnterSights()
|
|
end
|
|
elseif suitzoom and sighted then
|
|
self:ExitSights()
|
|
end
|
|
elseif !toggle then
|
|
if (owner:KeyDown(IN_ATTACK2) and !suitzoom) and !sighted then
|
|
self:EnterSights()
|
|
elseif (!owner:KeyDown(IN_ATTACK2) or suitzoom) and sighted then
|
|
self:ExitSights()
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
if (!game.SinglePlayer() and IsFirstTimePredicted()) or (game.SinglePlayer() and true) then
|
|
if self:InSprint() and (self:GetState() != ArcCW.STATE_SPRINT) then
|
|
self:EnterSprint()
|
|
elseif !self:InSprint() and (self:GetState() == ArcCW.STATE_SPRINT) then
|
|
self:ExitSprint()
|
|
end
|
|
end
|
|
|
|
if game.SinglePlayer() or IsFirstTimePredicted() then
|
|
self:SetSightDelta(math.Approach(self:GetSightDelta(), self:GetState() == ArcCW.STATE_SIGHTS and 0 or 1, FrameTime() / self:GetSightTime()))
|
|
self:SetSprintDelta(math.Approach(self:GetSprintDelta(), self:GetState() == ArcCW.STATE_SPRINT and 1 or 0, FrameTime() / self:GetSprintTime()))
|
|
end
|
|
|
|
if CLIENT and (game.SinglePlayer() or IsFirstTimePredicted()) then
|
|
self:ProcessRecoil()
|
|
end
|
|
|
|
if CLIENT and IsValid(vm) then
|
|
|
|
for i = 1, vm:GetBoneCount() do
|
|
vm:ManipulateBoneScale(i, vec1)
|
|
end
|
|
|
|
for i, k in pairs(self:GetBuff_Override("Override_CaseBones", self.CaseBones) or {}) do
|
|
if !isnumber(i) then continue end
|
|
for _, b in pairs(istable(k) and k or {k}) do
|
|
local bone = vm:LookupBone(b)
|
|
|
|
if !bone then continue end
|
|
|
|
if self:GetVisualClip() >= i then
|
|
vm:ManipulateBoneScale(bone, vec1)
|
|
else
|
|
vm:ManipulateBoneScale(bone, vec0)
|
|
end
|
|
end
|
|
end
|
|
|
|
for i, k in pairs(self:GetBuff_Override("Override_BulletBones", self.BulletBones) or {}) do
|
|
if !isnumber(i) then continue end
|
|
for _, b in pairs(istable(k) and k or {k}) do
|
|
local bone = vm:LookupBone(b)
|
|
|
|
if !bone then continue end
|
|
|
|
if self:GetVisualBullets() >= i then
|
|
vm:ManipulateBoneScale(bone, vec1)
|
|
else
|
|
vm:ManipulateBoneScale(bone, vec0)
|
|
end
|
|
end
|
|
end
|
|
|
|
for i, k in pairs(self:GetBuff_Override("Override_StripperClipBones", self.StripperClipBones) or {}) do
|
|
if !isnumber(i) then continue end
|
|
for _, b in pairs(istable(k) and k or {k}) do
|
|
local bone = vm:LookupBone(b)
|
|
|
|
if !bone then continue end
|
|
|
|
if self:GetVisualLoadAmount() >= i then
|
|
vm:ManipulateBoneScale(bone, vec1)
|
|
else
|
|
vm:ManipulateBoneScale(bone, vec0)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
self:DoHeat()
|
|
|
|
self:ThinkFreeAim()
|
|
|
|
-- if CLIENT then
|
|
-- if !IsValid(ArcCW.InvHUD) then
|
|
-- gui.EnableScreenClicker(false)
|
|
-- end
|
|
|
|
-- if self:GetState() != ArcCW.STATE_CUSTOMIZE then
|
|
-- self:CloseCustomizeHUD()
|
|
-- else
|
|
-- self:OpenCustomizeHUD()
|
|
-- end
|
|
-- end
|
|
|
|
for i, k in pairs(self.Attachments) do
|
|
if !k.Installed then continue end
|
|
local atttbl = ArcCW.AttachmentTable[k.Installed]
|
|
|
|
if atttbl.DamagePerSecond then
|
|
local dmg = atttbl.DamagePerSecond * FrameTime()
|
|
|
|
self:DamageAttachment(i, dmg)
|
|
end
|
|
end
|
|
|
|
if CLIENT then
|
|
self:DoOurViewPunch()
|
|
end
|
|
|
|
if self.Throwing and self:Clip1() == 0 and self:Ammo1() > 0 then
|
|
self:SetClip1(1)
|
|
owner:SetAmmo(self:Ammo1() - 1, self.Primary.Ammo)
|
|
end
|
|
|
|
-- self:RefreshBGs()
|
|
|
|
if self:GetMagUpIn() != 0 and CurTime() > self:GetMagUpIn() then
|
|
self:ReloadTimed()
|
|
self:SetMagUpIn( 0 )
|
|
end
|
|
|
|
if self:HasBottomlessClip() and self:Clip1() != ArcCW.BottomlessMagicNumber then
|
|
self:Unload()
|
|
self:SetClip1(ArcCW.BottomlessMagicNumber)
|
|
elseif !self:HasBottomlessClip() and self:Clip1() == ArcCW.BottomlessMagicNumber then
|
|
self:SetClip1(0)
|
|
end
|
|
|
|
-- Performing traces in rendering contexts seem to cause flickering with c_hands that have QC attachments(?)
|
|
-- Since we need to run the trace every tick anyways, do it here instead
|
|
if CLIENT then
|
|
self:BarrelHitWall()
|
|
end
|
|
|
|
self:GetBuff_Hook("Hook_Think")
|
|
|
|
-- Running this only serverside in SP breaks animation processing and causes CheckpointAnimation to !reset.
|
|
--if SERVER or !game.SinglePlayer() then
|
|
self:ProcessTimers()
|
|
--end
|
|
|
|
-- Only reset to idle if we don't need cycle. empty idle animation usually doesn't play nice
|
|
if self:GetNextIdle() != 0 and self:GetNextIdle() <= CurTime() and !self:GetNeedCycle()
|
|
and self:GetHolster_Time() == 0 and self:GetShotgunReloading() == 0 then
|
|
self:SetNextIdle(0)
|
|
self:PlayIdleAnimation(true)
|
|
end
|
|
|
|
if self:GetUBGLDebounce() and !self:GetOwner():KeyDown(IN_RELOAD) then
|
|
self:SetUBGLDebounce( false )
|
|
end
|
|
end
|
|
|
|
local lst = SysTime()
|
|
|
|
function SWEP:ProcessRecoil()
|
|
local owner = self:GetOwner()
|
|
local ft = (SysTime() - (lst or SysTime())) * GetConVar("host_timescale"):GetFloat()
|
|
local newang = owner:EyeAngles()
|
|
-- local r = self.RecoilAmount -- self:GetNWFloat("recoil", 0)
|
|
-- local rs = self.RecoilAmountSide -- self:GetNWFloat("recoilside", 0)
|
|
|
|
local ra = Angle(ang0)
|
|
|
|
ra = ra + (self:GetBuff_Override("Override_RecoilDirection", self.RecoilDirection) * self.RecoilAmount * 0.5)
|
|
ra = ra + (self:GetBuff_Override("Override_RecoilDirectionSide", self.RecoilDirectionSide) * self.RecoilAmountSide * 0.5)
|
|
|
|
newang = newang - ra
|
|
|
|
local rpb = self.RecoilPunchBack
|
|
local rps = self.RecoilPunchSide
|
|
local rpu = self.RecoilPunchUp
|
|
|
|
if rpb != 0 then
|
|
self.RecoilPunchBack = math.Approach(rpb, 0, ft * rpb * 10)
|
|
end
|
|
|
|
if rps != 0 then
|
|
self.RecoilPunchSide = math.Approach(rps, 0, ft * rps * 5)
|
|
end
|
|
|
|
if rpu != 0 then
|
|
self.RecoilPunchUp = math.Approach(rpu, 0, ft * rpu * 5)
|
|
end
|
|
|
|
lst = SysTime()
|
|
end
|
|
|
|
function SWEP:InSprint()
|
|
local owner = self:GetOwner()
|
|
|
|
local sm = self.SpeedMult * self:GetBuff_Mult("Mult_SpeedMult") * self:GetBuff_Mult("Mult_MoveSpeed")
|
|
|
|
sm = math.Clamp(sm, 0, 1)
|
|
|
|
local sprintspeed = owner:GetRunSpeed() * sm
|
|
local walkspeed = owner:GetWalkSpeed() * sm
|
|
|
|
local curspeed = owner:GetVelocity():Length()
|
|
|
|
if TTT2 and owner.isSprinting == true then
|
|
return (owner.sprintProgress or 0) > 0 and owner:KeyDown(IN_SPEED) and !owner:Crouching() and curspeed > walkspeed and owner:OnGround()
|
|
end
|
|
|
|
if !owner:KeyDown(IN_SPEED) or !owner:KeyDown(IN_FORWARD+IN_MOVELEFT+IN_MOVERIGHT+IN_BACK) then return false end
|
|
if !owner:OnGround() then return false end
|
|
if owner:Crouching() then return false end
|
|
if curspeed < Lerp(0.5, walkspeed, sprintspeed) then
|
|
-- provide some grace time so changing directions won't immediately exit sprint
|
|
self.LastExitSprintCheck = self.LastExitSprintCheck or CurTime()
|
|
if self.LastExitSprintCheck < CurTime() - 0.25 then
|
|
return false
|
|
end
|
|
else
|
|
self.LastExitSprintCheck = nil
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
function SWEP:IsTriggerHeld()
|
|
return self:GetOwner():KeyDown(IN_ATTACK) and (self:CanShootWhileSprint() or (!self.Sprinted or self:GetState() != ArcCW.STATE_SPRINT)) and (self:GetHolster_Time() < CurTime()) and !self:GetPriorityAnim()
|
|
end
|
|
|
|
SWEP.LastTriggerTime = 0
|
|
SWEP.LastTriggerDuration = 0
|
|
function SWEP:GetTriggerDelta(noheldcheck)
|
|
if self.LastTriggerTime <= 0 or (!noheldcheck and !self:IsTriggerHeld()) then return 0 end
|
|
return math.Clamp((CurTime() - self.LastTriggerTime) / self.LastTriggerDuration, 0, 1)
|
|
end
|
|
|
|
function SWEP:DoTriggerDelay()
|
|
local shouldHold = self:IsTriggerHeld()
|
|
|
|
local reserve = self:HasBottomlessClip() and self:Ammo1() or self:Clip1()
|
|
if self.LastTriggerTime == -1 or (!self.TriggerPullWhenEmpty and (reserve < self:GetBuff("AmmoPerShot"))) and self:GetNextPrimaryFire() < CurTime() then
|
|
if !shouldHold then
|
|
self.LastTriggerTime = 0 -- Good to fire again
|
|
self.LastTriggerDuration = 0
|
|
end
|
|
return
|
|
end
|
|
|
|
if self:GetBurstCount() > 0 and self:GetCurrentFiremode().Mode == 1 then
|
|
self.LastTriggerTime = -1 -- Cannot fire again until trigger released
|
|
self.LastTriggerDuration = 0
|
|
elseif self:GetNextPrimaryFire() < CurTime() and self.LastTriggerTime > 0 and !shouldHold then
|
|
-- Attack key is released. Stop the animation and clear progress
|
|
local anim = self:SelectAnimation("untrigger")
|
|
if anim then
|
|
self:PlayAnimation(anim, self:GetBuff_Mult("Mult_TriggerDelayTime"), true, 0)
|
|
end
|
|
self.LastTriggerTime = 0
|
|
self.LastTriggerDuration = 0
|
|
self:GetBuff_Hook("Hook_OnTriggerRelease")
|
|
elseif self:GetNextPrimaryFire() < CurTime() and self.LastTriggerTime == 0 and shouldHold then
|
|
-- We haven't played the animation yet. Pull it!
|
|
local anim = self:SelectAnimation("trigger")
|
|
self:PlayAnimation(anim, self:GetBuff_Mult("Mult_TriggerDelayTime"), true, 0, nil, nil, true) -- need to overwrite sprint up
|
|
self.LastTriggerTime = CurTime()
|
|
self.LastTriggerDuration = self:GetAnimKeyTime(anim, true) * self:GetBuff_Mult("Mult_TriggerDelayTime")
|
|
self:GetBuff_Hook("Hook_OnTriggerHeld")
|
|
end
|
|
end
|