Files
wnsrc/lua/weapons/arccw_base/cl_viewmodel.lua
lifestorm 94063e4369 Upload
2024-08-04 22:55:00 +03:00

888 lines
33 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/
--]]
--[[
Please, for the love of god, don't create objects in functions that are called multiple times per frame.
The garbage collector will explode and so will players' comptuters.
That means minimize usage of things that generate new objects, including:
calls to Vector() or Angle(); use vector_origin and angle_zero if the value isn't modified
arithmetic using +, -, * and / on Vectors and Angles; modifying individual parameters is fine
functions like Angle:Right() and Vector:Angle(); however functions like Vector:Add() and Angle:Add() are fine
Cache them if you use them more than one time!
]]
local mth = math
local m_appor = mth.Approach
local m_clamp = mth.Clamp
local f_lerp = Lerp
local srf = surface
SWEP.ActualVMData = false
local swayxmult, swayymult, swayzmult, swayspeed = 1, 1, 1, 1
local lookxmult, lookymult = 1, 1
SWEP.VMPos = Vector()
SWEP.VMAng = Angle()
SWEP.VMPosOffset = Vector()
SWEP.VMAngOffset = Angle()
SWEP.VMPosOffset_Lerp = Vector()
SWEP.VMAngOffset_Lerp = Angle()
SWEP.VMLookLerp = Angle()
SWEP.StepBob = 0
SWEP.StepBobLerp = 0
SWEP.StepRandomX = 1
SWEP.StepRandomY = 1
SWEP.LastEyeAng = Angle()
SWEP.SmoothEyeAng = Angle()
SWEP.LastVelocity = Vector()
SWEP.Velocity_Lerp = Vector()
SWEP.VelocityLastDiff = 0
SWEP.Breath_Intensity = 1
SWEP.Breath_Rate = 1
-- magic variables
local sprint_vec1 = Vector(-2, 5, 2)
local sprint_vec2 = Vector(0, 7, 3)
local sprint_ang1 = Angle(-15, -15, 0)
local spring_ang2 = Angle(-15, 15, -22)
local sight_vec1 = Vector(0, 15, -4)
local sight_vec2 = Vector(1, 5, -1)
local sight_ang1 = Angle(0, 0, -45)
local sight_ang2 = Angle(-5, 0, -10)
local sextra_vec = Vector(0.0002, 0.001, 0.005)
local procdraw_vec = Vector(0, 0, -5)
local procdraw_ang = Angle(-70, 30, 0)
local prochol_ang = Angle(-70, 30, 10)
local lst = SysTime()
local function scrunkly()
local ret = (SysTime() - (lst or SysTime())) * GetConVar("host_timescale"):GetFloat()
return ret
end
local function LerpC(t, a, b, powa)
return a + (b - a) * math.pow(t, powa)
end
local function ApproachMod(usrobj, to, dlt)
usrobj[1] = m_appor(usrobj[1], to[1], dlt)
usrobj[2] = m_appor(usrobj[2], to[2], dlt)
usrobj[3] = m_appor(usrobj[3], to[3], dlt)
end
local function LerpMod(usrobj, to, dlt, clamp_ang)
usrobj[1] = f_lerp(dlt, usrobj[1], to[1])
usrobj[2] = f_lerp(dlt, usrobj[2], to[2])
usrobj[3] = f_lerp(dlt, usrobj[3], to[3])
if clamp_ang then
for i = 1, 3 do usrobj[i] = math.NormalizeAngle(usrobj[i]) end
end
end
local function LerpMod2(from, usrobj, dlt, clamp_ang)
usrobj[1] = f_lerp(dlt, from[1], usrobj[1])
usrobj[2] = f_lerp(dlt, from[2], usrobj[2])
usrobj[3] = f_lerp(dlt, from[3], usrobj[3])
if clamp_ang then
for i = 1, 3 do usrobj[i] = math.NormalizeAngle(usrobj[i]) end
end
end
-- debug for testing garbage count
-- TODO: comment this out or something before actually going into main branch
local sw = false
local tries = {}
local totaltries = 1000
local sw_start = 0
local sw_orig = 0
concommand.Add("arccw_dev_stopwatch", function() tries = {} sw = true end)
local function stopwatch(name)
if !sw then return end
if name == true then
local d = (collectgarbage("count") - sw_orig)
if #tries == 0 then print(" total garbage: " .. d) end
table.insert(tries, d)
if #tries == totaltries then
sw = false
local average = 0
for _, v in ipairs(tries) do average = average + v end
average = average / totaltries
print("----------------------------------")
print("average over " .. totaltries .. " tries: " .. average)
end
return
end
local gb = collectgarbage("count")
if name then
if #tries == 0 then print(name .. ": " .. (gb - sw_start)) end
else
if #tries == 0 then print("----------------------------------") end
sw_orig = gb
end
sw_start = gb
end
function SWEP:Move_Process(EyePos, EyeAng, velocity)
local VMPos, VMAng = self.VMPos, self.VMAng
local VMPosOffset, VMAngOffset = self.VMPosOffset, self.VMAngOffset
local VMPosOffset_Lerp, VMAngOffset_Lerp = self.VMPosOffset_Lerp, self.VMAngOffset_Lerp
local FT = scrunkly()
local sightedmult = (self:GetState() == ArcCW.STATE_SIGHTS and 0.05) or 1
local sg = self:GetSightDelta()
VMPos:Set(EyePos)
VMAng:Set(EyeAng)
VMPosOffset.x = math.Clamp(velocity.z * 0.0025, -1, 1) * sightedmult
VMPosOffset.x = VMPosOffset.x + (velocity.x * 0.001 * sg)
VMPosOffset.y = math.Clamp(velocity.y * -0.002, -1, 1) * sightedmult
VMPosOffset.z = math.Clamp(VMPosOffset.x * -2, -4, 4)
VMPosOffset_Lerp.x = Lerp(8 * FT, VMPosOffset_Lerp.x, VMPosOffset.x)
VMPosOffset_Lerp.y = Lerp(8 * FT, VMPosOffset_Lerp.y, VMPosOffset.y)
VMPosOffset_Lerp.z = Lerp(8 * FT, VMPosOffset_Lerp.z, VMPosOffset.z)
--VMAngOffset.x = math.Clamp(VMPosOffset.x * 8, -4, 4)
VMAngOffset.y = VMPosOffset.y
VMAngOffset.z = VMPosOffset.y * 0.5 + (VMPosOffset.x * -5) + (velocity.x * -0.005 * sg)
VMAngOffset_Lerp.x = LerpC(10 * FT, VMAngOffset_Lerp.x, VMAngOffset.x, 0.75)
VMAngOffset_Lerp.y = LerpC(5 * FT, VMAngOffset_Lerp.y, VMAngOffset.y, 0.6)
VMAngOffset_Lerp.z = Lerp(25 * FT, VMAngOffset_Lerp.z, VMAngOffset.z)
VMPos:Add(VMAng:Up() * VMPosOffset_Lerp.x)
VMPos:Add(VMAng:Right() * VMPosOffset_Lerp.y)
VMPos:Add(VMAng:Forward() * VMPosOffset_Lerp.z)
VMAngOffset_Lerp:Normalize()
VMAng:Add(VMAngOffset_Lerp)
end
local stepend = math.pi * 4
function SWEP:Step_Process(EyePos, EyeAng, velocity)
local VMPos, VMAng = self.VMPos, self.VMAng
local VMPosOffset, VMAngOffset = self.VMPosOffset, self.VMAngOffset
local VMPosOffset_Lerp = self.VMPosOffset_Lerp
local state = self:GetState()
local sprd = self:GetSprintDelta()
if state == ArcCW.STATE_SPRINT and self:SelectAnimation("idle_sprint") and !self:GetReloading() and !self:CanShootWhileSprint() then
velocity = 0
else
velocity = math.min(velocity:Length(), 400) * Lerp(sprd, 1, 1.25)
end
local delta = math.abs(self.StepBob * 2 / stepend - 1)
local FT = scrunkly() --FrameTime()
local sightedmult = (state == ArcCW.STATE_SIGHTS and 0.25) or 1
local sprintmult = (state == ArcCW.STATE_SPRINT and !self:CanShootWhileSprint() and 2) or 1
local pronemult = (self:IsProne() and 10) or 1
local onground = self:GetOwner():OnGround()
self.StepBob = self.StepBob + (velocity * 0.00015 + (math.pow(delta, 0.01) * 0.03)) * swayspeed * FT * 300
if self.StepBob >= stepend then
self.StepBob = 0
self.StepRandomX = math.Rand(1, 1.5)
self.StepRandomY = math.Rand(1, 1.5)
end
if velocity == 0 then
self.StepBob = 0
end
if onground then
-- oh no it says sex tra
local sextra = vector_origin
if (state == ArcCW.STATE_SPRINT and !self:CanShootWhileSprint() and !self:SelectAnimation("idle_sprint")) or true then
sextra = LerpVector(sprd, vector_origin, sextra_vec)
end
VMPosOffset.x = (math.sin(self.StepBob) * velocity * (0.000375 + sextra.x) * sightedmult * swayxmult) * self.StepRandomX
VMPosOffset.y = (math.sin(self.StepBob * 0.5) * velocity * (0.0005 + sextra.y) * sightedmult * sprintmult * pronemult * swayymult) * self.StepRandomY
VMPosOffset.z = math.sin(self.StepBob * 0.75) * velocity * (0.002 + sextra.z) * sightedmult * pronemult * swayzmult
end
VMPosOffset_Lerp.x = Lerp(32 * FT, VMPosOffset_Lerp.x, VMPosOffset.x)
VMPosOffset_Lerp.y = Lerp(4 * FT, VMPosOffset_Lerp.y, VMPosOffset.y)
VMPosOffset_Lerp.z = Lerp(2 * FT, VMPosOffset_Lerp.z, VMPosOffset.z)
VMAngOffset.x = VMPosOffset_Lerp.x * 2
VMAngOffset.y = VMPosOffset_Lerp.y * -7.5
VMAngOffset.z = VMPosOffset_Lerp.y * 10
VMPos:Add(VMAng:Up() * VMPosOffset_Lerp.x)
VMPos:Add(VMAng:Right() * VMPosOffset_Lerp.y)
VMPos:Add(VMAng:Forward() * VMPosOffset_Lerp.z)
VMAng:Add(VMAngOffset)
end
function SWEP:Breath_Health()
local owner = self:GetOwner()
if !IsValid(owner) then return end
local health = owner:Health()
local maxhealth = owner:GetMaxHealth()
self.Breath_Intensity = math.Clamp(maxhealth / health, 0, 2)
self.Breath_Rate = math.Clamp((maxhealth * 0.5) / health, 1, 1.5)
end
function SWEP:Breath_StateMult()
local owner = self:GetOwner()
if !IsValid(owner) then return end
local sightedmult = (self:GetState() == ArcCW.STATE_SIGHTS and 0.05) or 1
self.Breath_Intensity = self.Breath_Intensity * sightedmult
end
function SWEP:Breath_Process(EyePos, EyeAng)
local VMPos, VMAng = self.VMPos, self.VMAng
local VMPosOffset, VMAngOffset = self.VMPosOffset, self.VMAngOffset
-- self:Breath_Health() Snaps around when regenerating
self:Breath_StateMult()
VMPosOffset.x = (math.sin(CurTime() * 2 * self.Breath_Rate) * 0.1) * self.Breath_Intensity
VMPosOffset.y = (math.sin(CurTime() * 2.5 * self.Breath_Rate) * 0.025) * self.Breath_Intensity
VMAngOffset.x = VMPosOffset.x * 1.5
VMAngOffset.y = VMPosOffset.y * 2
VMAngOffset.z = VMPosOffset.y * VMPosOffset.x * -40
VMPos:Add(VMAng:Up() * VMPosOffset.x)
VMPos:Add(VMAng:Right() * VMPosOffset.y)
VMAng:Add(VMAngOffset)
end
function SWEP:Look_Process(EyePos, EyeAng, velocity)
local VMPos, VMAng = self.VMPos, self.VMAng
local VMPosOffset, VMAngOffset = self.VMPosOffset, self.VMAngOffset
local FT = scrunkly()
local sightedmult = (self:GetState() == ArcCW.STATE_SIGHTS and 0.25) or 1
self.SmoothEyeAng = LerpAngle(0.05, self.SmoothEyeAng, EyeAng - self.LastEyeAng)
-- local xd, yd = (velocity.z / 10), (velocity.y / 200)
VMPosOffset.x = -self.SmoothEyeAng.x * -0.5 * sightedmult * lookxmult
VMPosOffset.y = self.SmoothEyeAng.y * 0.5 * sightedmult * lookymult
VMAngOffset.x = VMPosOffset.x * 0.75
VMAngOffset.y = VMPosOffset.y * 2.5
VMAngOffset.z = VMPosOffset.x * 2 + VMPosOffset.y * -2
self.VMLookLerp.y = Lerp(FT * 10, self.VMLookLerp.y, VMAngOffset.y * -1.5 + self.SmoothEyeAng.y)
VMAng.y = VMAng.y - self.VMLookLerp.y
VMPos:Add(VMAng:Up() * VMPosOffset.x)
VMPos:Add(VMAng:Right() * VMPosOffset.y)
VMAng:Add(VMAngOffset)
end
function SWEP:GetVMPosition(EyePos, EyeAng)
local velocity = self:GetOwner():GetVelocity()
velocity = WorldToLocal(velocity, angle_zero, vector_origin, EyeAng)
self:Move_Process(EyePos, EyeAng, velocity)
stopwatch("Move_Process")
self:Step_Process(EyePos, EyeAng, velocity)
stopwatch("Step_Process")
self:Breath_Process(EyePos, EyeAng)
stopwatch("Breath_Process")
self:Look_Process(EyePos, EyeAng, velocity)
stopwatch("Look_Process")
self.LastEyeAng = EyeAng
self.LastEyePos = EyePos
self.LastVelocity = velocity
return self.VMPos, self.VMAng
end
SWEP.TheJ = {posa = Vector(), anga = Angle()}
local rap_pos = Vector()
local rap_ang = Angle()
local actual
local target = {pos = Vector(), ang = Angle()}
local GunDriverFix = Angle( 0, 90, 90 )
function SWEP:GetViewModelPosition(pos, ang)
if ArcCW.ConVars["dev_benchgun"]:GetBool() then
if ArcCW.ConVars["dev_benchgun_custom"]:GetString() then
local bgc = ArcCW.ConVars["dev_benchgun_custom"]:GetString()
if string.Left(bgc, 6) != "setpos" then return vector_origin, angle_zero end
bgc = string.TrimLeft(bgc, "setpos ")
bgc = string.Replace(bgc, ";setang", "")
bgc = string.Explode(" ", bgc)
return Vector(bgc[1], bgc[2], bgc[3]), Angle(bgc[4], bgc[5], bgc[6])
else
return vector_origin, angle_zero
end
end
stopwatch()
local owner = self:GetOwner()
if !IsValid(owner) or !owner:Alive() then return end
local FT = scrunkly()
local CT = CurTime()
local TargetTick = (1 / FT) / 66.66
local cdelta = math.Clamp(math.ease.InOutSine((owner:GetViewOffset().z - owner:GetCurrentViewOffset().z) / (owner:GetViewOffset().z - owner:GetViewOffsetDucked().z)),0,1)
if TargetTick < 1 then
FT = FT * TargetTick
end
local vm = LocalPlayer():GetViewModel()
local asight = self:GetActiveSights()
local state = self:GetState()
local sgtd = self:GetSightDelta()
local sprd = self:GetSprintDelta()
local sprinted = self.Sprinted or state == ArcCW.STATE_SPRINT and !self:CanShootWhileSprint()
local sighted = self.Sighted or state == ArcCW.STATE_SIGHTS
local holstered = self:GetCurrentFiremode().Mode == 0
if game.SinglePlayer() then
sprinted = state == ArcCW.STATE_SPRINT and !self:CanShootWhileSprint()
sighted = state == ArcCW.STATE_SIGHTS
end
local oldpos, oldang = Vector(), Angle()
oldpos:Set(pos)
oldang:Set(ang)
ang:Sub(self:GetOurViewPunchAngles())
actual = self.ActualVMData or {
pos = Vector(),
ang = Angle(),
down = 1,
sway = 1,
bob = 1,
evpos = Vector(),
evang = Angle(),
}
local apos, aang = self:GetBuff_Override("Override_ActivePos", self.ActivePos), self:GetBuff_Override("Override_ActiveAng", self.ActiveAng)
local cpos, cang = self:GetBuff("CrouchPos", true) or apos, self:GetBuff("CrouchAng", true) or aang
target.down = 1
target.sway = 2
target.bob = 2
stopwatch("set")
if self:InBipod() and self:GetBipodAngle() then
local bpos = self:GetBuff_Override("Override_InBipodPos", self.InBipodPos)
target.pos:Set(asight and asight.Pos or apos)
target.ang:Set(asight and asight.Ang or aang)
local BEA = (self.BipodStartAngle or self:GetBipodAngle()) - owner:EyeAngles()
target.pos:Add(BEA:Right() * bpos.x * self.InBipodMult.x)
target.pos:Add(BEA:Forward() * bpos.y * self.InBipodMult.y)
target.pos:Add(BEA:Up() * bpos.z * self.InBipodMult.z)
target.sway = 0.2
-- elseif (owner:Crouching() or owner:KeyDown(IN_DUCK)) and !self:GetReloading() then
-- target.pos:Set(self:GetBuff("CrouchPos", true) or apos)
-- target.ang:Set(self:GetBuff("CrouchAng", true) or aang)
elseif self:GetReloading() then
target.pos:Set(self:GetBuff("ReloadPos", true) or apos)
target.ang:Set(self:GetBuff("ReloadAng", true) or aang)
else
target.pos:Set(apos)
target.ang:Set(aang)
LerpMod(target.pos, cpos, cdelta)
LerpMod(target.ang, cang, cdelta, true)
end
if (owner:Crouching() or owner:KeyDown(IN_DUCK)) then target.down = 0 end
stopwatch("reload, crouch, bipod")
target.pos.x = target.pos.x + ArcCW.ConVars["vm_right"]:GetFloat()
target.pos.y = target.pos.y + ArcCW.ConVars["vm_forward"]:GetFloat()
target.pos.z = target.pos.z + ArcCW.ConVars["vm_up"]:GetFloat()
target.ang.p = target.ang.p + ArcCW.ConVars["vm_pitch"]:GetFloat()
target.ang.y = target.ang.y + ArcCW.ConVars["vm_yaw"]:GetFloat()
target.ang.r = target.ang.r + ArcCW.ConVars["vm_roll"]:GetFloat()
if state == ArcCW.STATE_CUSTOMIZE then
target.down = 1
target.sway = 3
target.bob = 1
local mx, my = input.GetCursorPos()
mx = 2 * mx / ScrW()
my = 2 * my / ScrH()
target.pos:Set(self:GetBuff_Override("Override_CustomizePos", self.CustomizePos))
target.ang:Set(self:GetBuff_Override("Override_CustomizeAng", self.CustomizeAng))
target.pos.x = target.pos.x + mx
target.pos.z = target.pos.z + my
target.ang.y = target.ang.y + my * 2
target.ang.r = target.ang.r + mx * 2
if self.InAttMenu then
target.ang.y = target.ang.y - 5
end
end
stopwatch("cust")
-- Sprinting
local hpos, spos = self:GetBuff("HolsterPos", true), self:GetBuff("SprintPos", true)
local hang, sang = self:GetBuff("HolsterAng", true), self:GetBuff("SprintAng", true)
do
local aaaapos = holstered and (hpos or spos) or (spos or hpos)
local aaaaang = holstered and (hang or sang) or (sang or hang)
local sd = (self:GetReloading() and 0) or (self:IsProne() and math.Clamp(owner:GetVelocity():Length() / prone.Config.MoveSpeed, 0, 1)) or (holstered and 1) or (!self:CanShootWhileSprint() and sprd) or 0
sd = math.pow(math.sin(sd * math.pi * 0.5), 2)
local d = math.pow(math.sin(sd * math.pi * 0.5), math.pi)
local coolilove = d * math.cos(d * math.pi * 0.5)
local joffset, jaffset
if !sprinted then
joffset = sprint_vec2
jaffset = spring_ang2
else
joffset = sprint_vec1
jaffset = sprint_ang1
end
LerpMod(target.pos, aaaapos, sd)
LerpMod(target.ang, aaaaang, sd, true)
for i = 1, 3 do
target.pos[i] = target.pos[i] + joffset[i] * coolilove
target.ang[i] = target.ang[i] + jaffset[i] * coolilove
end
local fu_sprint = (sprinted and self:SelectAnimation("idle_sprint"))
target.sway = target.sway * f_lerp(sd, 1, fu_sprint and 0 or 2)
target.bob = target.bob * f_lerp(sd, 1, fu_sprint and 0 or 2)
end
stopwatch("sprint")
-- Sighting
if asight then
local delta = sgtd
delta = math.pow(math.sin(delta * math.pi * 0.5), math.pi)
local im = asight.Midpoint
local coolilove = delta * math.cos(delta * math.pi * 0.5)
local joffset, jaffset
if !sighted then
joffset = sight_vec2
jaffset = sight_ang2
else
joffset = (im and im.Pos or sight_vec1)
jaffset = (im and im.Ang or sight_ang1)
end
target.pos.z = target.pos.z - 1
LerpMod2(asight.Pos, target.pos, delta)
LerpMod2(asight.Ang, target.ang, delta)
for i = 1, 3 do
target.pos[i] = target.pos[i] + joffset[i] * coolilove
target.ang[i] = target.ang[i] + jaffset[i] * coolilove
end
target.evpos = f_lerp(delta, asight.EVPos or vector_origin, vector_origin)
target.evang = f_lerp(delta, asight.EVAng or angle_zero, angle_zero)
target.down = 0
target.sway = target.sway * f_lerp(delta, 0.1, 1)
target.bob = target.bob * f_lerp(delta, 0.1, 1)
end
stopwatch("sight")
local deg = self:GetBarrelNearWall()
if deg > 0 and ArcCW.ConVars["vm_nearwall"]:GetBool() then
LerpMod(target.pos, hpos, deg)
LerpMod(target.ang, hang, deg)
target.down = 2 * math.max(sgtd, 0.5)
end
if !isangle(target.ang) then
target.ang = Angle(target.ang)
end
target.ang.y = target.ang.y + (self:GetFreeAimOffset().y * 0.5)
target.ang.p = target.ang.p - (self:GetFreeAimOffset().p * 0.5)
if self.InProcDraw then
self.InProcHolster = false
local delta = m_clamp((CT - self.ProcDrawTime) / (0.5 * self:GetBuff_Mult("Mult_DrawTime")), 0, 1)
target.pos = LerpVector(delta, procdraw_vec, target.pos)
target.ang = LerpAngle(delta, procdraw_ang, target.ang)
target.down = target.down
target.sway = target.sway
target.bob = target.bob
end
if self.InProcHolster then
self.InProcDraw = false
local delta = 1 - m_clamp((CT - self.ProcHolsterTime) / (0.25 * self:GetBuff_Mult("Mult_DrawTime")), 0, 1)
target.pos = LerpVector(delta, procdraw_vec, target.pos)
target.ang = LerpAngle(delta, prochol_ang, target.ang)
target.down = target.down
target.sway = target.sway
target.bob = target.bob
end
if self.InProcBash then
self.InProcDraw = false
local mult = self:GetBuff_Mult("Mult_MeleeTime")
local mtime = self.MeleeTime * mult
local delta = 1 - m_clamp((CT - self.ProcBashTime) / mtime, 0, 1)
local bp, ba
if delta > 0.3 then
bp = self:GetBuff_Override("Override_BashPreparePos", self.BashPreparePos)
ba = self:GetBuff_Override("Override_BashPrepareAng", self.BashPrepareAng)
delta = (delta - 0.5) * 2
else
bp = self:GetBuff_Override("Override_BashPos", self.BashPos)
ba = self:GetBuff_Override("Override_BashAng", self.BashAng)
delta = delta * 2
end
LerpMod2(bp, target.pos, delta)
LerpMod2(ba, target.ang, delta)
target.speed = 10
if delta == 0 then
self.InProcBash = false
end
end
stopwatch("proc")
-- local gunbone, gbslot = self:GetBuff_Override("LHIK_GunDriver")
-- if gunbone and IsValid(self.Attachments[gbslot].VElement.Model) and self.LHIKGunPos and self.LHIKGunAng then
-- local magnitude = 1 --Lerp(sgtd, 0.1, 1)
-- local lhik_model = self.Attachments[gbslot].VElement.Model
-- local att = lhik_model:GetAttachment(lhik_model:LookupAttachment(gunbone))
-- local attang = att.Ang
-- local attpos = att.Pos
-- attang = lhik_model:WorldToLocalAngles(attang)
-- attpos = lhik_model:WorldToLocal(attpos)
-- attang:Sub(self.LHIKGunAng)
-- attpos:Sub(self.LHIKGunPos)
-- attang:Mul(magnitude)
-- attpos:Mul(magnitude)
-- --target.ang:Add(attang)
-- --target.pos:Add(attpos)
-- --debugoverlay.Axis(lhik_model:GetPos() + attpos, att.Ang, 8, FrameTime() * 3, true)
-- debugoverlay.Axis(lhik_model:GetPos(), att.Ang, 8, FrameTime() * 3, true)
-- end
-- stopwatch("gunbone")
local vmhit = self.ViewModel_Hit
if vmhit then
if !vmhit:IsZero() then
target.pos.x = target.pos.x + m_clamp(vmhit.y, -1, 1) * 0.25
target.pos.y = target.pos.y + vmhit.y
target.pos.z = target.pos.z + m_clamp(vmhit.x, -1, 1) * 1
target.ang.x = target.ang.x + m_clamp(vmhit.x, -1, 1) * 5
target.ang.y = target.ang.y + m_clamp(vmhit.y, -1, 1) * -2
target.ang.z = target.ang.z + m_clamp(vmhit.z, -1, 1) * 12.5
end
local spd = vmhit:Length() * 5
vmhit.x = m_appor(vmhit.x, 0, FT * spd)
vmhit.y = m_appor(vmhit.y, 0, FT * spd)
vmhit.z = m_appor(vmhit.z, 0, FT * spd)
end
if ArcCW.ConVars["shakevm"]:GetBool() and !engine.IsRecordingDemo() then
target.pos:Add(VectorRand() * self.RecoilAmount * 0.2 * self.RecoilVMShake)
end
stopwatch("vmhit")
local speed = 15 * FT * (game.SinglePlayer() and 1 or 2)
LerpMod(actual.pos, target.pos, speed)
LerpMod(actual.ang, target.ang, speed, true)
LerpMod(actual.evpos, target.evpos or vector_origin, speed)
LerpMod(actual.evang, target.evang or angle_zero, speed, true)
actual.down = f_lerp(speed, actual.down, target.down)
actual.sway = f_lerp(speed, actual.sway, target.sway)
actual.bob = f_lerp(speed, actual.bob, target.bob)
ApproachMod(actual.pos, target.pos, speed * 0.1)
ApproachMod(actual.ang, target.ang, speed * 0.1)
actual.down = m_appor(actual.down, target.down, speed * 0.1)
stopwatch("actual -> target")
local coolsway = ArcCW.ConVars["vm_coolsway"]:GetBool()
self.SwayScale = (coolsway and 0) or actual.sway
self.BobScale = (coolsway and 0) or actual.bob
if coolsway then
swayxmult = ArcCW.ConVars["vm_sway_zmult"]:GetFloat() or 1
swayymult = ArcCW.ConVars["vm_sway_xmult"]:GetFloat() or 1
swayzmult = ArcCW.ConVars["vm_sway_ymult"]:GetFloat() or 1
swayspeed = ArcCW.ConVars["vm_sway_speedmult"]:GetFloat() or 1
lookxmult = ArcCW.ConVars["vm_look_xmult"]:GetFloat() or 1
lookymult = ArcCW.ConVars["vm_look_ymult"]:GetFloat() or 1
local sd = self:GetSightDelta()
lookxmult = Lerp(sd, 0, lookxmult)
lookymult = Lerp(sd, 0, lookymult)
swayxmult = Lerp(sd, 0, swayxmult)
swayymult = Lerp(sd, 0, swayymult)
swayzmult = Lerp(sd, 0, swayzmult)
swayspeed = Lerp(sd, 0, swayspeed)
stopwatch("before vmposition")
local npos, nang = self:GetVMPosition(oldpos, oldang)
pos:Set(npos)
ang:Set(nang)
end
local old_r, old_f, old_u = oldang:Right(), oldang:Forward(), oldang:Up()
pos:Add(math.min(self.RecoilPunchBack, Lerp(sgtd, self.RecoilPunchBackMaxSights or 1, self.RecoilPunchBackMax)) * -old_f)
ang:RotateAroundAxis(old_r, actual.ang.x)
ang:RotateAroundAxis(old_u, actual.ang.y)
ang:RotateAroundAxis(old_f, actual.ang.z)
ang:RotateAroundAxis(old_r, actual.evang.x)
ang:RotateAroundAxis(old_u, actual.evang.y)
ang:RotateAroundAxis(old_f, actual.evang.z)
local new_r, new_f, new_u = ang:Right(), ang:Forward(), ang:Up()
old_r:Mul(actual.evpos.x)
old_f:Mul(actual.evpos.y)
old_u:Mul(actual.evpos.z)
pos:Add(old_r)
pos:Add(old_f)
pos:Add(old_u)
new_r:Mul(actual.pos.x)
new_f:Mul(actual.pos.y)
new_u:Mul(actual.pos.z)
pos:Add(new_r)
pos:Add(new_f)
pos:Add(new_u)
pos.z = pos.z - actual.down
ang:Add(self:GetOurViewPunchAngles() * Lerp(sgtd, 1, -1))
local gunbone, gbslot = self:GetBuff_Override("LHIK_GunDriver")
local lhik_model = gbslot and self.Attachments[gbslot].VElement and self.Attachments[gbslot].VElement.Model -- Visual M203 attachment
local lhik_anim_model = gbslot and self.Attachments[gbslot].GodDriver and self.Attachments[gbslot].GodDriver.Model -- M203 anim and camera
local lhik_refl_model = gbslot and self.Attachments[gbslot].ReflectDriver and self.Attachments[gbslot].ReflectDriver.Model -- Rifle
if IsValid(lhik_model) and IsValid(lhik_anim_model) and IsValid(lhik_refl_model) and lhik_anim_model:GetAttachment(lhik_anim_model:LookupAttachment(gunbone)) then
local att = lhik_anim_model:LookupAttachment(gunbone)
local offset = lhik_anim_model:GetAttachment(att).Pos
local affset = lhik_anim_model:GetAttachment(att).Ang
affset:Sub( GunDriverFix )
local r = affset.r
affset.r = affset.p
affset.p = -r
affset.y = -affset.y
local anchor = self.Attachments[gbslot].VMOffsetPos
local looku = lhik_refl_model:LookupBone( self.Attachments[gbslot].Bone )
local bonp, bona = lhik_refl_model:GetBonePosition( looku )
if bonp == lhik_refl_model:GetPos() then
bonp = lhik_refl_model:GetBoneMatrix( looku ):GetTranslation()
bona = lhik_refl_model:GetBoneMatrix( looku ):GetAngles()
end
if anchor and bonp then -- Not ready / deploying
anchor = ( bonp + ( (bona:Forward()*anchor.x) + (bona:Right()*anchor.y) + (bona:Up()*anchor.z) ) )
debugoverlay.Axis(anchor, angle_zero, 4, FrameTime(), true)
rap_pos, rap_ang = ArcCW.RotateAroundPoint2(pos, ang, anchor, offset, affset)
rap_pos:Sub(pos)
rap_ang:Sub(ang)
pos:Add(rap_pos)
ang:Add(rap_ang)
end
end
self.ActualVMData = actual
stopwatch("apply actual")
stopwatch(true)
lst = SysTime()
return pos, ang
end
function SWEP:ShouldCheapWorldModel()
local lp = LocalPlayer()
if lp:GetObserverMode() == OBS_MODE_IN_EYE and lp:GetObserverTarget() == self:GetOwner() then return true end
if !IsValid(self:GetOwner()) and !ArcCW.ConVars["att_showground"]:GetBool() then return true end
return !ArcCW.ConVars["att_showothers"]:GetBool()
end
local bird = Material("arccw/hud/arccw_bird.png", "mips smooth")
local iw = 32
function SWEP:DrawWorldModel()
local cvar2d3d = ArcCW.ConVars["2d3d"]:GetInt()
if !IsValid(self:GetOwner()) and !TTT2
and (cvar2d3d == 2 or (cvar2d3d == 1 and LocalPlayer():GetEyeTrace().Entity == self))
and (EyePos() - self:WorldSpaceCenter()):LengthSqr() <= 262144 then -- 512^2
local ang = LocalPlayer():EyeAngles()
ang:RotateAroundAxis(ang:Forward(), 180)
ang:RotateAroundAxis(ang:Right(), 90)
ang:RotateAroundAxis(ang:Up(), 90)
cam.Start3D2D(self:WorldSpaceCenter() + Vector(0, 0, 16), ang, 0.1)
srf.SetFont("ArcCW_32_Unscaled")
local w = srf.GetTextSize(self.PrintName)
srf.SetTextPos(-w / 2 + 2, 2)
srf.SetTextColor(0, 0, 0, 150)
srf.DrawText(self.PrintName)
srf.SetTextPos(-w / 2, 0)
srf.SetTextColor(255, 255, 255, 255)
srf.DrawText(self.PrintName)
local icons = {}
for i, slot in pairs(self.Attachments or {}) do
if slot.Installed then
local atttbl = ArcCW.AttachmentTable[slot.Installed]
if !atttbl then continue end
local icon = atttbl.Icon
if !icon or icon:IsError() then icon = bird end
table.insert(icons, icon)
end
end
local ind = math.min(6, #icons)
surface.SetDrawColor(255, 255, 255)
for i = 1, ind do
if i == 6 and #icons > 6 then
local str = "+" .. (#icons - ind)
local strw = srf.GetTextSize(str)
srf.SetTextPos(-ind * iw / 2 + (i - 1) * iw + 2 + strw / 2, iw + 14)
srf.SetTextColor(0, 0, 0, 150)
srf.DrawText(str)
srf.SetTextPos(-ind * iw / 2 + (i - 1) * iw + strw / 2, iw + 12)
srf.SetTextColor(255, 255, 255, 255)
srf.DrawText(str)
else
local icon = icons[i]
surface.SetMaterial(icon)
surface.DrawTexturedRect(-ind * iw / 2 + (i - 1) * iw, iw + 12, iw, iw)
end
end
-- srf.SetFont("ArcCW_24_Unscaled")
-- local count = self:CountAttachments()
-- if count > 0 then
-- local t = tostring(count) .. " Attachments"
-- w = srf.GetTextSize(t)
-- srf.SetTextPos(-w / 2, 32)
-- srf.SetTextColor(255, 255, 255, 255)
-- srf.DrawText(t)
-- end
cam.End3D2D()
end
self:DrawCustomModel(true)
self:DoLaser(true)
if self:ShouldGlint() then
self:DoScopeGlint()
end
if !self.CertainAboutAtts and !self.AttReqSent and !IsValid(self:GetOwner()) then
self.AttReqSent = true
-- print(self, "network weapon from cl_viewmodel")
-- debugoverlay.Cross(self:GetPos(), 8, 10, color_white, true)
-- debugoverlay.EntityTextAtPosition(self:GetPos(), 1, tostring(self) .. " requesting networking data", 10, color_white)
net.Start("arccw_rqwpnnet")
net.WriteEntity(self)
net.SendToServer()
end
end
function SWEP:ShouldCheapScope()
if !ArcCW.ConVars["cheapscopes"]:GetBool() then return end
end
local POSTVMDONE = nil
local POSTVMDONE_TIME = 0
local lst2 = SysTime()
function SWEP:PreDrawViewModel(vm)
if ArcCW.VM_OverDraw then return end
if !vm then return end
if self:GetState() == ArcCW.STATE_CUSTOMIZE then
self:BlurNotWeapon()
end
if ArcCW.ConVars["cheapscopesautoconfig"]:GetBool() then
local fps = 1 / (SysTime() - lst2)
lst2 = SysTime()
local lowfps = fps <= 45
ArcCW.ConVars["cheapscopes"]:SetBool(lowfps)
ArcCW.ConVars["cheapscopesautoconfig"]:SetBool(false)
end
local asight = self:GetActiveSights()
if asight and ((ArcCW.ConVars["cheapscopes"]:GetBool() and self:GetSightDelta() < 1 and asight.MagnifiedOptic)
or (self:GetSightDelta() < 1 and asight.ScopeTexture)) then
-- Necessary to call here since physbullets are not drawn until PreDrawEffects; cheap scope implementation will not allow them to be visible
-- Introduces a bug when we try to call GetAttachment on the viewmodel in DrawPhysBullets here, so set a workaround variable to not call it
ArcCW:DrawPhysBullets(true)
self:FormCheapScope()
end
local coolFOV = self.CurrentViewModelFOV or self.ViewModelFOV
if ArcCW.VMInRT then
local mag = asight.ScopeMagnification
coolFOV = self.ViewModelFOV - mag * 4 - (ArcCW.ConVars["vm_add_ads"]:GetFloat() * 3 or 0)
ArcCW.VMInRT = false
end
cam.Start3D(EyePos(), EyeAngles(), self:QuickFOVix(coolFOV), nil, nil, nil, nil, 0.5, 1000)
cam.IgnoreZ(true)
self:DrawCustomModel(false)
self:DoLHIK()
if !ArcCW.Overdraw then
self:DoLaser(false, true)
end
-- patrol
if POSTVMDONE == false and POSTVMDONE_TIME <= CurTime() then
POSTVMDONE_TIME = CurTime() + 1
print( "[ArcCW] Warning: PostDrawViewModel failed response!! cam.End3D errors may be inbound!! You may have an addon conflict!!")
print( "[ArcCW] Follow the troubleshooting guide at https://github.com/HaodongMo/ArcCW/wiki/Help-&-Troubleshooting#camend3d-errors")
end
POSTVMDONE = false
end
function SWEP:PostDrawViewModel()
POSTVMDONE = true
if ArcCW.VM_OverDraw then return end
render.SetBlend(1)
cam.End3D()
cam.Start3D(EyePos(), EyeAngles(), self:QuickFOVix(self.CurrentViewModelFOV or self.ViewModelFOV), nil, nil, nil, nil, 0.5, 1000)
cam.IgnoreZ(true)
if ArcCW.Overdraw then
ArcCW.Overdraw = false
else
--self:DoLaser()
self:DoHolosight()
end
cam.End3D()
end