mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 13:53:45 +03:00
Upload
This commit is contained in:
52
lua/weapons/arccw_base/cl_blur.lua
Normal file
52
lua/weapons/arccw_base/cl_blur.lua
Normal file
@@ -0,0 +1,52 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
local dofmat = Material("pp/dof")
|
||||
|
||||
function SWEP:BlurWeapon()
|
||||
if !ArcCW.ConVars["blur"]:GetBool() then return end
|
||||
local delta = self:GetSightDelta()
|
||||
if delta >= 1 then return end
|
||||
local vm = self:GetOwner():GetViewModel()
|
||||
render.UpdateScreenEffectTexture()
|
||||
render.ClearStencil()
|
||||
render.SetStencilEnable(true)
|
||||
render.SetStencilCompareFunction(STENCIL_ALWAYS)
|
||||
render.SetStencilPassOperation(STENCIL_REPLACE)
|
||||
render.SetStencilFailOperation(STENCIL_KEEP)
|
||||
render.SetStencilZFailOperation(STENCIL_REPLACE)
|
||||
render.SetStencilWriteMask(0xFF)
|
||||
render.SetStencilTestMask(0xFF)
|
||||
render.SetBlend(1)
|
||||
render.SetStencilReferenceValue(55)
|
||||
ArcCW.Overdraw = true
|
||||
vm:DrawModel()
|
||||
ArcCW.Overdraw = false
|
||||
render.SetBlend(0)
|
||||
render.SetStencilPassOperation(STENCIL_REPLACE)
|
||||
render.SetStencilCompareFunction(STENCIL_EQUAL)
|
||||
-- render.SetColorMaterial()
|
||||
dofmat:SetFloat("bluramount", 0.1 * (1 - delta))
|
||||
render.SetMaterial(dofmat)
|
||||
render.DrawScreenQuad()
|
||||
render.SetStencilEnable(false)
|
||||
end
|
||||
|
||||
function SWEP:BlurNotWeapon()
|
||||
if !ArcCW.ConVars["blur"]:GetBool() then return end
|
||||
render.UpdateRefractTexture()
|
||||
DrawToyTown(3, ScrH())
|
||||
end
|
||||
|
||||
function SWEP:DoToyTown()
|
||||
if !ArcCW.ConVars["blur_toytown"]:GetBool() then return end
|
||||
render.UpdateRefractTexture()
|
||||
DrawToyTown(3, ScrH() * 0.4 * (1 - self:GetSightDelta()))
|
||||
end
|
||||
303
lua/weapons/arccw_base/cl_crosshair.lua
Normal file
303
lua/weapons/arccw_base/cl_crosshair.lua
Normal file
@@ -0,0 +1,303 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
local size = 0
|
||||
local clump_inner = Material("arccw/hud/clump_inner.png", "mips smooth")
|
||||
local clump_outer = Material("arccw/hud/clump_outer.png", "mips smooth")
|
||||
local aimtr_result = {}
|
||||
local aimtr = {}
|
||||
local square_mat = Material("color")
|
||||
|
||||
function SWEP:ShouldDrawCrosshair()
|
||||
if ArcCW.ConVars["override_crosshair_off"]:GetBool() then return false end
|
||||
if !ArcCW.ConVars["crosshair"]:GetBool() then return false end
|
||||
if self:GetReloading() then return false end
|
||||
if self:BarrelHitWall() > 0 then return false end
|
||||
local asight = self:GetActiveSights()
|
||||
|
||||
if !self:GetOwner():ShouldDrawLocalPlayer()
|
||||
and self:GetState() == ArcCW.STATE_SIGHTS and !asight.CrosshairInSights then
|
||||
return false
|
||||
end
|
||||
|
||||
if self:GetNWState() == ArcCW.STATE_SPRINT and !self:CanShootWhileSprint() then return false end
|
||||
if self:GetCurrentFiremode().Mode == 0 then return false end
|
||||
if self:GetBuff_Hook("Hook_ShouldNotFire") then return false end
|
||||
if self:GetNWState() == ArcCW.STATE_CUSTOMIZE then return false end
|
||||
if self:GetNWState() == ArcCW.STATE_DISABLE then return false end
|
||||
return true
|
||||
end
|
||||
|
||||
local cr_main = Color( 0, 255, 0 )
|
||||
local cr_shad = Color( 0, 0, 0, 127 )
|
||||
|
||||
local gaA = 0
|
||||
local gaD = 0
|
||||
|
||||
function SWEP:GetFOVAcc( acc, disp )
|
||||
cam.Start3D()
|
||||
local lool = ( EyePos() + ( EyeAngles():Forward() ) + ( ( ArcCW.MOAToAcc * (acc or self:GetBuff("AccuracyMOA")) ) * EyeAngles():Up() ) ):ToScreen()
|
||||
local lool2 = ( EyePos() + ( EyeAngles():Forward() ) + ( ( (disp or self:GetDispersion()) * ArcCW.MOAToAcc / 10 ) * EyeAngles():Up() ) ):ToScreen()
|
||||
cam.End3D()
|
||||
|
||||
local gau = 0
|
||||
gau = ( (ScrH() / 2) - lool.y )
|
||||
gaA = math.Approach(gaA, gau, (ScrH() / 2) * FrameTime())
|
||||
gau = 0
|
||||
gau = ( (ScrH() / 2) - lool2.y )
|
||||
gaD = math.Approach(gaD, gau, (ScrH() / 2) * FrameTime())
|
||||
|
||||
return gaA, gaD
|
||||
end
|
||||
|
||||
function SWEP:DrawDevCrosshair(x, y)
|
||||
surface.SetDrawColor(255, 50, 50, 255)
|
||||
|
||||
surface.DrawLine(x, y - 256, x, y + 256)
|
||||
surface.DrawLine(x - 256, y, x + 256, y)
|
||||
|
||||
|
||||
local gA, gD = self:GetFOVAcc( self:GetBuff("AccuracyMOA"), self:GetDispersion() )
|
||||
surface.DrawCircle(x, y, gA + gD, 255, 255, 255, 155)
|
||||
surface.DrawCircle(x, y, gA, 255, 255, 0, 55)
|
||||
|
||||
draw.SimpleTextOutlined(math.Round(self:GetDispersion(), 1) .. " MOA", "ArcCW_24_Unscaled", x - gA - gD - 16, y, color_white, TEXT_ALIGN_RIGHT, TEXT_ALIGN_BOTTOM, 1, Color(0, 0, 0))
|
||||
draw.SimpleTextOutlined(math.Round(self:GetBuff("AccuracyMOA"), 1) .. " MOA", "ArcCW_24_Unscaled", x - gA - gD - 16, y, Color(255, 255, 0), TEXT_ALIGN_RIGHT, TEXT_ALIGN_TOP, 1, Color(0, 0, 0))
|
||||
|
||||
|
||||
local dist = self:GetOwner():GetEyeTrace().HitPos:Distance(self:GetOwner():GetShootPos()) * ArcCW.HUToM
|
||||
local rf = self:GetRangeFraction(dist)
|
||||
|
||||
local dmg = math.floor(self:GetDamage(dist))
|
||||
draw.SimpleTextOutlined(dmg .. " damage", "ArcCW_24_Unscaled", x + 256, y, color_white, TEXT_ALIGN_RIGHT, TEXT_ALIGN_BOTTOM, 1, Color(0, 0, 0))
|
||||
draw.SimpleTextOutlined(math.Round(dist, 1) .. "m", "ArcCW_24_Unscaled", x + 256 - 64, y, color_white, TEXT_ALIGN_RIGHT, TEXT_ALIGN_TOP, 1, Color(0, 0, 0))
|
||||
draw.SimpleTextOutlined(math.Round(rf * 100) .. "%", "ArcCW_24_Unscaled", x + 256, y, color_white, TEXT_ALIGN_RIGHT, TEXT_ALIGN_TOP, 1, Color(0, 0, 0))
|
||||
|
||||
end
|
||||
|
||||
function SWEP:DoDrawCrosshair(x, y)
|
||||
local ply = LocalPlayer()
|
||||
local pos = ply:EyePos()
|
||||
local ang = ply:EyeAngles() - self:GetOurViewPunchAngles() + self:GetFreeAimOffset()
|
||||
|
||||
if self:GetBuff_Hook("Hook_PreDrawCrosshair") then return end
|
||||
|
||||
local static = ArcCW.ConVars["crosshair_static"]:GetBool()
|
||||
|
||||
local prong_dot = ArcCW.ConVars["crosshair_dot"]:GetBool()
|
||||
local prong_top = ArcCW.ConVars["crosshair_prong_top"]:GetBool()
|
||||
local prong_left = ArcCW.ConVars["crosshair_prong_left"]:GetBool()
|
||||
local prong_right = ArcCW.ConVars["crosshair_prong_right"]:GetBool()
|
||||
local prong_down = ArcCW.ConVars["crosshair_prong_bottom"]:GetBool()
|
||||
|
||||
local prong_len = ArcCW.ConVars["crosshair_length"]:GetFloat()
|
||||
local prong_wid = ArcCW.ConVars["crosshair_thickness"]:GetFloat()
|
||||
local prong_out = ArcCW.ConVars["crosshair_outline"]:GetInt()
|
||||
local prong_tilt = ArcCW.ConVars["crosshair_tilt"]:GetBool()
|
||||
|
||||
local clr = Color(ArcCW.ConVars["crosshair_clr_r"]:GetInt(),
|
||||
ArcCW.ConVars["crosshair_clr_g"]:GetInt(),
|
||||
ArcCW.ConVars["crosshair_clr_b"]:GetInt())
|
||||
if ArcCW.ConVars["ttt_rolecrosshair"] and ArcCW.ConVars["ttt_rolecrosshair"]:GetBool() then
|
||||
if GetRoundState() == ROUND_PREP or GetRoundState() == ROUND_POST then
|
||||
clr = Color(255, 255, 255)
|
||||
elseif ply.GetRoleColor and ply:GetRoleColor() then
|
||||
clr = ply:GetRoleColor() -- TTT2 feature
|
||||
elseif ply:IsActiveTraitor() then
|
||||
clr = Color(255, 50, 50)
|
||||
elseif ply:IsActiveDetective() then
|
||||
clr = Color(50, 50, 255)
|
||||
else
|
||||
clr = Color(50, 255, 50)
|
||||
end
|
||||
end
|
||||
if ArcCW.ConVars["crosshair_aa"]:GetBool() and ply.ArcCW_AATarget != nil and ArcCW.ConVars["aimassist"]:GetBool() and ArcCW.ConVars["aimassist_cl"]:GetBool() then
|
||||
-- whooie
|
||||
clr = Color(255, 0, 0)
|
||||
end
|
||||
clr.a = ArcCW.ConVars["crosshair_clr_a"]:GetInt()
|
||||
|
||||
local outlineClr = Color(ArcCW.ConVars["crosshair_outline_r"]:GetInt(),
|
||||
ArcCW.ConVars["crosshair_outline_g"]:GetInt(),
|
||||
ArcCW.ConVars["crosshair_outline_b"]:GetInt(),
|
||||
ArcCW.ConVars["crosshair_outline_a"]:GetInt())
|
||||
|
||||
local gA, gD = self:GetFOVAcc( self:GetBuff("AccuracyMOA"), self:GetDispersion() )
|
||||
local gap = (static and 8 or gA + gD) * ArcCW.ConVars["crosshair_gap"]:GetFloat()
|
||||
|
||||
gap = gap + ( ScreenScale(8) * math.Clamp(self.RecoilAmount, 0, 1) )
|
||||
|
||||
local prong = ScreenScale(prong_len)
|
||||
local p_w = ScreenScale(prong_wid)
|
||||
local p_w2 = p_w + prong_out
|
||||
|
||||
local sp
|
||||
if self:GetOwner():ShouldDrawLocalPlayer() then
|
||||
local tr = util.GetPlayerTrace(self:GetOwner())
|
||||
local trace = util.TraceLine( tr )
|
||||
|
||||
cam.Start3D()
|
||||
local coords = trace.HitPos:ToScreen()
|
||||
coords.x = math.Round(coords.x)
|
||||
coords.y = math.Round(coords.y)
|
||||
cam.End3D()
|
||||
sp = { visible = true, x = coords.x, y = coords.y }
|
||||
end
|
||||
|
||||
cam.Start3D()
|
||||
sp = (pos + (ang:Forward() * 3200)):ToScreen()
|
||||
cam.End3D()
|
||||
|
||||
if ArcCW.ConVars["crosshair_trueaim"]:GetBool() then
|
||||
aimtr.start = self:GetShootSrc()
|
||||
else
|
||||
aimtr.start = pos
|
||||
end
|
||||
|
||||
aimtr.endpos = aimtr.start + ((ply:EyeAngles() + self:GetFreeAimOffset()):Forward() * 100000)
|
||||
aimtr.filter = {ply}
|
||||
aimtr.output = aimtr_result
|
||||
|
||||
table.Add(aimtr.filter, ArcCW:GetVehicleFilter(ply) or {})
|
||||
|
||||
util.TraceLine(aimtr)
|
||||
|
||||
cam.Start3D()
|
||||
local w2s = aimtr_result.HitPos:ToScreen()
|
||||
w2s.x = math.Round(w2s.x)
|
||||
w2s.y = math.Round(w2s.y)
|
||||
cam.End3D()
|
||||
|
||||
sp.x = w2s.x sp.y = w2s.y
|
||||
x, y = sp.x, sp.y
|
||||
|
||||
if ArcCW.ConVars["dev_crosshair"]:GetBool() and LocalPlayer():IsAdmin() then
|
||||
self:DrawDevCrosshair(x, y)
|
||||
end
|
||||
|
||||
local st = self:GetSightTime() / 2
|
||||
|
||||
if self:ShouldDrawCrosshair() then
|
||||
self.CrosshairDelta = math.Approach(self.CrosshairDelta or 0, 1, FrameTime() * 1 / st)
|
||||
else
|
||||
self.CrosshairDelta = math.Approach(self.CrosshairDelta or 0, 0, FrameTime() * 1 / st)
|
||||
end
|
||||
|
||||
if ArcCW.ConVars["crosshair_equip"]:GetBool() and (self:GetBuff("ShootEntity", true) or self.PrimaryBash) then
|
||||
prong = ScreenScale(prong_wid)
|
||||
p_w = ScreenScale(prong_wid)
|
||||
p_w2 = p_w + prong_out
|
||||
end
|
||||
|
||||
if prong_dot then
|
||||
surface.SetDrawColor(outlineClr.r, outlineClr.g, outlineClr.b, outlineClr.a * self.CrosshairDelta)
|
||||
surface.DrawRect(x - p_w2 / 2, y - p_w2 / 2, p_w2, p_w2)
|
||||
|
||||
surface.SetDrawColor(clr.r, clr.g, clr.b, clr.a * self.CrosshairDelta)
|
||||
surface.DrawRect(x - p_w / 2, y - p_w / 2, p_w, p_w)
|
||||
end
|
||||
|
||||
|
||||
size = math.Approach(size, gap, FrameTime() * 32 * gap)
|
||||
gap = size
|
||||
if !static then gap = gap * self.CrosshairDelta end
|
||||
gap = math.max(4, gap)
|
||||
|
||||
local num = self:GetBuff("Num")
|
||||
if ArcCW.ConVars["crosshair_shotgun"]:GetBool() and num > 1 then
|
||||
prong = ScreenScale(prong_wid)
|
||||
p_w = ScreenScale(prong_len)
|
||||
p_w2 = p_w + prong_out
|
||||
end
|
||||
|
||||
local prong2 = prong + prong_out
|
||||
if prong_tilt then
|
||||
local angle = (prong_left and prong_top and prong_right and prong_down) and 45 or 30
|
||||
local rad = math.rad(angle)
|
||||
local dx = gap * math.cos(rad) + prong * math.cos(rad) / 2
|
||||
local dy = gap * math.sin(rad) + prong * math.sin(rad) / 2
|
||||
surface.SetMaterial(square_mat)
|
||||
-- Shade
|
||||
surface.SetDrawColor(outlineClr.r, outlineClr.g, outlineClr.b, outlineClr.a * self.CrosshairDelta)
|
||||
if prong_left and prong_top then
|
||||
surface.DrawTexturedRectRotated(x - dx, y - dy, prong2, p_w2, -angle)
|
||||
surface.DrawTexturedRectRotated(x + dx, y - dy, prong2, p_w2, angle)
|
||||
elseif prong_left or prong_top then
|
||||
surface.DrawRect(x - p_w2 / 2, y - gap - prong2 + prong_out / 2, p_w2, prong2)
|
||||
end
|
||||
if prong_right and prong_down then
|
||||
surface.DrawTexturedRectRotated(x + dx, y + dy, prong2, p_w2, -angle)
|
||||
surface.DrawTexturedRectRotated(x - dx, y + dy, prong2, p_w2, angle)
|
||||
elseif prong_right or prong_down then
|
||||
surface.DrawRect(x - p_w2 / 2, y + gap - prong_out / 2, p_w2, prong2)
|
||||
end
|
||||
-- Fill
|
||||
surface.SetDrawColor(clr.r, clr.g, clr.b, clr.a * self.CrosshairDelta)
|
||||
if prong_left and prong_top then
|
||||
surface.DrawTexturedRectRotated(x - dx, y - dy, prong, p_w, -angle)
|
||||
surface.DrawTexturedRectRotated(x + dx, y - dy, prong, p_w, angle)
|
||||
elseif prong_left or prong_top then
|
||||
surface.DrawRect(x - p_w / 2, y - gap - prong, p_w, prong)
|
||||
end
|
||||
if prong_right and prong_down then
|
||||
surface.DrawTexturedRectRotated(x + dx, y + dy, prong, p_w, -angle)
|
||||
surface.DrawTexturedRectRotated(x - dx, y + dy, prong, p_w, angle)
|
||||
elseif prong_right or prong_down then
|
||||
surface.DrawRect(x - p_w / 2, y + gap, p_w, prong)
|
||||
end
|
||||
else
|
||||
-- Shade
|
||||
surface.SetDrawColor(outlineClr.r, outlineClr.g, outlineClr.b, outlineClr.a * self.CrosshairDelta)
|
||||
if prong_left then
|
||||
surface.DrawRect(x - gap - prong2 + prong_out / 2, y - p_w2 / 2, prong2, p_w2)
|
||||
end
|
||||
if prong_right then
|
||||
surface.DrawRect(x + gap - prong_out / 2, y - p_w2 / 2, prong2, p_w2)
|
||||
end
|
||||
if prong_top then
|
||||
surface.DrawRect(x - p_w2 / 2, y - gap - prong2 + prong_out / 2, p_w2, prong2)
|
||||
end
|
||||
if prong_down then
|
||||
surface.DrawRect(x - p_w2 / 2, y + gap - prong_out / 2, p_w2, prong2)
|
||||
end
|
||||
-- Fill
|
||||
surface.SetDrawColor(clr.r, clr.g, clr.b, clr.a * self.CrosshairDelta)
|
||||
if prong_left then
|
||||
surface.DrawRect(x - gap - prong, y - p_w / 2, prong, p_w)
|
||||
end
|
||||
if prong_right then
|
||||
surface.DrawRect(x + gap, y - p_w / 2, prong, p_w)
|
||||
end
|
||||
if prong_top then
|
||||
surface.DrawRect(x - p_w / 2, y - gap - prong, p_w, prong)
|
||||
end
|
||||
if prong_down then
|
||||
surface.DrawRect(x - p_w / 2, y + gap, p_w, prong)
|
||||
end
|
||||
end
|
||||
|
||||
if ArcCW.ConVars["crosshair_clump"]:GetBool() and (ArcCW.ConVars["crosshair_clump_always"]:GetBool() or num > 1) then
|
||||
local acc = math.max(1, gA)
|
||||
if ArcCW.ConVars["crosshair_clump_outline"]:GetBool() then
|
||||
surface.SetMaterial(clump_outer)
|
||||
|
||||
for i=1, prong_out do
|
||||
surface.DrawCircle(x-1, y-0, acc + math.ceil(i*0.5) * (i % 2 == 1 and 1 or -1), outlineClr.r, outlineClr.g, outlineClr.b, outlineClr.a * self.CrosshairDelta)
|
||||
end
|
||||
surface.DrawCircle(x-1, y-0, acc, outlineClr.r, outlineClr.g, outlineClr.b, outlineClr.a * self.CrosshairDelta)
|
||||
end
|
||||
|
||||
surface.DrawCircle(x-1, y-0, acc, clr.r, clr.g, clr.b, clr.a * self.CrosshairDelta)
|
||||
end
|
||||
|
||||
self:GetBuff_Hook("Hook_PostDrawCrosshair", w2s)
|
||||
|
||||
return true
|
||||
end
|
||||
3102
lua/weapons/arccw_base/cl_customize2.lua
Normal file
3102
lua/weapons/arccw_base/cl_customize2.lua
Normal file
File diff suppressed because it is too large
Load Diff
968
lua/weapons/arccw_base/cl_holosight.lua
Normal file
968
lua/weapons/arccw_base/cl_holosight.lua
Normal file
@@ -0,0 +1,968 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
function SWEP:DoHolosight()
|
||||
|
||||
-- In VRMod, we draw all holosights all the time
|
||||
if vrmod and vrmod.IsPlayerInVR(self:GetOwner()) then
|
||||
for i, asight in pairs(self.SightTable) do
|
||||
local aslot = self.Attachments[asight.Slot] or {}
|
||||
local atttbl = asight.HolosightData
|
||||
|
||||
if !atttbl and aslot.Installed then
|
||||
atttbl = ArcCW.AttachmentTable[aslot.Installed]
|
||||
|
||||
if !atttbl.Holosight then return end
|
||||
end
|
||||
|
||||
if atttbl then
|
||||
local hsp = asight.HolosightPiece or self.HSPElement
|
||||
local hsm = asight.HolosightModel
|
||||
|
||||
if !hsp and !hsm then
|
||||
self:SetupActiveSights()
|
||||
return
|
||||
end
|
||||
|
||||
self:DrawHolosight(atttbl, hsm, hsp, asight)
|
||||
end
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
local asight = self:GetActiveSights()
|
||||
if !asight then return end
|
||||
local aslot = self.Attachments[asight.Slot] or {}
|
||||
|
||||
local atttbl = asight.HolosightData
|
||||
|
||||
if !atttbl and aslot.Installed then
|
||||
atttbl = ArcCW.AttachmentTable[aslot.Installed]
|
||||
|
||||
if !atttbl.Holosight then return end
|
||||
end
|
||||
|
||||
if atttbl then
|
||||
local hsp = asight.HolosightPiece or self.HSPElement
|
||||
local hsm = asight.HolosightModel
|
||||
|
||||
if !hsp and !hsm then
|
||||
self:SetupActiveSights()
|
||||
return
|
||||
end
|
||||
|
||||
self:DrawHolosight(atttbl, hsm, hsp)
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:ShouldFlatScope()
|
||||
return false -- this system was removed, but we need to keep this function
|
||||
end
|
||||
|
||||
local rtsize = ScrH()
|
||||
|
||||
local rtmat = GetRenderTarget("arccw_rtmat", rtsize, rtsize, false)
|
||||
local rtmat_cheap = GetRenderTarget("arccw_rtmat_cheap", ScrW(), ScrH(), false)
|
||||
local rtmat_spare = GetRenderTarget("arccw_rtmat_spare", ScrW(), ScrH(), false)
|
||||
|
||||
|
||||
local thermal = Material("models/debug/debugwhite")
|
||||
local colormod = Material("pp/colour")
|
||||
local coldtime = 30
|
||||
|
||||
local additionalFOVconvar = ArcCW.ConVars["vm_add_ads"]
|
||||
|
||||
local matRefract = Material("pp/arccw/refract_rt")
|
||||
local matRefract_cheap = Material("pp/arccw/refract_cs") -- cheap scopes stretches square overlays so i need to make it 16x9
|
||||
|
||||
matRefract:SetTexture("$fbtexture", render.GetScreenEffectTexture())
|
||||
matRefract_cheap:SetTexture("$fbtexture", render.GetScreenEffectTexture())
|
||||
|
||||
timer.Create("ihategmod", 5, 0, function() -- i really dont know what the fucking problem with cheap scopes they dont want to set texture as not cheap ones
|
||||
matRefract_cheap:SetTexture("$fbtexture", render.GetScreenEffectTexture())
|
||||
matRefract:SetTexture("$fbtexture", render.GetScreenEffectTexture()) -- not cheap scope here why not
|
||||
end)
|
||||
|
||||
local pp_ca_base, pp_ca_r, pp_ca_g, pp_ca_b = Material("pp/arccw/ca_base"), Material("pp/arccw/ca_r"), Material("pp/arccw/ca_g"), Material("pp/arccw/ca_b")
|
||||
local pp_ca_r_thermal, pp_ca_g_thermal, pp_ca_b_thermal = Material("pp/arccw/ca_r_thermal"), Material("pp/arccw/ca_g_thermal"), Material("pp/arccw/ca_b_thermal")
|
||||
|
||||
pp_ca_r:SetTexture("$basetexture", render.GetScreenEffectTexture())
|
||||
pp_ca_g:SetTexture("$basetexture", render.GetScreenEffectTexture())
|
||||
pp_ca_b:SetTexture("$basetexture", render.GetScreenEffectTexture())
|
||||
|
||||
pp_ca_r_thermal:SetTexture("$basetexture", render.GetScreenEffectTexture())
|
||||
pp_ca_g_thermal:SetTexture("$basetexture", render.GetScreenEffectTexture())
|
||||
pp_ca_b_thermal:SetTexture("$basetexture", render.GetScreenEffectTexture())
|
||||
|
||||
local greenColor = Color(0, 255, 0) -- optimized +10000fps
|
||||
local whiteColor = Color(255, 255, 255)
|
||||
local blackColor = Color(0, 0, 0)
|
||||
|
||||
local function DrawTexturedRectRotatedPoint( x, y, w, h, rot, x0, y0 ) -- stolen from gmod wiki
|
||||
local c = math.cos( math.rad( rot ) )
|
||||
local s = math.sin( math.rad( rot ) )
|
||||
|
||||
local newx = y0 * s - x0 * c
|
||||
local newy = y0 * c + x0 * s
|
||||
|
||||
surface.DrawTexturedRectRotated( x + newx, y + newy, w, h, rot )
|
||||
end
|
||||
|
||||
|
||||
local function IsWHOT(ent)
|
||||
if !ent:IsValid() or ent:IsWorld() then return false end
|
||||
|
||||
if ent:IsPlayer() then -- balling
|
||||
if ent.ArcticMedShots_ActiveEffects and ent.ArcticMedShots_ActiveEffects["coldblooded"] or ent:Health() <= 0 then return false end -- arc stims
|
||||
return true
|
||||
end
|
||||
|
||||
if ent:IsNPC() or ent:IsNextBot() then -- npcs
|
||||
if ent.ArcCWCLHealth and ent.ArcCWCLHealth <= 0 or ent:Health() <= 0 then return false end
|
||||
return true
|
||||
end
|
||||
|
||||
if ent:IsRagdoll() then -- ragdolling
|
||||
if !ent.ArcCW_ColdTime then ent.ArcCW_ColdTime = CurTime() + coldtime end
|
||||
return ent.ArcCW_ColdTime > CurTime()
|
||||
end
|
||||
|
||||
if ent:IsVehicle() or ent:IsOnFire() or ent.ArcCW_Hot or ent:IsScripted() and !ent:GetOwner():IsValid() then -- vroom vroom + :fire: + ents but not guns (guns on ground will be fine)
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function SWEP:FormThermalImaging(tex)
|
||||
if !tex then
|
||||
tex = render.GetRenderTarget()
|
||||
end
|
||||
|
||||
render.PushRenderTarget(tex)
|
||||
|
||||
cam.Start3D()
|
||||
|
||||
if tex then
|
||||
colormod:SetTexture("$fbtexture", tex)
|
||||
else
|
||||
colormod:SetTexture("$fbtexture", render.GetScreenEffectTexture())
|
||||
end
|
||||
|
||||
local asight = self:GetActiveSights()
|
||||
|
||||
local nvsc = asight.ThermalScopeColor or whiteColor
|
||||
local tvsc = asight.ThermalHighlightColor or whiteColor
|
||||
|
||||
local tab = ents.GetAll()
|
||||
|
||||
-- table.Add(tab, player.GetAll())
|
||||
-- table.Add(tab, ents.FindByClass("npc_*"))
|
||||
|
||||
render.SetStencilEnable(true)
|
||||
render.SetStencilWriteMask(255)
|
||||
render.SetStencilTestMask(255)
|
||||
render.ClearStencil()
|
||||
|
||||
local sw = ScrH()
|
||||
local sh = sw
|
||||
|
||||
local sx = (ScrW() - sw) / 2
|
||||
local sy = (ScrH() - sh) / 2
|
||||
|
||||
render.SetScissorRect( sx, sy, sx + sw, sy + sh, true )
|
||||
|
||||
render.SetStencilReferenceValue(64)
|
||||
|
||||
render.SetStencilPassOperation(STENCIL_REPLACE)
|
||||
render.SetStencilFailOperation(STENCIL_KEEP)
|
||||
render.SetStencilZFailOperation(STENCIL_KEEP)
|
||||
render.SetStencilCompareFunction(STENCIL_ALWAYS)
|
||||
|
||||
for _, v in pairs(tab) do
|
||||
|
||||
if !IsWHOT(v) then continue end
|
||||
|
||||
if !asight.ThermalScopeSimple then
|
||||
render.SetBlend(0.5)
|
||||
render.SuppressEngineLighting(true)
|
||||
|
||||
render.SetColorModulation(250, 250, 250)
|
||||
|
||||
v:DrawModel()
|
||||
end
|
||||
end
|
||||
|
||||
render.SetColorModulation(1, 1, 1)
|
||||
|
||||
render.SuppressEngineLighting(false)
|
||||
|
||||
render.MaterialOverride()
|
||||
|
||||
render.SetBlend(1)
|
||||
|
||||
render.SetStencilCompareFunction(STENCIL_EQUAL)
|
||||
|
||||
if asight.ThermalScopeSimple then
|
||||
surface.SetDrawColor(255, 255, 255, 255)
|
||||
surface.DrawRect(0, 0, ScrW(), ScrH())
|
||||
end
|
||||
|
||||
DrawColorModify({
|
||||
["$pp_colour_addr"] = 0,
|
||||
["$pp_colour_addg"] = 0,
|
||||
["$pp_colour_addb"] = 0,
|
||||
["$pp_colour_brightness"] = 0,
|
||||
["$pp_colour_contrast"] = 1,
|
||||
["$pp_colour_colour"] = 0,
|
||||
["$pp_colour_mulr"] = 0,
|
||||
["$pp_colour_mulg"] = 0,
|
||||
["$pp_colour_mulb"] = 0
|
||||
})
|
||||
|
||||
DrawColorModify({
|
||||
["$pp_colour_addr"] = tvsc.r - 255,
|
||||
["$pp_colour_addg"] = tvsc.g - 255,
|
||||
["$pp_colour_addb"] = tvsc.b - 255,
|
||||
["$pp_colour_addr"] = 0,
|
||||
["$pp_colour_addg"] = 0,
|
||||
["$pp_colour_addb"] = 0,
|
||||
["$pp_colour_brightness"] = 0,
|
||||
["$pp_colour_contrast"] = 1,
|
||||
["$pp_colour_colour"] = 1,
|
||||
["$pp_colour_mulr"] = 0,
|
||||
["$pp_colour_mulg"] = 0,
|
||||
["$pp_colour_mulb"] = 0
|
||||
})
|
||||
|
||||
if !asight.ThermalNoCC then
|
||||
render.SetStencilCompareFunction(STENCIL_NOTEQUAL)
|
||||
render.SetStencilPassOperation(STENCIL_KEEP)
|
||||
|
||||
if !asight.ThermalFullColor then
|
||||
DrawColorModify({
|
||||
["$pp_colour_addr"] = 0,
|
||||
["$pp_colour_addg"] = 0,
|
||||
["$pp_colour_addb"] = 0,
|
||||
["$pp_colour_brightness"] = 0,
|
||||
["$pp_colour_contrast"] = 1,
|
||||
["$pp_colour_colour"] = 0,
|
||||
["$pp_colour_mulr"] = 0,
|
||||
["$pp_colour_mulg"] = 0,
|
||||
["$pp_colour_mulb"] = 0
|
||||
})
|
||||
end
|
||||
|
||||
if ArcCW.ConVars["thermalpp"]:GetBool() and ArcCW.ConVars["scopepp"]:GetBool() then
|
||||
-- chromatic abberation
|
||||
|
||||
render.CopyRenderTargetToTexture(render.GetScreenEffectTexture())
|
||||
|
||||
render.SetMaterial( pp_ca_base )
|
||||
render.DrawScreenQuad()
|
||||
render.SetMaterial( pp_ca_r_thermal )
|
||||
render.DrawScreenQuad()
|
||||
render.SetMaterial( pp_ca_g_thermal )
|
||||
render.DrawScreenQuad()
|
||||
render.SetMaterial( pp_ca_b_thermal )
|
||||
render.DrawScreenQuad()
|
||||
-- pasted here cause otherwise either target colors will get fucked either pp either motion blur
|
||||
end
|
||||
|
||||
DrawColorModify({
|
||||
["$pp_colour_addr"] = nvsc.r - 255,
|
||||
["$pp_colour_addg"] = nvsc.g - 255,
|
||||
["$pp_colour_addb"] = nvsc.b - 255,
|
||||
-- ["$pp_colour_addr"] = 0,
|
||||
-- ["$pp_colour_addg"] = 0,
|
||||
-- ["$pp_colour_addb"] = 0,
|
||||
["$pp_colour_brightness"] = asight.Brightness or 0.1,
|
||||
["$pp_colour_contrast"] = asight.Contrast or 0.5,
|
||||
["$pp_colour_colour"] = asight.Colormult or 1,
|
||||
["$pp_colour_mulr"] = 0,
|
||||
["$pp_colour_mulg"] = 0,
|
||||
["$pp_colour_mulb"] = 0
|
||||
})
|
||||
end
|
||||
|
||||
render.SetScissorRect( sx, sy, sx + sw, sy + sh, false )
|
||||
|
||||
render.SetStencilEnable(false)
|
||||
|
||||
colormod:SetTexture("$fbtexture", render.GetScreenEffectTexture())
|
||||
|
||||
cam.End3D()
|
||||
|
||||
if ArcCW.ConVars["thermalpp"]:GetBool() then
|
||||
if !render.SupportsPixelShaders_2_0() then return end
|
||||
|
||||
DrawSharpen(0.3,0.9)
|
||||
DrawBloom(0,0.3,5,5,3,0.5,1,1,1)
|
||||
-- DrawMotionBlur(0.7,1,1/(asight.FPSLock or 45)) -- upd i changed order and it fucking worked lmao //////i cant fucking understand why motionblur fucks render target
|
||||
end
|
||||
|
||||
render.PopRenderTarget()
|
||||
end
|
||||
|
||||
function SWEP:FormNightVision(tex)
|
||||
local asight = self:GetActiveSights()
|
||||
|
||||
local orig = colormod:GetTexture("$fbtexture")
|
||||
|
||||
colormod:SetTexture("$fbtexture", tex)
|
||||
|
||||
render.PushRenderTarget(tex)
|
||||
|
||||
local nvsc = asight.NVScopeColor or greenColor
|
||||
|
||||
if !asight.NVFullColor then
|
||||
DrawColorModify({
|
||||
["$pp_colour_addr"] = 0,
|
||||
["$pp_colour_addg"] = 0,
|
||||
["$pp_colour_addb"] = 0,
|
||||
["$pp_colour_brightness"] = 0,
|
||||
["$pp_colour_contrast"] = 1,
|
||||
["$pp_colour_colour"] = 0,
|
||||
["$pp_colour_mulr"] = 0,
|
||||
["$pp_colour_mulg"] = 0,
|
||||
["$pp_colour_mulb"] = 0
|
||||
})
|
||||
end
|
||||
|
||||
DrawColorModify({
|
||||
["$pp_colour_addr"] = nvsc.r - 255,
|
||||
["$pp_colour_addg"] = nvsc.g - 255,
|
||||
["$pp_colour_addb"] = nvsc.b - 255,
|
||||
["$pp_colour_brightness"] = asight.Brightness or -0.05,
|
||||
["$pp_colour_contrast"] = asight.Contrast or 4,
|
||||
["$pp_colour_colour"] = 1,
|
||||
["$pp_colour_mulr"] = 0,
|
||||
["$pp_colour_mulg"] = 0,
|
||||
["$pp_colour_mulb"] = 0
|
||||
})
|
||||
|
||||
render.PopRenderTarget()
|
||||
|
||||
colormod:SetTexture("$fbtexture", orig)
|
||||
end
|
||||
|
||||
local pp_cc_tab = {
|
||||
["$pp_colour_addr"] = 0,
|
||||
["$pp_colour_addg"] = 0,
|
||||
["$pp_colour_addb"] = 0,
|
||||
["$pp_colour_brightness"] = 0, -- why nothing works hh
|
||||
["$pp_colour_contrast"] = 0.9, -- but same time chroma dont work without calling it
|
||||
["$pp_colour_colour"] = 1,
|
||||
["$pp_colour_mulr"] = 0,
|
||||
["$pp_colour_mulg"] = 0,
|
||||
["$pp_colour_mulb"] = 0
|
||||
}
|
||||
|
||||
function SWEP:FormPP(tex)
|
||||
if !render.SupportsPixelShaders_2_0() then return end
|
||||
|
||||
local asight = self:GetActiveSights()
|
||||
|
||||
if asight.Thermal then return end -- eyah
|
||||
|
||||
local cs = ArcCW.ConVars["cheapscopes"]:GetBool()
|
||||
local refract = ArcCW.ConVars["scopepp_refract"]:GetBool()
|
||||
local pp = ArcCW.ConVars["scopepp"]:GetBool()
|
||||
|
||||
|
||||
if refract or pp then
|
||||
if !cs then render.PushRenderTarget(tex) end
|
||||
render.CopyRenderTargetToTexture(render.GetScreenEffectTexture())
|
||||
|
||||
if pp then
|
||||
render.SetMaterial( pp_ca_base )
|
||||
render.DrawScreenQuad()
|
||||
render.SetMaterial( pp_ca_r )
|
||||
render.DrawScreenQuad()
|
||||
render.SetMaterial( pp_ca_g )
|
||||
render.DrawScreenQuad()
|
||||
render.SetMaterial( pp_ca_b )
|
||||
render.DrawScreenQuad()
|
||||
-- Color modify
|
||||
|
||||
DrawColorModify( pp_cc_tab )
|
||||
-- Sharpen
|
||||
DrawSharpen(-0.1, 5) -- dont work for some reason
|
||||
end
|
||||
|
||||
if refract then
|
||||
local addads = math.Clamp(additionalFOVconvar:GetFloat(), -2, 14)
|
||||
local refractratio = ArcCW.ConVars["scopepp_refract_ratio"]:GetFloat() or 0
|
||||
local refractamount = (-0.6 + addads / 30) * refractratio
|
||||
local refractmat = cs and matRefract_cheap or matRefract
|
||||
|
||||
refractmat:SetFloat( "$refractamount", refractamount )
|
||||
|
||||
render.SetMaterial(refractmat)
|
||||
render.DrawScreenQuad()
|
||||
end
|
||||
|
||||
if !cs then render.PopRenderTarget() end
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:FormCheapScope()
|
||||
local screen = render.GetRenderTarget()
|
||||
|
||||
render.CopyTexture( screen, rtmat_spare )
|
||||
|
||||
render.PushRenderTarget(screen)
|
||||
cam.Start3D(EyePos(), EyeAngles(), nil, nil, nil, nil, nil, 0, nil)
|
||||
ArcCW.LaserBehavior = true
|
||||
self:DoLaser(false)
|
||||
ArcCW.LaserBehavior = false
|
||||
cam.End3D()
|
||||
|
||||
self:FormPP(screen)
|
||||
|
||||
render.PopRenderTarget()
|
||||
|
||||
-- so, in order to avoid the fact that copying RTs doesn't transfer depth buffer data, we just take the screen texture and...
|
||||
-- redraw it to cover up the thermal scope stuff. Don't think too hard about this. You have plenty of VRAM.
|
||||
|
||||
local asight = self:GetActiveSights()
|
||||
|
||||
if asight.Thermal then
|
||||
self:FormThermalImaging(screen)
|
||||
end
|
||||
|
||||
if asight.SpecialScopeFunction then
|
||||
asight.SpecialScopeFunction(screen)
|
||||
end
|
||||
|
||||
-- integrated render delay for better optimization
|
||||
if asight.FPSLock then
|
||||
asight.fpsdelay = CurTime() + 1 / (asight.FPSLock or 45)
|
||||
end
|
||||
|
||||
render.CopyTexture( screen, rtmat_cheap )
|
||||
|
||||
render.DrawTextureToScreen(rtmat_spare)
|
||||
|
||||
render.UpdateFullScreenDepthTexture()
|
||||
end
|
||||
|
||||
function SWEP:FormRTScope()
|
||||
local asight = self:GetActiveSights()
|
||||
|
||||
if !asight then return end
|
||||
|
||||
if !asight.MagnifiedOptic then return end
|
||||
|
||||
local mag = asight.ScopeMagnification
|
||||
|
||||
cam.Start3D()
|
||||
|
||||
ArcCW.Overdraw = true
|
||||
ArcCW.LaserBehavior = true
|
||||
ArcCW.VMInRT = true
|
||||
|
||||
local rtangles, rtpos, rtdrawvm
|
||||
|
||||
if self:GetState() == ArcCW.STATE_SIGHTS then
|
||||
if ArcCW.ConVars["drawbarrel"]:GetBool() and ArcCW.ConVars["vm_coolsway"]:GetBool() and asight.Slot and asight.Slot == 1 then -- slot check to ignore integrated
|
||||
rtangles = self.VMAng - self.VMAngOffset - (self:GetOurViewPunchAngles() * mag * 0.1)
|
||||
rtangles.x = rtangles.x - self.VMPosOffset_Lerp.z * 10
|
||||
rtangles.y = rtangles.y + self.VMPosOffset_Lerp.y * 10
|
||||
|
||||
rtpos = self.VMPos + self.VMAng:Forward() * (asight.EVPos.y + 7 + (asight.ScopeMagnificationMax and asight.ScopeMagnificationMax / 3 or asight.HolosightData.HolosightMagnification / 3)) -- eh
|
||||
rtdrawvm = true
|
||||
else
|
||||
rtangles = EyeAngles()
|
||||
rtpos = EyePos()
|
||||
rtdrawvm = false
|
||||
|
||||
-- HACK HACK HACK HACK HACK
|
||||
-- If we do not draw the viewmodel in RT scope, calling GetAttachment on the vm seems to break LHIK.
|
||||
-- So... just draw it! The results gets drawn over again so it doesn't affect the outcome
|
||||
render.RenderView({drawviewmodel = true}) -- ?????
|
||||
end
|
||||
end
|
||||
|
||||
local addads = math.Clamp(additionalFOVconvar:GetFloat(), -2, 14)
|
||||
|
||||
local rt = {
|
||||
w = rtsize,
|
||||
h = rtsize,
|
||||
angles = rtangles,
|
||||
origin = rtpos,
|
||||
drawviewmodel = rtdrawvm,
|
||||
fov = self:GetOwner():GetFOV() / mag / 1.2 - (addads or 0) / 4,
|
||||
}
|
||||
|
||||
rtsize = ScrH()
|
||||
|
||||
if ScrH() > ScrW() then rtsize = ScrW() end
|
||||
|
||||
local rtres = asight.ForceLowRes and ScrH() * 0.6 or ScrH() -- we can emit low res lcd displays for scopes
|
||||
|
||||
rtmat = GetRenderTarget("arccw_rtmat" .. rtres, rtres, rtres, false)
|
||||
|
||||
render.PushRenderTarget(rtmat, 0, 0, rtsize, rtsize)
|
||||
|
||||
render.ClearRenderTarget(rt, blackColor)
|
||||
|
||||
if self:GetState() == ArcCW.STATE_SIGHTS then
|
||||
render.RenderView(rt)
|
||||
cam.Start3D(EyePos(), EyeAngles(), rt.fov, 0, 0, nil, nil, 0, nil)
|
||||
self:DoLaser(false)
|
||||
cam.End3D()
|
||||
end
|
||||
|
||||
ArcCW.Overdraw = false
|
||||
ArcCW.LaserBehavior = false
|
||||
ArcCW.VMInRT = false
|
||||
|
||||
self:FormPP(rtmat)
|
||||
|
||||
render.PopRenderTarget()
|
||||
|
||||
cam.End3D()
|
||||
|
||||
if asight.Thermal then
|
||||
self:FormThermalImaging(rtmat)
|
||||
end
|
||||
|
||||
if asight.SpecialScopeFunction then
|
||||
asight.SpecialScopeFunction(rtmat)
|
||||
end
|
||||
|
||||
-- integrated render delay for better optimization
|
||||
if asight.FPSLock then
|
||||
asight.fpsdelay = CurTime() + 1 / (asight.FPSLock or 45)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- local fpsdelay = CurTime()
|
||||
|
||||
hook.Add("RenderScene", "ArcCW", function()
|
||||
if ArcCW.ConVars["cheapscopes"]:GetBool() then return end
|
||||
|
||||
local wpn = LocalPlayer():GetActiveWeapon()
|
||||
|
||||
if !wpn.ArcCW then return end
|
||||
if wpn:GetActiveSights() and wpn:GetActiveSights().FPSLock
|
||||
and (wpn:GetActiveSights().fpsdelay or 0) > CurTime() then
|
||||
return
|
||||
end
|
||||
wpn:FormRTScope()
|
||||
end)
|
||||
|
||||
local black = Material("arccw/hud/black.png")
|
||||
local defaultdot = Material("arccw/hud/hit_dot.png")
|
||||
|
||||
function SWEP:DrawHolosight(hs, hsm, hsp, asight)
|
||||
-- holosight structure
|
||||
-- holosight model
|
||||
|
||||
local ref = 32
|
||||
|
||||
asight = asight or self:GetActiveSights()
|
||||
local delta = self:GetSightDelta()
|
||||
|
||||
if asight.HolosightData then
|
||||
hs = asight.HolosightData
|
||||
end
|
||||
|
||||
if self:GetState() != ArcCW.STATE_SIGHTS and delta > 0.5 or self:GetBarrelNearWall() > 0 then return end
|
||||
|
||||
if !hs then return end
|
||||
|
||||
if delta != 0 and ArcCW.ConVars["scopepp"]:GetBool() then
|
||||
pp_ca_r:SetVector("$color2", Vector(1-delta, 0, 0))
|
||||
pp_ca_g:SetVector("$color2", Vector(0, 1-delta, 0))
|
||||
pp_ca_b:SetVector("$color2", Vector(0, 0, 1-delta))
|
||||
pp_ca_base:SetFloat("$alpha", 1-delta)
|
||||
end
|
||||
|
||||
local hsc = Color(255, 255, 255) -- putting here global or white local SOMEHOW FUCKS IT EVEN GLOBAL BEING FUCKED WTF I HATE
|
||||
|
||||
if hs.Colorable then
|
||||
hsc.r = ArcCW.ConVars["scope_r"]:GetInt()
|
||||
hsc.g = ArcCW.ConVars["scope_g"]:GetInt()
|
||||
hsc.b = ArcCW.ConVars["scope_b"]:GetInt()
|
||||
else
|
||||
hsc = hs.HolosightColor or hsc
|
||||
end
|
||||
|
||||
local attid = 0
|
||||
|
||||
if hsm then
|
||||
|
||||
attid = hsm:LookupAttachment(asight.HolosightBone or hs.HolosightBone or "holosight")
|
||||
|
||||
if attid == 0 then
|
||||
attid = hsm:LookupAttachment("holosight")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local ret, pos, ang
|
||||
|
||||
if attid != 0 then
|
||||
|
||||
ret = hsm:GetAttachment(attid)
|
||||
pos = ret.Pos
|
||||
ang = ret.Ang
|
||||
|
||||
else
|
||||
|
||||
pos = EyePos()
|
||||
ang = EyeAngles()
|
||||
|
||||
end
|
||||
|
||||
local hsmag = asight.ScopeMagnification or 1
|
||||
|
||||
local size = hs.HolosightSize or 1
|
||||
|
||||
local addads = math.Clamp(additionalFOVconvar:GetFloat(), -2, 14)
|
||||
|
||||
local addconvar = asight.MagnifiedOptic and (addads or 0) or 0
|
||||
|
||||
size = size + addconvar + (addconvar > 5.5 and (addconvar-5.5) * 2 or 0)
|
||||
|
||||
|
||||
-- if asight.NightVision then
|
||||
|
||||
if hsmag and hsmag > 1 and delta < 1 and asight.NVScope then
|
||||
local screen = rtmat
|
||||
|
||||
if ArcCW.ConVars["cheapscopes"]:GetBool() then
|
||||
screen = rtmat_cheap
|
||||
end
|
||||
|
||||
if asight.NVScope then
|
||||
self:FormNightVision(screen)
|
||||
end
|
||||
end
|
||||
|
||||
render.UpdateScreenEffectTexture()
|
||||
render.ClearStencil()
|
||||
render.SetStencilEnable(true)
|
||||
render.SetStencilCompareFunction(STENCIL_ALWAYS)
|
||||
render.SetStencilPassOperation(STENCIL_REPLACE)
|
||||
render.SetStencilFailOperation(STENCIL_KEEP)
|
||||
render.SetStencilZFailOperation(STENCIL_REPLACE)
|
||||
render.SetStencilWriteMask(255)
|
||||
render.SetStencilTestMask(255)
|
||||
|
||||
render.SetBlend(0)
|
||||
|
||||
render.SetStencilReferenceValue(ref)
|
||||
|
||||
ArcCW.Overdraw = true
|
||||
|
||||
render.OverrideDepthEnable( true, true )
|
||||
|
||||
if !hsm then
|
||||
hsp:DrawModel()
|
||||
else
|
||||
|
||||
hsm:SetBodygroup(1, 0)
|
||||
|
||||
if !hsp or hs.HolosightNoHSP then
|
||||
hsm:DrawModel()
|
||||
end
|
||||
|
||||
-- render.MaterialOverride()
|
||||
|
||||
render.SetStencilReferenceValue(0)
|
||||
|
||||
hsm:SetBodygroup(1, 1)
|
||||
-- hsm:SetSubMaterial(0, "dev/no_pixel_write")
|
||||
hsm:DrawModel()
|
||||
-- hsm:SetSubMaterial()
|
||||
hsm:SetBodygroup(1, 0)
|
||||
|
||||
-- local vm = self:GetOwner():GetViewModel()
|
||||
|
||||
-- ArcCW.Overdraw = true
|
||||
-- vm:DrawModel()
|
||||
|
||||
-- ArcCW.Overdraw = false
|
||||
|
||||
render.SetStencilReferenceValue(ref)
|
||||
|
||||
if hsp then
|
||||
hsp:DrawModel()
|
||||
end
|
||||
end
|
||||
|
||||
-- render.MaterialOverride()
|
||||
|
||||
render.OverrideDepthEnable( false, true )
|
||||
|
||||
ArcCW.Overdraw = false
|
||||
|
||||
render.SetBlend(1)
|
||||
|
||||
render.SetStencilPassOperation(STENCIL_REPLACE)
|
||||
render.SetStencilCompareFunction(STENCIL_EQUAL)
|
||||
|
||||
-- local pos = EyePos()
|
||||
-- local ang = EyeAngles()
|
||||
|
||||
ang:RotateAroundAxis(ang:Forward(), -90)
|
||||
|
||||
local dir = ang:Up()
|
||||
|
||||
local pdiff = (pos - EyePos()):Length()
|
||||
|
||||
pos = LerpVector(delta, EyePos(), pos)
|
||||
|
||||
local eyeangs = self:GetOwner():EyeAngles() - self:GetOurViewPunchAngles() * hsmag * 0.1
|
||||
|
||||
-- local vm = hsm or hsp
|
||||
|
||||
-- eyeangs = eyeangs + (eyeangs - vm:GetAngles())
|
||||
|
||||
dir = LerpVector(delta, eyeangs:Forward(), dir:GetNormalized())
|
||||
|
||||
pdiff = Lerp(delta, pdiff, 0)
|
||||
|
||||
local d = (8 + pdiff)
|
||||
|
||||
d = hs.HolosightConstDist or d
|
||||
|
||||
local vmscale = (self.Attachments[asight.Slot] or {}).VMScale or Vector(1, 1, 1)
|
||||
|
||||
if hs.HolosightConstDist then
|
||||
vmscale = Vector(1, 1, 1)
|
||||
end
|
||||
|
||||
local hsx = vmscale[2] or 1
|
||||
local hsy = vmscale[3] or 1
|
||||
|
||||
pos = pos + (dir * d)
|
||||
|
||||
local pos2 = pos + (dir * -8)
|
||||
|
||||
local a = self:GetOwner():InVehicle() and {x = ScrW() / 2, y = ScrH() / 2} or pos:ToScreen()
|
||||
local x = a.x - (self.VMAngOffset.y - self.VMPosOffset_Lerp.y * 10) * (hsmag * 1.5) ^ 2
|
||||
local y = a.y + (self.VMAngOffset.x * 5 + self.VMPosOffset_Lerp.z * 10) * (hsmag * 1.5) ^ 2
|
||||
|
||||
local a2 = self:GetOwner():InVehicle() and {x = ScrW() / 2, y = ScrH() / 2} or pos2:ToScreen()
|
||||
|
||||
local off_x = a2.x - (ScrW() / 2)
|
||||
local off_y = a2.y - (ScrH() / 2)
|
||||
|
||||
--pos = pos + Vector(ArcCW.StrafeTilt(self), 0, 0)
|
||||
|
||||
-- local corner1, corner2, corner3, corner4
|
||||
|
||||
-- corner2 = pos + (ang:Right() * (-0.5 * size)) + (ang:Forward() * (0.5 * size))
|
||||
-- corner1 = pos + (ang:Right() * (-0.5 * size)) + (ang:Forward() * (-0.5 * size))
|
||||
-- corner4 = pos + (ang:Right() * (0.5 * size)) + (ang:Forward() * (-0.5 * size))
|
||||
-- corner3 = pos + (ang:Right() * (0.5 * size)) + (ang:Forward() * (0.5 * size))
|
||||
|
||||
-- render.SetColorMaterialIgnoreZ()
|
||||
-- render.DrawScreenQuad()
|
||||
|
||||
-- render.SetStencilEnable( false )
|
||||
-- local fovmag = asight.Magnification or 1
|
||||
|
||||
if hsmag and hsmag > 1 and delta < 1 then
|
||||
local screen = rtmat
|
||||
|
||||
-- local sw2 = ScrH()
|
||||
-- local sh2 = sw2
|
||||
|
||||
-- local sx2 = (ScrW() - sw2) / 2
|
||||
-- local sy2 = (ScrH() - sh2) / 2
|
||||
|
||||
-- render.SetScissorRect( sx2, sy2, sx2 + sw2, sy2 + sh2, true )
|
||||
|
||||
if render.GetHDREnabled() and delta < 0.07 then
|
||||
render.SetToneMappingScaleLinear(Vector(1,1,1)) -- hdr fix
|
||||
end
|
||||
|
||||
if ArcCW.ConVars["cheapscopes"]:GetBool() then
|
||||
|
||||
screen = rtmat_cheap
|
||||
|
||||
local addads = math.Clamp(additionalFOVconvar:GetFloat(), -2, 14)
|
||||
local csratio = math.Clamp(GetConVar("arccw_cheapscopesv2_ratio"):GetFloat(), 0, 1)
|
||||
|
||||
local ssmag = 1 + csratio * hsmag + (addads or 0) / 20 -- idk why 20
|
||||
local sw = ScrW() * ssmag
|
||||
local sh = ScrH() * ssmag
|
||||
|
||||
-- local sx = -(sw - ScrW()) / 2
|
||||
-- local sy = -(sh - ScrH()) / 2
|
||||
|
||||
local cpos = self:GetOwner():EyePos() + ((EyeAngles() + (self:GetOurViewPunchAngles() * 0.5)):Forward() * 2048)
|
||||
|
||||
--cpos:Rotate(Angle(0, -ArcCW.StrafeTilt(self), 0))
|
||||
|
||||
local ts = self:GetOwner():InVehicle() and {x = ScrW() / 2, y = ScrH() / 2} or cpos:ToScreen()
|
||||
|
||||
local sx = ts.x - (sw / 2) - off_x - (self.VMAngOffset.y - self.VMPosOffset_Lerp.y * 15) * (hsmag * 1) ^ 2
|
||||
local sy = ts.y - (sh / 2) - off_y + (self.VMAngOffset.x * 5 + self.VMPosOffset_Lerp.z * 15) * (hsmag * 1) ^ 2
|
||||
|
||||
render.SetMaterial(black)
|
||||
render.DrawScreenQuad()
|
||||
|
||||
render.DrawTextureToScreenRect(screen, sx, sy, sw, sh)
|
||||
|
||||
else
|
||||
|
||||
local sw = ScrH()
|
||||
local sh = sw
|
||||
|
||||
local sx = ((ScrW() - sw) / 2) - off_x
|
||||
local sy = ((ScrH() - sh) / 2) - off_x
|
||||
|
||||
render.SetMaterial(black)
|
||||
render.DrawScreenQuad()
|
||||
|
||||
render.DrawTextureToScreenRect(screen, sx, sy, sw, sh)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
-- cam.Start3D()
|
||||
|
||||
-- render.SetColorMaterialIgnoreZ()
|
||||
-- render.DrawScreenQuad()
|
||||
|
||||
-- render.DrawQuad( corner1, corner2, corner3, corner4, hsc or hs.HolosightColor )
|
||||
cam.IgnoreZ( true )
|
||||
|
||||
render.SetStencilReferenceValue(ref)
|
||||
|
||||
-- render.SetMaterial(hs.HolosightReticle or defaultdot)
|
||||
-- render.DrawSprite( pos, size * hsx, size * hsy, hsc or Color(255, 255, 255) )
|
||||
-- if !hs.HolosightNoFlare then
|
||||
-- render.SetMaterial(hs.HolosightFlare or hs.HolosightReticle or defaultdot)
|
||||
-- local hss = 0.75
|
||||
-- if hs.HolosightFlare then
|
||||
-- hss = 1
|
||||
-- end
|
||||
-- render.DrawSprite( pos, size * hss * hsx, size * hss * hsy, Color(255, 255, 255, 255) )
|
||||
-- end
|
||||
|
||||
cam.Start2D()
|
||||
|
||||
if hs.HolosightBlackbox then
|
||||
render.SetStencilPassOperation(STENCIL_KEEP)
|
||||
|
||||
surface.SetDrawColor(0, 0, 0, 255 * delta)
|
||||
surface.DrawRect(0, 0, ScrW(), ScrH())
|
||||
end
|
||||
|
||||
render.SetStencilPassOperation(STENCIL_DECR)
|
||||
render.SetStencilCompareFunction(STENCIL_EQUAL)
|
||||
|
||||
local hss = size * 32 * math.min(ScrW(), ScrH()) / 800
|
||||
|
||||
--local thej = self.TheJ.anga + LocalPlayer():GetViewPunchAngles() + self:GetOurViewPunchAngles()
|
||||
-- AYE, UR ACTIVE ANG BEIN TWISTED DUNT GIVE AUH SHET
|
||||
|
||||
surface.SetMaterial(hs.HolosightReticle or defaultdot)
|
||||
surface.SetDrawColor(hsc or 255, 255, 255)
|
||||
-- surface.DrawTexturedRect(x - (hss / 2), y - (hss / 2), hss, hss)
|
||||
|
||||
DrawTexturedRectRotatedPoint(x, y, hss, hss, -(self.VMAngOffset.r+self.VMAngOffset_Lerp.r+self:GetOurViewPunchAngles().r)*5 , 0, 0)
|
||||
|
||||
if !hs.HolosightNoFlare then
|
||||
render.SetStencilPassOperation(STENCIL_KEEP)
|
||||
render.SetStencilReferenceValue(ref - 1)
|
||||
surface.SetMaterial(hs.HolosightFlare or hs.HolosightReticle or defaultdot)
|
||||
surface.SetDrawColor(255, 255, 255, 150)
|
||||
|
||||
local hss2 = hss
|
||||
|
||||
if !hs.HolosightFlare then
|
||||
hss2 = hss - 2
|
||||
end
|
||||
|
||||
surface.DrawTexturedRect(x - (hss2 / 2), y - (hss2 / 2), hss2, hss2)
|
||||
--surface.DrawTexturedRectRotated(x, y, hss2, hss2, -thej.r or 0)
|
||||
|
||||
render.SetStencilReferenceValue(ref)
|
||||
end
|
||||
|
||||
if hs.HolosightBlackbox then
|
||||
-- render.SetColorMaterialIgnoreZ()
|
||||
-- render.DrawScreenQuad()
|
||||
|
||||
surface.SetDrawColor(0, 0, 0)
|
||||
surface.DrawRect(0, 0, ScrW(), ScrH())
|
||||
-- surface.DrawRect(0, (ScrH() - hss) / 2, ScrW(), (ScrH() - hss) / 2)
|
||||
end
|
||||
|
||||
cam.End2D()
|
||||
|
||||
render.SetStencilEnable( false )
|
||||
|
||||
cam.IgnoreZ( false )
|
||||
|
||||
-- cam.End3D()
|
||||
|
||||
if hsp then
|
||||
|
||||
cam.IgnoreZ(true)
|
||||
|
||||
if ArcCW.ConVars["glare"]:GetBool() then
|
||||
render.SetBlend(delta + 0.1)
|
||||
else
|
||||
render.SetBlend(delta)
|
||||
end
|
||||
hsp:DrawModel()
|
||||
render.SetBlend(1)
|
||||
|
||||
cam.IgnoreZ( false )
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- I wanted to make here procedural normal map for refract using rt but steamsnooze
|
||||
|
||||
|
||||
-- local TEX_SIZE = 512
|
||||
|
||||
-- local tex = GetRenderTarget( "ExampleRT", TEX_SIZE, TEX_SIZE )
|
||||
|
||||
-- local txBackground = surface.GetTextureID( "pp/arccw/lense_nrm2" )
|
||||
-- local myMat = CreateMaterial( "ExampleRTMat3", "UnlitGeneric", {
|
||||
-- ["$basetexture"] = tex:GetName() -- Make the material use our render target texture
|
||||
-- } )
|
||||
|
||||
-- hook.Add( "HUDPaint", "DrawExampleMat", function()
|
||||
-- render.PushRenderTarget( tex )
|
||||
-- cam.Start2D()
|
||||
|
||||
-- surface.SetDrawColor( 128,128,255 )
|
||||
-- surface.DrawRect(0,0,TEX_SIZE, TEX_SIZE)
|
||||
-- surface.SetDrawColor( color_white )
|
||||
-- surface.SetTexture( txBackground )
|
||||
-- local joke = math.sin(CurTime()*5)/4
|
||||
|
||||
-- surface.DrawTexturedRect( TEX_SIZE/4-joke/2, TEX_SIZE/4-joke/2, TEX_SIZE/2+joke, TEX_SIZE/2+joke )
|
||||
|
||||
-- cam.End2D()
|
||||
-- render.PopRenderTarget()
|
||||
-- surface.SetDrawColor( color_white )
|
||||
-- surface.SetMaterial( myMat )
|
||||
-- surface.DrawTexturedRect( 25, 25, TEX_SIZE, TEX_SIZE )
|
||||
-- print()
|
||||
-- DrawTexturedRectRotatedPoint(250+250/2,250+250/2,250,250,(CurTime()%360)*50,0,0)
|
||||
-- surface.DrawRect(250,250,250,250)
|
||||
|
||||
-- end )
|
||||
1205
lua/weapons/arccw_base/cl_hud.lua
Normal file
1205
lua/weapons/arccw_base/cl_hud.lua
Normal file
File diff suppressed because it is too large
Load Diff
199
lua/weapons/arccw_base/cl_laser.lua
Normal file
199
lua/weapons/arccw_base/cl_laser.lua
Normal file
@@ -0,0 +1,199 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
local mth = math
|
||||
local m_log10 = mth.log10
|
||||
local m_rand = mth.Rand
|
||||
local rnd = render
|
||||
local SetMat = rnd.SetMaterial
|
||||
local DrawBeam = rnd.DrawBeam
|
||||
local DrawSprite = rnd.DrawSprite
|
||||
local cam = cam
|
||||
|
||||
local lasermat = Material("arccw/laser")
|
||||
local flaremat = Material("effects/whiteflare")
|
||||
local delta = 1
|
||||
|
||||
function SWEP:DoLaser(world, nocontext)
|
||||
world = world or false
|
||||
|
||||
if !nocontext then
|
||||
if world then
|
||||
cam.Start3D()
|
||||
else
|
||||
cam.Start3D(EyePos(), EyeAngles(), self:QuickFOVix(self.CurrentViewModelFOV))
|
||||
end
|
||||
end
|
||||
|
||||
for slot, k in pairs(self.Attachments) do
|
||||
if !k.Installed then continue end
|
||||
|
||||
local attach = ArcCW.AttachmentTable[k.Installed]
|
||||
|
||||
if self:GetBuff_Stat("Laser", slot) then
|
||||
local color = self:GetBuff_Stat("LaserColor", slot) or attach.ColorOptionsTable[k.ColorOptionIndex or 1]
|
||||
|
||||
if world then
|
||||
if !k.WElement then continue end
|
||||
self:DrawLaser(attach, k.WElement.Model, color, true)
|
||||
else
|
||||
if !k.VElement then continue end
|
||||
self:DrawLaser(attach, k.VElement.Model, color)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if self.Lasers then
|
||||
if world then
|
||||
for _, k in pairs(self.Lasers) do
|
||||
self:DrawLaser(k, self.WMModel or self, k.LaserColor, true)
|
||||
end
|
||||
else
|
||||
-- cam.Start3D(nil, nil, self.ViewmodelFOV)
|
||||
for _, k in pairs(self.Lasers) do
|
||||
self:DrawLaser(k, self:GetOwner():GetViewModel(), k.LaserColor)
|
||||
end
|
||||
-- cam.End3D()
|
||||
end
|
||||
end
|
||||
|
||||
if !nocontext then
|
||||
cam.End3D()
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:DrawLaser(laser, model, color, world)
|
||||
local owner = self:GetOwner()
|
||||
local behav = ArcCW.LaserBehavior
|
||||
|
||||
if !owner then return end
|
||||
|
||||
if !IsValid(owner) then return end
|
||||
|
||||
if !model then return end
|
||||
|
||||
if !IsValid(model) then return end
|
||||
|
||||
local att = model:LookupAttachment(laser.LaserBone or "laser")
|
||||
|
||||
att = att == 0 and model:LookupAttachment("muzzle") or att
|
||||
|
||||
local pos, ang, dir
|
||||
|
||||
if att == 0 then
|
||||
pos = model:GetPos()
|
||||
ang = owner:EyeAngles() + self:GetFreeAimOffset()
|
||||
dir = ang:Forward()
|
||||
else
|
||||
local attdata = model:GetAttachment(att)
|
||||
pos, ang = attdata.Pos, attdata.Ang
|
||||
dir = -ang:Right()
|
||||
end
|
||||
|
||||
if world then
|
||||
dir = owner:IsNPC() and (-ang:Right()) or dir
|
||||
else
|
||||
ang:RotateAroundAxis(ang:Up(), 90)
|
||||
|
||||
if self.LaserOffsetAngle then
|
||||
ang:RotateAroundAxis(ang:Right(), self.LaserOffsetAngle[1])
|
||||
ang:RotateAroundAxis(ang:Up(), self.LaserOffsetAngle[2])
|
||||
ang:RotateAroundAxis(ang:Forward(), self.LaserOffsetAngle[3])
|
||||
end
|
||||
if self.LaserIronsAngle and self:GetActiveSights().IronSight then
|
||||
local d = 1 - self:GetSightDelta()
|
||||
ang:RotateAroundAxis(ang:Right(), d * self.LaserIronsAngle[1])
|
||||
ang:RotateAroundAxis(ang:Up(), d * self.LaserIronsAngle[2])
|
||||
ang:RotateAroundAxis(ang:Forward(), d * self.LaserIronsAngle[3])
|
||||
end
|
||||
|
||||
dir = ang:Forward()
|
||||
|
||||
local eyeang = EyeAngles() - self:GetOurViewPunchAngles() + self:GetFreeAimOffset()
|
||||
local canlaser = self:GetCurrentFiremode().Mode != 0 and !self:GetReloading() and self:BarrelHitWall() <= 0
|
||||
|
||||
delta = Lerp(0, delta, canlaser and self:GetSightDelta() or 1)
|
||||
|
||||
if self.GuaranteeLaser then
|
||||
delta = 1
|
||||
else
|
||||
delta = self:GetSightDelta()
|
||||
end
|
||||
|
||||
dir = Lerp(delta, eyeang:Forward(), dir)
|
||||
end
|
||||
|
||||
local beamdir, tracepos = dir, pos
|
||||
|
||||
beamdir = world and (-ang:Right()) or beamdir
|
||||
|
||||
if behav and !world then
|
||||
-- local cheap = ArcCW.ConVars["cheapscopes"]:GetBool()
|
||||
local punch = self:GetOurViewPunchAngles()
|
||||
|
||||
ang = EyeAngles() - punch + self:GetFreeAimOffset()
|
||||
|
||||
tracepos = EyePos() - Vector(0, 0, 1)
|
||||
pos, dir = tracepos, ang:Forward()
|
||||
beamdir = dir
|
||||
end
|
||||
|
||||
local dist = 128
|
||||
|
||||
local tl = {}
|
||||
tl.start = tracepos
|
||||
tl.endpos = tracepos + (dir * 33000)
|
||||
tl.filter = owner
|
||||
|
||||
local tr = util.TraceLine(tl)
|
||||
|
||||
tl.endpos = tracepos + (beamdir * dist)
|
||||
|
||||
local btr = util.TraceLine(tl)
|
||||
|
||||
local hit = tr.Hit
|
||||
local hitpos = tr.HitPos
|
||||
local solid = tr.StartSolid
|
||||
|
||||
local strength = laser.LaserStrength or 1
|
||||
local laserpos = solid and tr.StartPos or hitpos
|
||||
|
||||
laserpos = laserpos - ((EyeAngles() + self:GetFreeAimOffset()):Forward())
|
||||
|
||||
if solid then return end
|
||||
|
||||
local width = m_rand(0.05, 0.1) * strength * 1
|
||||
|
||||
if (!behav or world) and hit then
|
||||
SetMat(lasermat)
|
||||
local a = 200
|
||||
DrawBeam(pos, btr.HitPos, width * 0.3, 1, 0, Color(a, a, a, a))
|
||||
DrawBeam(pos, btr.HitPos, width, 1, 0, color)
|
||||
end
|
||||
|
||||
if hit and !tr.HitSky then
|
||||
local mul = 1 * strength
|
||||
mul = m_log10((hitpos - EyePos()):Length()) * strength
|
||||
local rad = m_rand(4, 6) * mul
|
||||
local glr = rad * m_rand(0.2, 0.3)
|
||||
|
||||
SetMat(flaremat)
|
||||
|
||||
-- if !world then
|
||||
-- cam.IgnoreZ(true)
|
||||
-- end
|
||||
DrawSprite(laserpos, rad, rad, color)
|
||||
DrawSprite(laserpos, glr, glr, color_white)
|
||||
|
||||
-- if !world then
|
||||
-- cam.IgnoreZ(false)
|
||||
-- end
|
||||
end
|
||||
end
|
||||
402
lua/weapons/arccw_base/cl_lhik.lua
Normal file
402
lua/weapons/arccw_base/cl_lhik.lua
Normal file
@@ -0,0 +1,402 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
local function qerp(delta, a, b)
|
||||
local qdelta = -(delta ^ 2) + (delta * 2)
|
||||
|
||||
qdelta = math.Clamp(qdelta, 0, 1)
|
||||
|
||||
return Lerp(qdelta, a, b)
|
||||
end
|
||||
|
||||
SWEP.LHIKAnimation_IsIdle = false
|
||||
SWEP.LHIKAnimation = nil
|
||||
SWEP.LHIKAnimationStart = 0
|
||||
SWEP.LHIKAnimationTime = 0
|
||||
|
||||
SWEP.LHIKCamAng = Angle(0, 0, 0)
|
||||
SWEP.LHIKGunAng = Angle(0, 0, 0)
|
||||
|
||||
function SWEP:DoLHIKAnimation(key, time, spbitch)
|
||||
if !IsValid(self:GetOwner()) then return end
|
||||
|
||||
if game.SinglePlayer() and !spbitch then
|
||||
timer.Simple(0, function() if IsValid(self) then self:DoLHIKAnimation(key, time, true) end end)
|
||||
return
|
||||
end
|
||||
|
||||
local vm = self:GetOwner():GetViewModel()
|
||||
if !IsValid(vm) then return end
|
||||
|
||||
local lhik_model
|
||||
local lhik_anim_model
|
||||
local LHIK_GunDriver
|
||||
local LHIK_CamDriver
|
||||
local offsetang
|
||||
|
||||
local tranim = self:GetBuff_Hook("Hook_LHIK_TranslateAnimation", key)
|
||||
|
||||
key = tranim or key
|
||||
|
||||
for i, k in pairs(self.Attachments) do
|
||||
if !k.Installed then continue end
|
||||
if !k.VElement then continue end
|
||||
|
||||
if self:GetBuff_Stat("LHIK", i) then
|
||||
lhik_model = k.VElement.Model
|
||||
lhik_anim_model = k.GodDriver and k.GodDriver.Model or false
|
||||
offsetang = k.VElement.OffsetAng
|
||||
|
||||
if self:GetBuff_Stat("LHIK_GunDriver", i) then
|
||||
LHIK_GunDriver = self:GetBuff_Stat("LHIK_GunDriver", i)
|
||||
end
|
||||
|
||||
if self:GetBuff_Stat("LHIK_CamDriver", i) then
|
||||
LHIK_CamDriver = self:GetBuff_Stat("LHIK_CamDriver", i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if !IsValid(lhik_model) then return false end
|
||||
|
||||
local seq = lhik_model:LookupSequence(key)
|
||||
|
||||
if !seq then return false end
|
||||
if seq == -1 then return false end
|
||||
|
||||
lhik_model:ResetSequence(seq)
|
||||
if IsValid(lhik_anim_model) then
|
||||
lhik_anim_model:ResetSequence(seq)
|
||||
end
|
||||
|
||||
if !time or time < 0 then time = lhik_model:SequenceDuration(seq) end
|
||||
|
||||
self.LHIKAnimation = seq
|
||||
self.LHIKAnimationStart = UnPredictedCurTime()
|
||||
self.LHIKAnimationTime = time
|
||||
|
||||
self.LHIKAnimation_IsIdle = false
|
||||
|
||||
if IsValid(lhik_anim_model) and LHIK_GunDriver then
|
||||
local att = lhik_anim_model:LookupAttachment(LHIK_GunDriver)
|
||||
local ang = lhik_anim_model:GetAttachment(att).Ang
|
||||
local pos = lhik_anim_model:GetAttachment(att).Pos
|
||||
|
||||
self.LHIKGunAng = lhik_anim_model:WorldToLocalAngles(ang) - Angle(0, 90, 90)
|
||||
self.LHIKGunPos = lhik_anim_model:WorldToLocal(pos)
|
||||
|
||||
self.LHIKGunAngVM = vm:WorldToLocalAngles(ang) - Angle(0, 90, 90)
|
||||
self.LHIKGunPosVM = vm:WorldToLocal(pos)
|
||||
end
|
||||
|
||||
if IsValid(lhik_anim_model) and LHIK_CamDriver then
|
||||
local att = lhik_anim_model:LookupAttachment(LHIK_CamDriver)
|
||||
local ang = lhik_anim_model:GetAttachment(att).Ang
|
||||
|
||||
self.LHIKCamOffsetAng = offsetang
|
||||
self.LHIKCamAng = lhik_anim_model:WorldToLocalAngles(ang)
|
||||
end
|
||||
|
||||
-- lhik_model:SetCycle(0)
|
||||
-- lhik_model:SetPlaybackRate(dur / time)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
SWEP.LHIKDelta = {}
|
||||
SWEP.LHIKDeltaAng = {}
|
||||
SWEP.ViewModel_Hit = Vector(0, 0, 0)
|
||||
SWEP.Customize_Hide = 0
|
||||
|
||||
function SWEP:GetLHIKAnim()
|
||||
local cyc = (UnPredictedCurTime() - self.LHIKAnimationStart) / self.LHIKAnimationTime
|
||||
|
||||
if cyc > 1 then return nil end
|
||||
if self.LHIKAnimation_IsIdle then return nil end
|
||||
|
||||
return self.LHIKAnimation
|
||||
end
|
||||
|
||||
function SWEP:DoLHIK()
|
||||
if !IsValid(self:GetOwner()) then return end
|
||||
|
||||
local justhide = false
|
||||
local lhik_model = nil
|
||||
local lhik_anim_model = nil
|
||||
local hide_component = false
|
||||
local delta = 1
|
||||
|
||||
local vm = self:GetOwner():GetViewModel()
|
||||
|
||||
if !ArcCW.ConVars["reloadincust"]:GetBool() and !self.NoHideLeftHandInCustomization and !self:GetBuff_Override("Override_NoHideLeftHandInCustomization") then
|
||||
if self:GetState() == ArcCW.STATE_CUSTOMIZE then
|
||||
self.Customize_Hide = math.Approach(self.Customize_Hide, 1, FrameTime() / 0.25)
|
||||
else
|
||||
self.Customize_Hide = math.Approach(self.Customize_Hide, 0, FrameTime() / 0.25)
|
||||
end
|
||||
end
|
||||
|
||||
for i, k in pairs(self.Attachments) do
|
||||
if !k.Installed then continue end
|
||||
-- local atttbl = ArcCW.AttachmentTable[k.Installed]
|
||||
|
||||
-- if atttbl.LHIKHide then
|
||||
if self:GetBuff_Stat("LHIKHide", i) then
|
||||
justhide = true
|
||||
end
|
||||
|
||||
if !k.VElement then continue end
|
||||
|
||||
-- if atttbl.LHIK then
|
||||
if self:GetBuff_Stat("LHIK", i) then
|
||||
lhik_model = k.VElement.Model
|
||||
if k.GodDriver then
|
||||
lhik_anim_model = k.GodDriver.Model
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if self.LHIKTimeline then
|
||||
local tl = self.LHIKTimeline
|
||||
|
||||
local stage, next_stage, next_stage_index
|
||||
|
||||
for i, k in pairs(tl) do
|
||||
if !k or !k.t then continue end
|
||||
if k.t + self.LHIKStartTime > UnPredictedCurTime() then
|
||||
next_stage_index = i
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if next_stage_index then
|
||||
if next_stage_index == 1 then
|
||||
-- we are on the first stage.
|
||||
stage = {t = 0, lhik = 0}
|
||||
next_stage = self.LHIKTimeline[next_stage_index]
|
||||
else
|
||||
stage = self.LHIKTimeline[next_stage_index - 1]
|
||||
next_stage = self.LHIKTimeline[next_stage_index]
|
||||
end
|
||||
else
|
||||
stage = self.LHIKTimeline[#self.LHIKTimeline]
|
||||
next_stage = {t = self.LHIKEndTime, lhik = self.LHIKTimeline[#self.LHIKTimeline].lhik}
|
||||
end
|
||||
|
||||
local local_time = UnPredictedCurTime() - self.LHIKStartTime
|
||||
|
||||
local delta_time = next_stage.t - stage.t
|
||||
delta_time = (local_time - stage.t) / delta_time
|
||||
|
||||
delta = qerp(delta_time, stage.lhik, next_stage.lhik)
|
||||
|
||||
if lhik_model and IsValid(lhik_model) then
|
||||
local key
|
||||
|
||||
if stage.lhik > next_stage.lhik then
|
||||
key = "in"
|
||||
elseif next_stage.lhik > stage.lhik then
|
||||
key = "out"
|
||||
end
|
||||
|
||||
if key then
|
||||
local tranim = self:GetBuff_Hook("Hook_LHIK_TranslateAnimation", key)
|
||||
|
||||
key = tranim or key
|
||||
|
||||
local seq = lhik_model:LookupSequence(key)
|
||||
|
||||
if seq and seq > 0 then
|
||||
lhik_model:SetSequence(seq)
|
||||
lhik_model:SetCycle(delta)
|
||||
if lhik_anim_model then
|
||||
lhik_anim_model:SetSequence(seq)
|
||||
lhik_anim_model:SetCycle(delta)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- if tl[4] <= UnPredictedCurTime() then
|
||||
-- -- it's over
|
||||
-- delta = 1
|
||||
-- elseif tl[3] <= UnPredictedCurTime() then
|
||||
-- -- transition back to 1
|
||||
-- delta = (UnPredictedCurTime() - tl[3]) / (tl[4] - tl[3])
|
||||
-- delta = qerp(delta, 0, 1)
|
||||
|
||||
-- if lhik_model and IsValid(lhik_model) then
|
||||
-- local key = "out"
|
||||
|
||||
-- local tranim = self:GetBuff_Hook("Hook_LHIK_TranslateAnimation", key)
|
||||
|
||||
-- key = tranim or key
|
||||
|
||||
-- local seq = lhik_model:LookupSequence(key)
|
||||
|
||||
-- if seq and seq > 0 then
|
||||
-- lhik_model:SetSequence(seq)
|
||||
-- lhik_model:SetCycle(delta)
|
||||
-- end
|
||||
-- end
|
||||
-- elseif tl[2] <= UnPredictedCurTime() then
|
||||
-- -- hold 0
|
||||
-- delta = 0
|
||||
-- elseif tl[1] <= UnPredictedCurTime() then
|
||||
-- -- transition to 0
|
||||
-- delta = (UnPredictedCurTime() - tl[1]) / (tl[2] - tl[1])
|
||||
-- delta = qerp(delta, 1, 0)
|
||||
|
||||
-- if lhik_model and IsValid(lhik_model) then
|
||||
-- local key = "in"
|
||||
|
||||
-- local tranim = self:GetBuff_Hook("Hook_LHIK_TranslateAnimation", key)
|
||||
|
||||
-- key = tranim or key
|
||||
|
||||
-- local seq = lhik_model:LookupSequence(key)
|
||||
|
||||
-- if seq and seq > 0 then
|
||||
-- lhik_model:SetSequence(seq)
|
||||
-- lhik_model:SetCycle(delta)
|
||||
-- end
|
||||
-- end
|
||||
else
|
||||
-- hasn't started yet
|
||||
delta = 1
|
||||
end
|
||||
|
||||
if delta == 1 and self.Customize_Hide > 0 then
|
||||
if !lhik_model or !IsValid(lhik_model) then
|
||||
justhide = true
|
||||
delta = math.min(self.Customize_Hide, delta)
|
||||
else
|
||||
hide_component = true
|
||||
end
|
||||
end
|
||||
|
||||
if justhide then
|
||||
for _, bone in pairs(ArcCW.LHIKBones) do
|
||||
local vmbone = vm:LookupBone(bone)
|
||||
|
||||
if !vmbone then continue end -- Happens when spectating someone prolly
|
||||
|
||||
local vmtransform = vm:GetBoneMatrix(vmbone)
|
||||
|
||||
if !vmtransform then continue end -- something very bad has happened
|
||||
|
||||
local vm_pos = vmtransform:GetTranslation()
|
||||
local vm_ang = vmtransform:GetAngles()
|
||||
|
||||
local newtransform = Matrix()
|
||||
|
||||
newtransform:SetTranslation(LerpVector(delta, vm_pos, vm_pos - (EyeAngles():Up() * 12) - (EyeAngles():Forward() * 12) - (EyeAngles():Right() * 4)))
|
||||
newtransform:SetAngles(vm_ang)
|
||||
|
||||
vm:SetBoneMatrix(vmbone, newtransform)
|
||||
end
|
||||
end
|
||||
|
||||
if !lhik_model or !IsValid(lhik_model) then return end
|
||||
|
||||
lhik_model:SetupBones()
|
||||
|
||||
if justhide then return end
|
||||
|
||||
local cyc = (UnPredictedCurTime() - self.LHIKAnimationStart) / self.LHIKAnimationTime
|
||||
|
||||
if self.LHIKAnimation and cyc < 1 then
|
||||
lhik_model:SetSequence(self.LHIKAnimation)
|
||||
lhik_model:SetCycle(cyc)
|
||||
if IsValid(lhik_anim_model) then
|
||||
lhik_anim_model:SetSequence(self.LHIKAnimation)
|
||||
lhik_anim_model:SetCycle(cyc)
|
||||
end
|
||||
else
|
||||
local key = "idle"
|
||||
|
||||
local tranim = self:GetBuff_Hook("Hook_LHIK_TranslateAnimation", key)
|
||||
|
||||
key = tranim or key
|
||||
|
||||
if key and key != "DoNotPlayIdle" then
|
||||
self:DoLHIKAnimation(key, -1)
|
||||
end
|
||||
|
||||
self.LHIKAnimation_IsIdle = true
|
||||
end
|
||||
|
||||
local cf_deltapos = Vector(0, 0, 0)
|
||||
local cf = 0
|
||||
|
||||
|
||||
for _, bone in pairs(ArcCW.LHIKBones) do
|
||||
local vmbone = vm:LookupBone(bone)
|
||||
local lhikbone = lhik_model:LookupBone(bone)
|
||||
|
||||
if !vmbone then continue end
|
||||
if !lhikbone then continue end
|
||||
|
||||
local vmtransform = vm:GetBoneMatrix(vmbone)
|
||||
local lhiktransform = lhik_model:GetBoneMatrix(lhikbone)
|
||||
|
||||
if !vmtransform then continue end
|
||||
if !lhiktransform then continue end
|
||||
|
||||
local vm_pos = vmtransform:GetTranslation()
|
||||
local vm_ang = vmtransform:GetAngles()
|
||||
local lhik_pos = lhiktransform:GetTranslation()
|
||||
local lhik_ang = lhiktransform:GetAngles()
|
||||
|
||||
local newtransform = Matrix()
|
||||
|
||||
newtransform:SetTranslation(LerpVector(delta, vm_pos, lhik_pos))
|
||||
newtransform:SetAngles(LerpAngle(delta, vm_ang, lhik_ang))
|
||||
|
||||
if !self:GetBuff_Override("LHIK_GunDriver") and self.LHIKDelta[lhikbone] and self.LHIKAnimation and cyc < 1 then
|
||||
local deltapos = lhik_model:WorldToLocal(lhik_pos) - self.LHIKDelta[lhikbone]
|
||||
|
||||
if !deltapos:IsZero() then
|
||||
cf_deltapos = cf_deltapos + deltapos
|
||||
cf = cf + 1
|
||||
end
|
||||
end
|
||||
|
||||
self.LHIKDelta[lhikbone] = lhik_model:WorldToLocal(lhik_pos)
|
||||
|
||||
if hide_component then
|
||||
local new_pos = newtransform:GetTranslation()
|
||||
newtransform:SetTranslation(LerpVector(self.Customize_Hide, new_pos, new_pos - (EyeAngles():Up() * 12) - (EyeAngles():Forward() * 12) - (EyeAngles():Right() * 4)))
|
||||
end
|
||||
|
||||
local matrix = Matrix(newtransform)
|
||||
|
||||
vm:SetBoneMatrix(vmbone, matrix)
|
||||
|
||||
-- local vm_pos, vm_ang = vm:GetBonePosition(vmbone)
|
||||
-- local lhik_pos, lhik_ang = lhik_model:GetBonePosition(lhikbone)
|
||||
|
||||
-- local pos = LerpVector(delta, vm_pos, lhik_pos)
|
||||
-- local ang = LerpAngle(delta, vm_ang, lhik_ang)
|
||||
|
||||
-- vm:SetBonePosition(vmbone, pos, ang)
|
||||
end
|
||||
|
||||
if !cf_deltapos:IsZero() and cf > 0 and self:GetBuff_Override("LHIK_Animation") then
|
||||
local new = Vector(0, 0, 0)
|
||||
local viewmult = self:GetBuff_Override("LHIK_MovementMult") or 1
|
||||
|
||||
new[1] = cf_deltapos[2] * viewmult
|
||||
new[2] = cf_deltapos[1] * viewmult
|
||||
new[3] = cf_deltapos[3] * viewmult
|
||||
|
||||
self.ViewModel_Hit = LerpVector(0.25, self.ViewModel_Hit, new / cf):GetNormalized()
|
||||
end
|
||||
end
|
||||
373
lua/weapons/arccw_base/cl_light.lua
Normal file
373
lua/weapons/arccw_base/cl_light.lua
Normal file
@@ -0,0 +1,373 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
SWEP.Flashlights = {} -- tracks projectedlights
|
||||
-- {{att = int, light = ProjectedTexture}}
|
||||
SWEP.CheapFlashlights = {} -- tracks cheap flashlight models + lights
|
||||
-- {{att = int, dlight = DynamicLight, vlight = ClientsideModel}}
|
||||
|
||||
function SWEP:GetHasFlashlights()
|
||||
for i, k in pairs(self.Attachments) do
|
||||
if !k.Installed then continue end
|
||||
if self:GetBuff_Stat("Flashlight", i) != nil then return true end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function SWEP:CreateFlashlightsVM()
|
||||
self:KillFlashlights()
|
||||
self.Flashlights = {}
|
||||
|
||||
local total_lights = 0
|
||||
|
||||
for i, k in pairs(self.Attachments) do
|
||||
if !k.Installed then continue end
|
||||
if self:GetBuff_Stat("Flashlight", i) then
|
||||
local newlight = {
|
||||
att = i,
|
||||
light = ProjectedTexture(),
|
||||
bone = self:GetBuff_Stat("FlashlightBone", i) or "laser",
|
||||
col = self:GetBuff_Stat("FlashlightColor", i) or Color(255, 255, 255),
|
||||
br = self:GetBuff_Stat("FlashlightBrightness", i) or 2
|
||||
}
|
||||
total_lights = total_lights + 1
|
||||
|
||||
local l = newlight.light
|
||||
if !IsValid(l) then continue end
|
||||
|
||||
table.insert(self.Flashlights, newlight)
|
||||
|
||||
l:SetFOV(self:GetBuff_Stat("FlashlightFOV", i) or 50)
|
||||
|
||||
if self:GetBuff_Stat("FlashlightHFOV", i) then
|
||||
l:SetHorizontalFOV(self:GetBuff_Stat("FlashlightHFOV", i))
|
||||
end
|
||||
|
||||
if self:GetBuff_Stat("FlashlightVFOV", i) then
|
||||
l:SetVerticalFOV(self:GetBuff_Stat("FlashlightVFOV", i))
|
||||
end
|
||||
|
||||
l:SetFarZ(self:GetBuff_Stat("FlashlightFarZ", i) or 512)
|
||||
l:SetNearZ(self:GetBuff_Stat("FlashlightNearZ", i) or 4)
|
||||
|
||||
local atten = self:GetBuff_Stat("FlashlightAttenuationType", i) or ArcCW.FLASH_ATT_LINEAR
|
||||
|
||||
l:SetLinearAttenuation(0)
|
||||
l:SetConstantAttenuation(0)
|
||||
l:SetQuadraticAttenuation(0)
|
||||
|
||||
if atten == ArcCW.FLASH_ATT_CONSTANT then
|
||||
l:SetConstantAttenuation(100)
|
||||
elseif atten == ArcCW.FLASH_ATT_QUADRATIC then
|
||||
l:SetQuadraticAttenuation(100)
|
||||
else
|
||||
l:SetLinearAttenuation(100)
|
||||
end
|
||||
|
||||
l:SetColor(self:GetBuff_Stat("FlashlightColor", i) or Color(255, 255, 255))
|
||||
l:SetTexture(self:GetBuff_Stat("FlashlightTexture", i))
|
||||
l:SetBrightness(self:GetBuff_Stat("FlashlightBrightness", i))
|
||||
l:SetEnableShadows(true)
|
||||
l:Update()
|
||||
|
||||
local g_light = {
|
||||
Weapon = self,
|
||||
ProjectedTexture = l
|
||||
}
|
||||
|
||||
table.insert(ArcCW.FlashlightPile, g_light)
|
||||
end
|
||||
end
|
||||
|
||||
if total_lights > 2 then -- you are a madman
|
||||
for i, k in pairs(self.Flashlights) do
|
||||
if k.light:IsValid() then k.light:SetEnableShadows(false) end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- for world model flashlights we will use a cheap solution similar to what HL2 uses
|
||||
-- throw up a volumetric light model
|
||||
-- function SWEP:CreateFlashlightsWM()
|
||||
-- self:KillFlashlights()
|
||||
-- self.CheapFlashlights = {}
|
||||
-- for i, k in pairs(self.Attachments) do
|
||||
-- if !k.Installed then continue end
|
||||
-- local atttbl = ArcCW.AttachmentTable[k.Installed]
|
||||
|
||||
-- if atttbl.Flashlight then
|
||||
-- local newlight = {
|
||||
-- att = i,
|
||||
-- vlight = ClientsideModel(ArcCW.VolumetricLightModel),
|
||||
-- scale_x = 1,
|
||||
-- scale_y = 1,
|
||||
-- maxz = atttbl.FlashlightFarZ or 512,
|
||||
-- bone = atttbl.FlashlightBone or "laser",
|
||||
-- col = Color(255, 255, 255)
|
||||
-- }
|
||||
|
||||
-- local vl = newlight.vlight
|
||||
|
||||
-- if !IsValid(vl) then continue end
|
||||
|
||||
-- table.insert(self.CheapFlashlights, newlight)
|
||||
|
||||
-- local xfov = atttbl.FlashlightHFOV or atttbl.FlashlightFOV or 50
|
||||
-- local yfov = atttbl.FlashlightVFOV or atttbl.FlashlightFOV or 50
|
||||
|
||||
-- local target_x = 128 * (xfov / 90)
|
||||
-- local target_y = 128 * (yfov / 90)
|
||||
|
||||
-- local scale_x = target_x / ArcCW.VolumetricLightX
|
||||
-- local scale_y = target_y / ArcCW.VolumetricLightY
|
||||
|
||||
-- newlight.scale_x = scale_x
|
||||
-- newlight.scale_y = scale_y
|
||||
|
||||
-- vl:SetNoDraw(ArcCW.NoDraw)
|
||||
-- vl:DrawShadow(false)
|
||||
-- local col = atttbl.FlashlightColor or Color(255, 255, 255)
|
||||
-- col = Color(255, 0, 0)
|
||||
-- newlight.col = col
|
||||
-- -- vl:SetColor(col)
|
||||
|
||||
-- local g_light = {
|
||||
-- Model = vl,
|
||||
-- Weapon = self
|
||||
-- }
|
||||
|
||||
-- table.insert(ArcCW.CSModelPile, g_light)
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
|
||||
function SWEP:KillFlashlights()
|
||||
self:KillFlashlightsVM()
|
||||
-- self:KillFlashlightsWM()
|
||||
end
|
||||
|
||||
function SWEP:KillFlashlightsVM()
|
||||
if !self.Flashlights then return end
|
||||
|
||||
for i, k in pairs(self.Flashlights) do
|
||||
if k.light and k.light:IsValid() then
|
||||
k.light:Remove()
|
||||
end
|
||||
end
|
||||
|
||||
self.Flashlights = nil
|
||||
end
|
||||
|
||||
function SWEP:KillFlashlightsWM()
|
||||
-- if !self.CheapFlashlights then return end
|
||||
|
||||
-- for i, k in pairs(self.CheapFlashlights) do
|
||||
-- if k.vlight and k.vlight:IsValid() then
|
||||
-- k.vlight:Remove()
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- self.CheapFlashlights = nil
|
||||
end
|
||||
|
||||
-- given fov and distance solve apparent size
|
||||
local function solvetriangle(angle, dist)
|
||||
local a = angle / 2
|
||||
local b = dist
|
||||
return b * math.tan(a) * 2
|
||||
end
|
||||
|
||||
local flashlight_mat = Material("models/effects/vol_light002")
|
||||
-- local flashlight_mat = Material("effects/blueblacklargebeam")
|
||||
|
||||
function SWEP:DrawFlashlightsWM()
|
||||
-- if !self.CheapFlashlights then
|
||||
-- self:CreateFlashlightsWM()
|
||||
-- end
|
||||
|
||||
local owner = self:GetOwner()
|
||||
|
||||
for i, k in pairs(self.Attachments) do
|
||||
if !k.Installed then continue end
|
||||
local atttbl = ArcCW.AttachmentTable[k.Installed]
|
||||
|
||||
if !atttbl or !self:GetBuff_Stat("Flashlight", i) then continue end
|
||||
|
||||
local maxz = atttbl.FlashlightFarZ or 512
|
||||
local bone = atttbl.FlashlightBone or "laser"
|
||||
local col = atttbl.FlashlightColor or Color(255, 255, 255)
|
||||
|
||||
if !k.WElement then continue end
|
||||
local model = k.WElement.Model
|
||||
if !IsValid(model) then return end
|
||||
|
||||
local pos, ang, dir
|
||||
|
||||
if !model then
|
||||
pos = owner:EyePos()
|
||||
ang = owner:EyeAngles()
|
||||
dir = ang:Forward()
|
||||
else
|
||||
local att = model:LookupAttachment(bone or "laser")
|
||||
|
||||
att = att == 0 and model:LookupAttachment("muzzle") or att
|
||||
|
||||
if att == 0 then
|
||||
pos = model:GetPos()
|
||||
ang = IsValid(owner) and owner:EyeAngles() or model:GetAngles()
|
||||
dir = ang:Forward()
|
||||
dir_2 = ang:Up()
|
||||
else
|
||||
local attdata = model:GetAttachment(att)
|
||||
pos, ang = attdata.Pos, attdata.Ang
|
||||
dir = -ang:Right()
|
||||
dir_2 = ang:Up()
|
||||
end
|
||||
end
|
||||
|
||||
local maxs = Vector(2, 2, 2)
|
||||
local mins = -maxs
|
||||
|
||||
-- scale volumetric light
|
||||
local tr = util.TraceHull({
|
||||
start = pos,
|
||||
endpos = pos + (dir * maxz),
|
||||
mask = MASK_OPAQUE,
|
||||
mins = mins,
|
||||
maxs = maxs
|
||||
})
|
||||
|
||||
local z = (tr.HitPos - tr.StartPos):Length()
|
||||
-- local s_z = z / ArcCW.VolumetricLightZ
|
||||
|
||||
local xfov = atttbl.FlashlightHFOV or atttbl.FlashlightFOV or 50
|
||||
local yfov = atttbl.FlashlightVFOV or atttbl.FlashlightFOV or 50
|
||||
|
||||
-- local target_x = 128 * (xfov / 90)
|
||||
-- local target_y = 128 * (yfov / 90)
|
||||
|
||||
local target_x = solvetriangle(xfov, z)
|
||||
local target_y = target_x
|
||||
|
||||
if xfov != yfov then
|
||||
target_y = solvetriangle(yfov, z)
|
||||
end
|
||||
|
||||
local vs = EyeAngles():Up()
|
||||
|
||||
local c1 = pos + vs
|
||||
local c4 = pos - vs
|
||||
local c2 = tr.HitPos + (vs * target_y * 0.75)
|
||||
local c3 = tr.HitPos - (vs * target_y * 0.75)
|
||||
|
||||
render.SetMaterial(flashlight_mat)
|
||||
render.DrawQuad(c1,c2,c3,c4, col)
|
||||
|
||||
-- local scale = Matrix()
|
||||
-- scale:Scale(Vector(s_x, s_y, s_z))
|
||||
|
||||
-- k.vlight:SetPos(pos)
|
||||
-- k.vlight:SetAngles(ang + Angle(0, 0, 90))
|
||||
-- k.vlight:EnableMatrix("RenderMultiply", scale)
|
||||
-- k.vlight:SetColor(Color(255, 0, 0, 255))
|
||||
-- k.vlight:SetRenderMode(RENDERMODE_NORMAL)
|
||||
-- k.vlight:SetKeyValue("RenderFX", kRenderFxNone)
|
||||
-- k.vlight:DrawModel()
|
||||
-- place dynamic light to make some light appear
|
||||
|
||||
local dl = DynamicLight(self:EntIndex())
|
||||
|
||||
local delta = (z / maxz)
|
||||
delta = math.Clamp(delta, 0, 1)
|
||||
|
||||
if dl then
|
||||
dl.pos = tr.HitPos
|
||||
dl.r = col.r
|
||||
dl.g = col.g
|
||||
dl.b = col.b
|
||||
dl.brightness = Lerp(delta, atttbl.FlashlightBrightness or 2, 0)
|
||||
-- print(z / maxz)
|
||||
dl.Decay = 1000 / 1
|
||||
dl.dietime = CurTime() + 0.1
|
||||
dl.size = xfov * 5
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:DrawFlashlightsVM()
|
||||
if !self.Flashlights then
|
||||
self:CreateFlashlightsVM()
|
||||
end
|
||||
|
||||
local owner = self:GetOwner()
|
||||
|
||||
for i, k in pairs(self.Flashlights) do
|
||||
local model = (self.Attachments[k.att].VElement or {}).Model
|
||||
|
||||
local pos, ang
|
||||
|
||||
if !model then
|
||||
pos = owner:EyePos()
|
||||
ang = owner:EyeAngles()
|
||||
else
|
||||
local att = model:LookupAttachment(k.bone or "laser")
|
||||
|
||||
att = att == 0 and model:LookupAttachment("muzzle") or att
|
||||
|
||||
if att == 0 then
|
||||
pos = model:GetPos()
|
||||
ang = owner:EyeAngles()
|
||||
else
|
||||
local attdata = model:GetAttachment(att)
|
||||
pos, ang = attdata.Pos, attdata.Ang
|
||||
end
|
||||
end
|
||||
|
||||
local tr = util.TraceLine({
|
||||
start = owner:EyePos(),
|
||||
endpos = owner:EyePos() - ang:Right() * 128,
|
||||
mask = MASK_OPAQUE,
|
||||
filter = LocalPlayer(),
|
||||
})
|
||||
if tr.Fraction < 1 then -- We need to push the flashlight back
|
||||
local tr2 = util.TraceLine({
|
||||
start = owner:EyePos(),
|
||||
endpos = owner:EyePos() + ang:Right() * 128,
|
||||
mask = MASK_OPAQUE,
|
||||
filter = LocalPlayer(),
|
||||
})
|
||||
-- push it as back as the area behind us allows
|
||||
pos = pos + ang:Right() * 128 * math.min(1 - tr.Fraction, tr2.Fraction)
|
||||
end
|
||||
|
||||
ang:RotateAroundAxis(ang:Up(), 90)
|
||||
|
||||
k.light:SetPos(pos)
|
||||
k.light:SetAngles(ang)
|
||||
k.light:Update()
|
||||
|
||||
-- local col = k.col
|
||||
|
||||
-- local dl = DynamicLight(self:EntIndex())
|
||||
|
||||
-- if dl then
|
||||
-- dl.pos = pos
|
||||
-- dl.r = col.r
|
||||
-- dl.g = col.g
|
||||
-- dl.b = col.b
|
||||
-- dl.brightness = k.br or 2
|
||||
-- -- print(z / maxz)
|
||||
-- dl.Decay = 1000 / 0.1
|
||||
-- dl.dietime = CurTime() + 0.1
|
||||
-- dl.size = (k.br or 2) * 64
|
||||
-- end
|
||||
end
|
||||
end
|
||||
468
lua/weapons/arccw_base/cl_presets.lua
Normal file
468
lua/weapons/arccw_base/cl_presets.lua
Normal file
@@ -0,0 +1,468 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
-- atts are comma separated
|
||||
-- optic_mrs,,,perk_quickdraw,ammo_match
|
||||
|
||||
|
||||
|
||||
local function ScreenScaleMulti(input)
|
||||
return ScreenScale(input) * ArcCW.ConVars["hud_size"]:GetFloat()
|
||||
end
|
||||
|
||||
function SWEP:GetPresetBase()
|
||||
return self.PresetBase or self:GetClass()
|
||||
end
|
||||
|
||||
function SWEP:GetPresets()
|
||||
local path = ArcCW.PresetPath .. self:GetPresetBase() .. "/*.txt"
|
||||
|
||||
local files = file.Find(path, "DATA")
|
||||
|
||||
files = table.Add(files, file.Find(ArcCW.PresetPath .. self:GetPresetBase() .. "/*.json", "DATA"))
|
||||
|
||||
return files
|
||||
end
|
||||
|
||||
function SWEP:LoadPreset(presetname)
|
||||
presetname = presetname or "autosave"
|
||||
if presetname == "autosave" then
|
||||
if self:GetNWBool("ArcCW_DisableAutosave", false) then return end
|
||||
if !ArcCW.ConVars["autosave"]:GetBool() then return end
|
||||
end
|
||||
|
||||
if presetname != "autosave" then
|
||||
surface.PlaySound("weapons/arccw/install.wav")
|
||||
end
|
||||
|
||||
-- ???
|
||||
self.Attachments.BaseClass = nil
|
||||
|
||||
local presetTbl
|
||||
|
||||
|
||||
-- New behavior
|
||||
local filename = ArcCW.PresetPath .. self:GetPresetBase() .. "/" .. presetname .. ".json"
|
||||
if file.Exists(filename, "DATA") then
|
||||
presetTbl = util.JSONToTable(file.Read(filename))
|
||||
if presetTbl and presetTbl != {} then
|
||||
for i = 1, table.Count(self.Attachments) do
|
||||
local ok = true
|
||||
|
||||
if !presetTbl[i] or !ArcCW.AttachmentTable[presetTbl[i].Installed or ""] then
|
||||
ok = false
|
||||
end
|
||||
|
||||
if !ok then
|
||||
presetTbl[i] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Legacy behavior
|
||||
filename = ArcCW.PresetPath .. self:GetPresetBase() .. "/" .. presetname .. ".txt"
|
||||
if presetTbl == nil and file.Exists(filename, "DATA") then
|
||||
local f = file.Open(filename, "r", "DATA")
|
||||
if !f then return end
|
||||
|
||||
presetTbl = {}
|
||||
|
||||
for i = 1, table.Count(self.Attachments) do
|
||||
local line = f:ReadLine()
|
||||
if !line then continue end
|
||||
local split = string.Split(string.Trim(line, "\n"), ",")
|
||||
if !ArcCW.AttachmentTable[split[1]] then continue end
|
||||
presetTbl[i] = {
|
||||
Installed = split[1],
|
||||
SlidePos = split[2] and tonumber(split[2]),
|
||||
SightMagnifications = split[3] and tonumber(split[3]),
|
||||
ToggleNum = nil, -- not implemented in legacy preset
|
||||
}
|
||||
end
|
||||
f:Close()
|
||||
end
|
||||
|
||||
if !presetTbl then return end
|
||||
|
||||
net.Start("arccw_applypreset")
|
||||
net.WriteEntity(self)
|
||||
for k, v in pairs(self.Attachments) do
|
||||
local att = (presetTbl[k] or {}).Installed
|
||||
|
||||
if !att or !ArcCW.AttachmentTable[att] then
|
||||
net.WriteUInt(0, ArcCW.GetBitNecessity())
|
||||
continue
|
||||
end
|
||||
|
||||
net.WriteUInt(ArcCW.AttachmentTable[att].ID, ArcCW.GetBitNecessity())
|
||||
|
||||
net.WriteBool(presetTbl[k].SlidePos)
|
||||
if presetTbl[k].SlidePos then
|
||||
net.WriteFloat(presetTbl[k].SlidePos)
|
||||
end
|
||||
|
||||
if ArcCW.AttachmentTable[att].ToggleStats != nil then
|
||||
net.WriteUInt(presetTbl[k].ToggleNum or 1, 8)
|
||||
end
|
||||
v.ToggleNum = presetTbl[k].ToggleNum or 1
|
||||
|
||||
-- not networked
|
||||
self.SightMagnifications[k] = presetTbl[k].SightMagnifications
|
||||
end
|
||||
net.SendToServer()
|
||||
|
||||
--[[]
|
||||
for i = 1, table.Count(self.Attachments) do
|
||||
local att = presetTbl[i]
|
||||
if !att then continue end
|
||||
|
||||
if ArcCW:PlayerGetAtts(self:GetOwner(), att) == 0 then continue end
|
||||
if !self.Attachments[i] then continue end
|
||||
|
||||
-- detect commas
|
||||
-- no commas = do nothing
|
||||
-- commas: If exactly two commas are detected
|
||||
-- try to parse them as slidepos, magnification
|
||||
|
||||
local split = string.Split(att, ",")
|
||||
local sc = table.Count(split)
|
||||
|
||||
local slidepos = 0.5
|
||||
local mag = -1
|
||||
|
||||
if sc == 3 then
|
||||
att = split[1]
|
||||
slidepos = tonumber(split[2])
|
||||
mag = tonumber(split[3])
|
||||
end
|
||||
|
||||
if att == self.Attachments[i].Installed then continue end
|
||||
|
||||
self:Detach(i, true, true)
|
||||
|
||||
if !ArcCW.AttachmentTable[att] then continue end
|
||||
|
||||
self:Attach(i, att, true, true)
|
||||
|
||||
if slidepos != 0.5 then
|
||||
self.Attachments[i].SlidePos = slidepos
|
||||
end
|
||||
|
||||
if mag != -1 then
|
||||
self.SightMagnifications[i] = mag
|
||||
end
|
||||
end
|
||||
|
||||
self:SendAllDetails()
|
||||
|
||||
self:SavePreset()
|
||||
]]
|
||||
end
|
||||
|
||||
function SWEP:SavePreset(presetname)
|
||||
presetname = presetname or "autosave"
|
||||
if presetname == "autosave" and !ArcCW.ConVars["attinv_free"]:GetBool() then return end
|
||||
|
||||
local presetTbl = {}
|
||||
for i, k in pairs(self.Attachments) do
|
||||
if k.Installed then
|
||||
presetTbl[i] = {
|
||||
Installed = k.Installed,
|
||||
SlidePos = k.SlidePos,
|
||||
SightMagnifications = self.SightMagnifications[i],
|
||||
ToggleNum = k.ToggleNum
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
filename = ArcCW.PresetPath .. self:GetPresetBase() .. "/" .. presetname .. ".json"
|
||||
file.CreateDir(ArcCW.PresetPath .. self:GetPresetBase())
|
||||
file.Write(filename, util.TableToJSON(presetTbl))
|
||||
|
||||
local legacy_filename = ArcCW.PresetPath .. self:GetPresetBase() .. "/" .. presetname .. ".txt"
|
||||
if file.Exists(legacy_filename, "DATA") then
|
||||
file.Delete(legacy_filename)
|
||||
end
|
||||
|
||||
-- Legacy presets
|
||||
--[[]
|
||||
local str = ""
|
||||
for i, k in pairs(self.Attachments) do
|
||||
if k.Installed then
|
||||
str = str .. k.Installed
|
||||
if k.SlidePos or self.SightMagnifications[i] then
|
||||
str = str .. "," .. tostring(k.SlidePos or 0.5) .. "," .. tostring(self.SightMagnifications[i] or -1)
|
||||
end
|
||||
end
|
||||
|
||||
str = str .. "\n"
|
||||
end
|
||||
|
||||
filename = ArcCW.PresetPath .. self:GetPresetBase() .. "/" .. filename .. ".txt"
|
||||
|
||||
file.CreateDir(ArcCW.PresetPath .. self:GetPresetBase())
|
||||
file.Write(filename, str)
|
||||
]]
|
||||
end
|
||||
|
||||
function SWEP:CreatePresetSave()
|
||||
if !IsValid(ArcCW.InvHUD) then return end
|
||||
local bg = vgui.Create("DFrame", ArcCW.InvHUD)
|
||||
bg:SetPos(0, 0)
|
||||
bg:SetSize(ScrW(), ScrH())
|
||||
bg:SetText("")
|
||||
bg:SetTitle("")
|
||||
bg:SetDraggable(false)
|
||||
bg:ShowCloseButton(false)
|
||||
bg.Paint = function(span)
|
||||
surface.SetDrawColor(0, 0, 0, 200)
|
||||
surface.DrawRect(0, 0, ScrW(), ScrH())
|
||||
end
|
||||
bg:MakePopup()
|
||||
|
||||
local text = vgui.Create("DTextEntry", bg)
|
||||
text:SetSize(ScreenScaleMulti(256), ScreenScaleMulti(26))
|
||||
text:Center()
|
||||
text:RequestFocus()
|
||||
text:SetFont("ArcCW_24")
|
||||
text:SetText(self.LastPresetName or "")
|
||||
|
||||
local accept = vgui.Create("DButton", bg)
|
||||
accept:SetSize((ScreenScaleMulti(256) - ScreenScaleMulti(2)) / 2, ScreenScaleMulti(14))
|
||||
accept:SetText("")
|
||||
accept:SetPos((ScrW() - ScreenScaleMulti(256)) / 2, ((ScrH() - ScreenScaleMulti(14)) / 2) + ScreenScaleMulti(26) + ScreenScaleMulti(2))
|
||||
|
||||
accept.OnMousePressed = function(spaa, kc)
|
||||
local txt = text:GetText()
|
||||
txt = string.sub(txt, 0, 36)
|
||||
self.LastPresetName = txt
|
||||
self:SavePreset(txt)
|
||||
bg:Close()
|
||||
bg:Remove()
|
||||
|
||||
ArcCW.InvHUD_FormPresets()
|
||||
end
|
||||
|
||||
accept.Paint = function(spaa, w, h)
|
||||
if !self:IsValid() then return end
|
||||
local Bfg_col = Color(255, 255, 255, 255)
|
||||
local Bbg_col = Color(0, 0, 0, 100)
|
||||
|
||||
if spaa:IsHovered() then
|
||||
Bbg_col = Color(255, 255, 255, 100)
|
||||
Bfg_col = Color(0, 0, 0, 255)
|
||||
end
|
||||
|
||||
surface.SetDrawColor(Bbg_col)
|
||||
surface.DrawRect(0, 0, w, h)
|
||||
|
||||
local txt = "Save"
|
||||
|
||||
surface.SetTextColor(Bfg_col)
|
||||
surface.SetTextPos(ScreenScaleMulti(2), ScreenScaleMulti(1))
|
||||
surface.SetFont("ArcCW_12")
|
||||
surface.DrawText(txt)
|
||||
end
|
||||
|
||||
local cancel = vgui.Create("DButton", bg)
|
||||
cancel:SetSize((ScreenScaleMulti(256) - ScreenScaleMulti(2)) / 2, ScreenScaleMulti(14))
|
||||
cancel:SetText("")
|
||||
cancel:SetPos(((ScrW() - ScreenScaleMulti(256)) / 2) + ScreenScaleMulti(128 + 1), ((ScrH() - ScreenScaleMulti(14)) / 2) + ScreenScaleMulti(26) + ScreenScaleMulti(2))
|
||||
|
||||
cancel.OnMousePressed = function(spaa, kc)
|
||||
bg:Close()
|
||||
bg:Remove()
|
||||
end
|
||||
|
||||
cancel.Paint = function(spaa, w, h)
|
||||
if !self:IsValid() then return end
|
||||
local Bfg_col = Color(255, 255, 255, 255)
|
||||
local Bbg_col = Color(0, 0, 0, 100)
|
||||
|
||||
if spaa:IsHovered() then
|
||||
Bbg_col = Color(255, 255, 255, 100)
|
||||
Bfg_col = Color(0, 0, 0, 255)
|
||||
end
|
||||
|
||||
surface.SetDrawColor(Bbg_col)
|
||||
surface.DrawRect(0, 0, w, h)
|
||||
|
||||
local txt = "Cancel"
|
||||
|
||||
surface.SetTextColor(Bfg_col)
|
||||
surface.SetTextPos(ScreenScaleMulti(2), ScreenScaleMulti(1))
|
||||
surface.SetFont("ArcCW_12")
|
||||
surface.DrawText(txt)
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:CreatePresetMenu()
|
||||
if !IsValid(ArcCW.InvHUD) then return end
|
||||
|
||||
if !IsValid(ArcCW.InvHUD) then return end
|
||||
local bg = vgui.Create("DFrame", ArcCW.InvHUD)
|
||||
bg:SetPos(0, 0)
|
||||
bg:SetSize(ScrW(), ScrH())
|
||||
bg:SetText("")
|
||||
bg:SetTitle("")
|
||||
bg:SetDraggable(false)
|
||||
bg:ShowCloseButton(false)
|
||||
bg.Paint = function(span)
|
||||
surface.SetDrawColor(0, 0, 0, 200)
|
||||
surface.DrawRect(0, 0, ScrW(), ScrH())
|
||||
end
|
||||
|
||||
local cancel = vgui.Create("DButton", bg)
|
||||
cancel:SetSize(ScreenScaleMulti(128), ScreenScaleMulti(14))
|
||||
cancel:SetText("")
|
||||
cancel:SetPos((ScrW() - ScreenScaleMulti(128)) / 2, ScrH() - ScreenScaleMulti(32))
|
||||
|
||||
cancel.OnMousePressed = function(spaa, kc)
|
||||
bg:Close()
|
||||
bg:Remove()
|
||||
end
|
||||
|
||||
cancel.Paint = function(spaa, w, h)
|
||||
if !self:IsValid() then return end
|
||||
local Bfg_col = Color(255, 255, 255, 255)
|
||||
local Bbg_col = Color(0, 0, 0, 100)
|
||||
|
||||
if spaa:IsHovered() then
|
||||
Bbg_col = Color(255, 255, 255, 100)
|
||||
Bfg_col = Color(0, 0, 0, 255)
|
||||
end
|
||||
|
||||
surface.SetDrawColor(Bbg_col)
|
||||
surface.DrawRect(0, 0, w, h)
|
||||
|
||||
local txt = "Cancel"
|
||||
|
||||
surface.SetTextColor(Bfg_col)
|
||||
surface.SetTextPos(ScreenScaleMulti(2), ScreenScaleMulti(1))
|
||||
surface.SetFont("ArcCW_12")
|
||||
surface.DrawText(txt)
|
||||
end
|
||||
|
||||
local presetsmenu = vgui.Create("DScrollPanel", bg)
|
||||
presetsmenu:SetText("")
|
||||
presetsmenu:SetSize(ScreenScaleMulti(256), ScrH() - ScreenScaleMulti(64))
|
||||
presetsmenu:SetPos((ScrW() - ScreenScaleMulti(256)) / 2, ScreenScaleMulti(8))
|
||||
presetsmenu.Paint = function(span, w, h)
|
||||
end
|
||||
|
||||
local sbar = presetsmenu:GetVBar()
|
||||
sbar.Paint = function() end
|
||||
|
||||
sbar.btnUp.Paint = function(span, w, h)
|
||||
end
|
||||
|
||||
sbar.btnDown.Paint = function(span, w, h)
|
||||
end
|
||||
|
||||
sbar.btnGrip.Paint = function(span, w, h)
|
||||
surface.SetDrawColor(255, 255, 255, 255)
|
||||
surface.DrawRect(0, 0, w, h)
|
||||
end
|
||||
|
||||
local c = 0
|
||||
|
||||
for i, k in pairs(self:GetPresets()) do
|
||||
if string.StripExtension(k) == "autosave" then continue end
|
||||
local preset = vgui.Create("DButton", presetsmenu)
|
||||
preset:SetSize(ScreenScaleMulti(254), ScreenScaleMulti(14))
|
||||
preset:SetText("")
|
||||
preset:Dock(TOP)
|
||||
preset:DockMargin( 0, 0, 0, ScreenScaleMulti(2) )
|
||||
|
||||
preset.PresetName = string.StripExtension(k) --string.sub(k, 1, -5)
|
||||
preset.PresetFile = k
|
||||
|
||||
preset.OnMousePressed = function(spaa, kc)
|
||||
self.LastPresetName = spaa.PresetName
|
||||
self:LoadPreset(spaa.PresetName)
|
||||
bg:Close()
|
||||
bg:Remove()
|
||||
end
|
||||
|
||||
preset.Paint = function(spaa, w, h)
|
||||
if !self:IsValid() then return end
|
||||
local Bfg_col = Color(255, 255, 255, 255)
|
||||
local Bbg_col = Color(0, 0, 0, 100)
|
||||
|
||||
if spaa:IsHovered() then
|
||||
Bbg_col = Color(255, 255, 255, 100)
|
||||
Bfg_col = Color(0, 0, 0, 255)
|
||||
end
|
||||
|
||||
surface.SetDrawColor(Bbg_col)
|
||||
surface.DrawRect(0, 0, w, h)
|
||||
|
||||
surface.SetTextColor(Bfg_col)
|
||||
surface.SetTextPos(ScreenScaleMulti(2), ScreenScaleMulti(1))
|
||||
surface.SetFont("ArcCW_12")
|
||||
surface.DrawText(string.upper(spaa.PresetName))
|
||||
end
|
||||
|
||||
local close = vgui.Create("DButton", preset)
|
||||
close:SetSize(ScreenScaleMulti(16), ScreenScaleMulti(16))
|
||||
close:SetText("")
|
||||
close:Dock(RIGHT)
|
||||
|
||||
close.OnMousePressed = function(spaa, kc)
|
||||
local filename = spaa.PresetFile
|
||||
file.Delete(filename)
|
||||
preset:Remove()
|
||||
end
|
||||
|
||||
close.Paint = function(spaa, w, h)
|
||||
if !self:IsValid() or preset:IsHovered() then return end
|
||||
local Bfg_col = Color(255, 255, 255, 255)
|
||||
local Bbg_col = Color(0, 0, 0, 100)
|
||||
|
||||
if spaa:IsHovered() then
|
||||
Bbg_col = Color(255, 255, 255, 100)
|
||||
Bfg_col = Color(0, 0, 0, 255)
|
||||
end
|
||||
|
||||
surface.SetDrawColor(Bbg_col)
|
||||
surface.DrawRect(0, 0, w, h)
|
||||
|
||||
local w_x, h_x = surface.GetTextSize("×")
|
||||
surface.SetTextColor(Bfg_col)
|
||||
surface.SetTextPos((ScreenScaleMulti(16) - w_x) / 2, (ScreenScaleMulti(16) - h_x) / 2)
|
||||
surface.SetFont("ArcCW_12")
|
||||
surface.DrawText("×")
|
||||
end
|
||||
c = c + 1
|
||||
end
|
||||
|
||||
if c == 0 then
|
||||
local label = vgui.Create("DLabel", presetsmenu)
|
||||
label:SetSize(ScreenScaleMulti(254), ScreenScaleMulti(14))
|
||||
label:SetText("")
|
||||
label:Dock(TOP)
|
||||
label:DockMargin( 0, 0, 0, ScreenScaleMulti(2) )
|
||||
|
||||
label.Paint = function(spaa, w, h)
|
||||
local Bfg_col = Color(255, 255, 255, 255)
|
||||
|
||||
local txt = "No presets found! Go make some!"
|
||||
|
||||
surface.SetTextColor(Bfg_col)
|
||||
surface.SetTextPos(ScreenScaleMulti(2), ScreenScaleMulti(1))
|
||||
surface.SetFont("ArcCW_12")
|
||||
surface.DrawText(txt)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:ClosePresetMenu()
|
||||
end
|
||||
266
lua/weapons/arccw_base/cl_scope.lua
Normal file
266
lua/weapons/arccw_base/cl_scope.lua
Normal file
@@ -0,0 +1,266 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
function SWEP:AdjustMouseSensitivity()
|
||||
if self:GetState() != ArcCW.STATE_SIGHTS then return end
|
||||
|
||||
local threshold = ArcCW.ConVars["adjustsensthreshold"]:GetFloat()
|
||||
|
||||
local irons = self:GetActiveSights() or {}
|
||||
|
||||
local tmag = ((irons.Magnification or 1) + (irons.ScopeMagnification or 0))
|
||||
|
||||
if tmag < threshold then return end
|
||||
|
||||
return 1 / tmag
|
||||
end
|
||||
|
||||
function SWEP:Scroll(var)
|
||||
local irons = self:GetActiveSights()
|
||||
|
||||
if irons.ScrollFunc == ArcCW.SCROLL_ZOOM then
|
||||
if !irons.ScopeMagnificationMin then return end
|
||||
if !irons.ScopeMagnificationMax then return end
|
||||
|
||||
local old = irons.ScopeMagnification
|
||||
|
||||
local minus = var < 0
|
||||
|
||||
var = math.abs(irons.ScopeMagnificationMax - irons.ScopeMagnificationMin)
|
||||
|
||||
var = var / (irons.ZoomLevels or 5)
|
||||
|
||||
if minus then
|
||||
var = var * -1
|
||||
end
|
||||
|
||||
irons.ScopeMagnification = irons.ScopeMagnification - var
|
||||
|
||||
irons.ScopeMagnification = math.Clamp(irons.ScopeMagnification, irons.ScopeMagnificationMin, irons.ScopeMagnificationMax)
|
||||
|
||||
self.SightMagnifications[irons.Slot or 0] = irons.ScopeMagnification
|
||||
|
||||
if old != irons.ScopeMagnification then
|
||||
self:MyEmitSound(irons.ZoomSound or "", 75, math.Rand(95, 105), 1, CHAN_ITEM)
|
||||
end
|
||||
|
||||
-- if !irons.MinZoom then return end
|
||||
-- if !irons.MaxZoom then return end
|
||||
|
||||
-- local old = irons.Magnification
|
||||
|
||||
-- irons.Magnification = irons.Magnification - var
|
||||
|
||||
-- irons.Magnification = math.Clamp(irons.Magnification, irons.MinZoom, irons.MaxZoom)
|
||||
|
||||
-- if old != irons.Magnification then
|
||||
-- self:MyEmitSound(irons.ZoomSound or "", 75, 100, 1, CHAN_ITEM)
|
||||
-- end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local ang0 = Angle(0, 0, 0)
|
||||
|
||||
SWEP.ViewPunchAngle = Angle(ang0)
|
||||
SWEP.ViewPunchVelocity = Angle(ang0)
|
||||
|
||||
function SWEP:OurViewPunch(angle)
|
||||
self.ViewPunchVelocity:Add(angle)
|
||||
for i = 1, 3 do self.ViewPunchVelocity[i] = math.Clamp(self.ViewPunchVelocity[i], -180, 180) end
|
||||
end
|
||||
|
||||
function SWEP:GetOurViewPunchAngles()
|
||||
local a = self:GetOwner():GetViewPunchAngles()
|
||||
for i = 1, 3 do a[i] = a[i] + self.ViewPunchAngle[i] * 10 end
|
||||
return a
|
||||
end
|
||||
|
||||
local function lensqr(ang)
|
||||
return (ang[1] ^ 2) + (ang[2] ^ 2) + (ang[3] ^ 2)
|
||||
end
|
||||
|
||||
-- scraped from source SDK 2013, just like this viewpunch damping code
|
||||
local PUNCH_DAMPING = 9
|
||||
local PUNCH_SPRING_CONSTANT = 120
|
||||
|
||||
function SWEP:DoOurViewPunch()
|
||||
-- if ( player->m_Local.m_vecPunchAngle->LengthSqr() > 0.001 || player->m_Local.m_vecPunchAngleVel->LengthSqr() > 0.001 )
|
||||
|
||||
local vpa = self.ViewPunchAngle
|
||||
local vpv = self.ViewPunchVelocity
|
||||
|
||||
if lensqr(vpa) + lensqr(vpv) > 0.000001 then
|
||||
-- {
|
||||
-- player->m_Local.m_vecPunchAngle += player->m_Local.m_vecPunchAngleVel * gpGlobals->frametime;
|
||||
-- float damping = 1 - (PUNCH_DAMPING * gpGlobals->frametime);
|
||||
|
||||
local ft = FrameTime()
|
||||
|
||||
vpa = vpa + (vpv * ft)
|
||||
local damping = 1 - (PUNCH_DAMPING * ft)
|
||||
|
||||
-- if ( damping < 0 )
|
||||
-- {
|
||||
-- damping = 0;
|
||||
-- }
|
||||
|
||||
if damping < 0 then damping = 0 end
|
||||
|
||||
-- player->m_Local.m_vecPunchAngleVel *= damping;
|
||||
|
||||
vpv = vpv * damping
|
||||
|
||||
-- // torsional spring
|
||||
-- // UNDONE: Per-axis spring constant?
|
||||
-- float springForceMagnitude = PUNCH_SPRING_CONSTANT * gpGlobals->frametime;
|
||||
local springforcemagnitude = PUNCH_SPRING_CONSTANT * ft
|
||||
-- springForceMagnitude = clamp(springForceMagnitude, 0.f, 2.f );
|
||||
springforcemagnitude = math.Clamp(springforcemagnitude, 0, 2)
|
||||
-- player->m_Local.m_vecPunchAngleVel -= player->m_Local.m_vecPunchAngle * springForceMagnitude;
|
||||
vpv = vpv - (vpa * springforcemagnitude)
|
||||
|
||||
-- // don't wrap around
|
||||
-- player->m_Local.m_vecPunchAngle.Init(
|
||||
-- clamp(player->m_Local.m_vecPunchAngle->x, -89.f, 89.f ),
|
||||
-- clamp(player->m_Local.m_vecPunchAngle->y, -179.f, 179.f ),
|
||||
-- clamp(player->m_Local.m_vecPunchAngle->z, -89.f, 89.f ) );
|
||||
-- }
|
||||
|
||||
vpa[1] = math.Clamp(vpa[1], -89.9, 89.9)
|
||||
vpa[2] = math.Clamp(vpa[2], -179.9, 179.9)
|
||||
vpa[3] = math.Clamp(vpa[3], -89.9, 89.9)
|
||||
|
||||
self.ViewPunchAngle = vpa
|
||||
self.ViewPunchVelocity = vpv
|
||||
else
|
||||
self.ViewPunchAngle = Angle(ang0)
|
||||
self.ViewPunchVelocity = Angle(ang0)
|
||||
end
|
||||
end
|
||||
|
||||
-- viewbob during reload and firing shake
|
||||
SWEP.ProceduralViewOffset = Angle(ang0)
|
||||
local procedural_spdlimit = 5
|
||||
local oldangtmp
|
||||
local mzang_fixed,mzang_fixed_last
|
||||
local mzang_velocity = Angle(ang0)
|
||||
local progress = 0
|
||||
local targint,targbool
|
||||
|
||||
function SWEP:CoolView(ply, pos, ang, fov)
|
||||
if !ang then return end
|
||||
if ply != LocalPlayer() then return end
|
||||
if ply:ShouldDrawLocalPlayer() then return end
|
||||
local vm = ply:GetViewModel()
|
||||
if !IsValid(vm) then return end
|
||||
local ftv = FrameTime()
|
||||
|
||||
local gunbone, gbslot = self:GetBuff_Override("LHIK_CamDriver")
|
||||
local lhik_anim_model = gbslot and self.Attachments[gbslot].GodDriver and self.Attachments[gbslot].GodDriver.Model
|
||||
if IsValid(lhik_anim_model) and lhik_anim_model:GetAttachment(gunbone) then
|
||||
local catang = lhik_anim_model:GetAttachment(gunbone).Ang
|
||||
|
||||
catang:Sub( Angle( 0, 90, 90 ) )
|
||||
catang.y = -catang.y
|
||||
local r = catang.r
|
||||
catang.r = -catang.p
|
||||
catang.p = -r
|
||||
|
||||
ang:RotateAroundAxis( ang:Right(), catang.x )
|
||||
ang:RotateAroundAxis( ang:Up(), catang.y )
|
||||
ang:RotateAroundAxis( ang:Forward(), catang.z )
|
||||
|
||||
end
|
||||
|
||||
-- Cam_Offset_Ang might not always be assigned properly. Try not to use it if it's nil, or it'll tilt the player's view.
|
||||
local att = self:GetBuff_Override("Override_CamAttachment", self.CamAttachment) or -1
|
||||
if vm:GetAttachment(att) and self.Cam_Offset_Ang then
|
||||
local attang = vm:WorldToLocalAngles(vm:GetAttachment(att).Ang)
|
||||
attang:Sub(self.Cam_Offset_Ang)
|
||||
ang:Add(attang)
|
||||
return
|
||||
end
|
||||
|
||||
local viewbobintensity = self.ProceduralViewBobIntensity or 0.3
|
||||
|
||||
if viewbobintensity == 0 then return end
|
||||
|
||||
oldpostmp = pos * 1
|
||||
oldangtmp = ang * 1
|
||||
|
||||
targbool = self:GetNextPrimaryFire() - .1 > CurTime()
|
||||
targint = targbool and 1 or 0
|
||||
targint = math.min(targint, 1-math.pow( vm:GetCycle(), 2 ) )
|
||||
progress = Lerp(ftv * 15, progress, targint)
|
||||
|
||||
local angpos = vm:GetAttachment(self.ProceduralViewBobAttachment or self.MuzzleEffectAttachment or 1)
|
||||
|
||||
if angpos and self:GetReloading() then
|
||||
mzang_fixed = vm:WorldToLocalAngles(angpos.Ang)
|
||||
mzang_fixed:Normalize()
|
||||
else return
|
||||
end
|
||||
|
||||
self.ProceduralViewOffset:Normalize()
|
||||
|
||||
if mzang_fixed_last then
|
||||
local delta = mzang_fixed - mzang_fixed_last
|
||||
delta:Normalize()
|
||||
mzang_velocity = mzang_velocity + delta * 2
|
||||
mzang_velocity.p = math.Approach(mzang_velocity.p, -self.ProceduralViewOffset.p * 2, ftv * 20)
|
||||
mzang_velocity.p = math.Clamp(mzang_velocity.p, -procedural_spdlimit, procedural_spdlimit)
|
||||
self.ProceduralViewOffset.p = self.ProceduralViewOffset.p + mzang_velocity.p * ftv
|
||||
self.ProceduralViewOffset.p = math.Clamp(self.ProceduralViewOffset.p, -90, 90)
|
||||
mzang_velocity.y = math.Approach(mzang_velocity.y, -self.ProceduralViewOffset.y * 2, ftv * 20)
|
||||
mzang_velocity.y = math.Clamp(mzang_velocity.y, -procedural_spdlimit, procedural_spdlimit)
|
||||
self.ProceduralViewOffset.y = self.ProceduralViewOffset.y + mzang_velocity.y * ftv
|
||||
self.ProceduralViewOffset.y = math.Clamp(self.ProceduralViewOffset.y, -90, 90)
|
||||
mzang_velocity.r = math.Approach(mzang_velocity.r, -self.ProceduralViewOffset.r * 2, ftv * 20)
|
||||
mzang_velocity.r = math.Clamp(mzang_velocity.r, -procedural_spdlimit, procedural_spdlimit)
|
||||
self.ProceduralViewOffset.r = self.ProceduralViewOffset.r + mzang_velocity.r * ftv
|
||||
self.ProceduralViewOffset.r = math.Clamp(self.ProceduralViewOffset.r, -90, 90)
|
||||
end
|
||||
|
||||
self.ProceduralViewOffset.p = math.Approach(self.ProceduralViewOffset.p, 0, (1 - progress) * ftv * -self.ProceduralViewOffset.p)
|
||||
self.ProceduralViewOffset.y = math.Approach(self.ProceduralViewOffset.y, 0, (1 - progress) * ftv * -self.ProceduralViewOffset.y)
|
||||
self.ProceduralViewOffset.r = math.Approach(self.ProceduralViewOffset.r, 0, (1 - progress) * ftv * -self.ProceduralViewOffset.r)
|
||||
mzang_fixed_last = mzang_fixed
|
||||
local ints = 3 * ArcCW.ConVars["vm_coolview_mult"]:GetFloat() * -viewbobintensity
|
||||
ang:RotateAroundAxis(ang:Right(), Lerp(progress, 0, -self.ProceduralViewOffset.p) * ints)
|
||||
ang:RotateAroundAxis(ang:Up(), Lerp(progress, 0, self.ProceduralViewOffset.y / 2) * ints)
|
||||
ang:RotateAroundAxis(ang:Forward(), Lerp(progress, 0, self.ProceduralViewOffset.r / 3) * ints)
|
||||
|
||||
ang = LerpAngle(0, ang, oldangtmp)
|
||||
end
|
||||
|
||||
function SWEP:CalcView(ply, pos, ang, fov)
|
||||
if !CLIENT then return end
|
||||
|
||||
if ArcCW.ConVars["vm_coolview"]:GetBool() then
|
||||
self:CoolView(ply, pos, ang, fov)
|
||||
end
|
||||
|
||||
if ArcCW.ConVars["shake"]:GetBool() and !engine.IsRecordingDemo() then
|
||||
local de = (0.2 + (self:GetSightDelta()*0.8))
|
||||
ang = ang + (AngleRand() * self.RecoilAmount * 0.006 * de)
|
||||
end
|
||||
|
||||
ang = ang + (self.ViewPunchAngle * 10)
|
||||
|
||||
return pos, ang, fov
|
||||
end
|
||||
|
||||
function SWEP:ShouldGlint()
|
||||
return self:GetBuff_Override("ScopeGlint") and self:GetState() == ArcCW.STATE_SIGHTS
|
||||
end
|
||||
|
||||
function SWEP:DoScopeGlint()
|
||||
end
|
||||
887
lua/weapons/arccw_base/cl_viewmodel.lua
Normal file
887
lua/weapons/arccw_base/cl_viewmodel.lua
Normal file
@@ -0,0 +1,887 @@
|
||||
--[[
|
||||
| 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
|
||||
311
lua/weapons/arccw_base/sh_anim.lua
Normal file
311
lua/weapons/arccw_base/sh_anim.lua
Normal file
@@ -0,0 +1,311 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
SWEP.Cam_Offset_Ang = nil --Angle(0, 0, 0)
|
||||
|
||||
function SWEP:SelectAnimation(anim)
|
||||
if self:GetNWState() == ArcCW.STATE_SIGHTS and self.Animations[anim .. "_iron"] then
|
||||
anim = anim .. "_iron"
|
||||
end
|
||||
|
||||
if self:GetNWState() == ArcCW.STATE_SIGHTS and self.Animations[anim .. "_sights"] then
|
||||
anim = anim .. "_sights"
|
||||
end
|
||||
|
||||
if self:GetNWState() == ArcCW.STATE_SIGHTS and self.Animations[anim .. "_sight"] then
|
||||
anim = anim .. "_sight"
|
||||
end
|
||||
|
||||
if self:GetNWState() == ArcCW.STATE_SPRINT and self.Animations[anim .. "_sprint"] and !self:CanShootWhileSprint() then
|
||||
anim = anim .. "_sprint"
|
||||
end
|
||||
|
||||
if self:InBipod() and self.Animations[anim .. "_bipod"] then
|
||||
anim = anim .. "_bipod"
|
||||
end
|
||||
|
||||
if self:GetState() == ArcCW.STATE_CUSTOMIZE and self.Animations[anim .. "_inspect"] and ((CLIENT and !ArcCW.ConVars["noinspect"]:GetBool()) or (SERVER and self:GetOwner():GetInfoNum("arccw_noinspect", 0))) then
|
||||
anim = anim .. "_inspect"
|
||||
end
|
||||
|
||||
if (self:Clip1() == 0 or (self:HasBottomlessClip() and self:Ammo1() == 0)) and self.Animations[anim .. "_empty"] then
|
||||
anim = anim .. "_empty"
|
||||
end
|
||||
|
||||
if self:GetMalfunctionJam() and self.Animations[anim .. "_jammed"] then
|
||||
anim = anim .. "_jammed"
|
||||
end
|
||||
|
||||
if self:GetBuff_Override("Override_TriggerDelay", self.TriggerDelay) and self:IsTriggerHeld() and self.Animations[anim .. "_trigger"] then
|
||||
anim = anim .. "_trigger"
|
||||
end
|
||||
|
||||
if !self.Animations[anim] then return end
|
||||
|
||||
return anim
|
||||
end
|
||||
|
||||
SWEP.LastAnimStartTime = 0
|
||||
SWEP.LastAnimFinishTime = 0
|
||||
|
||||
function SWEP:PlayAnimationEZ(key, mult, priority)
|
||||
return self:PlayAnimation(key, mult, true, 0, false, false, priority, false)
|
||||
end
|
||||
|
||||
function SWEP:PlayAnimation(key, mult, pred, startfrom, tt, skipholster, priority, absolute)
|
||||
mult = mult or 1
|
||||
pred = pred or false
|
||||
startfrom = startfrom or 0
|
||||
tt = tt or false
|
||||
--skipholster = skipholster or false Unused
|
||||
priority = priority or false
|
||||
absolute = absolute or false
|
||||
if !key then return end
|
||||
|
||||
local ct = CurTime()
|
||||
|
||||
if self:GetPriorityAnim() and !priority then return end
|
||||
|
||||
if game.SinglePlayer() and SERVER and pred then
|
||||
net.Start("arccw_sp_anim")
|
||||
net.WriteString(key)
|
||||
net.WriteFloat(mult)
|
||||
net.WriteFloat(startfrom)
|
||||
net.WriteBool(tt)
|
||||
--net.WriteBool(skipholster) Unused
|
||||
net.WriteBool(priority)
|
||||
net.Send(self:GetOwner())
|
||||
end
|
||||
|
||||
local anim = self.Animations[key]
|
||||
if !anim then return end
|
||||
local tranim = self:GetBuff_Hook("Hook_TranslateAnimation", key)
|
||||
if self.Animations[tranim] then
|
||||
key = tranim
|
||||
anim = self.Animations[tranim]
|
||||
--[[elseif self.Animations[key] then -- Can't do due to backwards compatibility... unless you have a better idea?
|
||||
anim = self.Animations[key]
|
||||
else
|
||||
return]]
|
||||
end
|
||||
|
||||
if anim.ViewPunchTable and CLIENT then
|
||||
for k, v in pairs(anim.ViewPunchTable) do
|
||||
|
||||
if !v.t then continue end
|
||||
|
||||
local st = (v.t * mult) - startfrom
|
||||
|
||||
if isnumber(v.t) and st >= 0 and self:GetOwner():IsPlayer() and (game.SinglePlayer() or IsFirstTimePredicted()) then
|
||||
self:SetTimer(st, function() self:OurViewPunch(v.p or Vector(0, 0, 0)) end, id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if isnumber(anim.ShellEjectAt) then
|
||||
self:SetTimer(anim.ShellEjectAt * mult, function()
|
||||
local num = 1
|
||||
if self.RevolverReload then
|
||||
num = self.Primary.ClipSize - self:Clip1()
|
||||
end
|
||||
for i = 1,num do
|
||||
self:DoShellEject()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
if !self:GetOwner() then return end
|
||||
if !self:GetOwner().GetViewModel then return end
|
||||
local vm = self:GetOwner():GetViewModel()
|
||||
|
||||
if !vm then return end
|
||||
if !IsValid(vm) then return end
|
||||
|
||||
local seq = anim.Source
|
||||
if anim.RareSource and util.SharedRandom("raresource", 0, 1, CurTime()) < (1 / (anim.RareSourceChance or 100)) then
|
||||
seq = anim.RareSource
|
||||
end
|
||||
seq = self:GetBuff_Hook("Hook_TranslateSequence", seq)
|
||||
|
||||
if istable(seq) then
|
||||
seq["BaseClass"] = nil
|
||||
seq = seq[math.Round(util.SharedRandom("randomseq" .. CurTime(), 1, #seq))]
|
||||
end
|
||||
|
||||
if isstring(seq) then
|
||||
seq = vm:LookupSequence(seq)
|
||||
end
|
||||
|
||||
local time = absolute and 1 or self:GetAnimKeyTime(key)
|
||||
--if time == 0 then return end
|
||||
|
||||
local ttime = (time * mult) - startfrom
|
||||
if startfrom > (time * mult) then return end
|
||||
|
||||
if tt then
|
||||
self:SetNextPrimaryFire(ct + ((anim.MinProgress or time) * mult) - startfrom)
|
||||
end
|
||||
|
||||
if anim.LHIK then
|
||||
self.LHIKStartTime = ct
|
||||
self.LHIKEndTime = ct + ttime
|
||||
|
||||
if anim.LHIKTimeline then
|
||||
self.LHIKTimeline = {}
|
||||
|
||||
for i, k in pairs(anim.LHIKTimeline) do
|
||||
table.Add(self.LHIKTimeline, {t = (k.t or 0) * mult, lhik = k.lhik or 1})
|
||||
end
|
||||
else
|
||||
self.LHIKTimeline = {
|
||||
{t = -math.huge, lhik = 1},
|
||||
{t = ((anim.LHIKIn or 0.1) - (anim.LHIKEaseIn or anim.LHIKIn or 0.1)) * mult, lhik = 1},
|
||||
{t = (anim.LHIKIn or 0.1) * mult, lhik = 0},
|
||||
{t = ttime - ((anim.LHIKOut or 0.1) * mult), lhik = 0},
|
||||
{t = ttime - (((anim.LHIKOut or 0.1) - (anim.LHIKEaseOut or anim.LHIKOut or 0.1)) * mult), lhik = 1},
|
||||
{t = math.huge, lhik = 1}
|
||||
}
|
||||
|
||||
if anim.LHIKIn == 0 then
|
||||
self.LHIKTimeline[1].lhik = -math.huge
|
||||
self.LHIKTimeline[2].lhik = -math.huge
|
||||
end
|
||||
|
||||
if anim.LHIKOut == 0 then
|
||||
self.LHIKTimeline[#self.LHIKTimeline - 1].lhik = math.huge
|
||||
self.LHIKTimeline[#self.LHIKTimeline].lhik = math.huge
|
||||
end
|
||||
end
|
||||
else
|
||||
self.LHIKTimeline = nil
|
||||
end
|
||||
|
||||
if anim.LastClip1OutTime then
|
||||
self.LastClipOutTime = ct + ((anim.LastClip1OutTime * mult) - startfrom)
|
||||
end
|
||||
|
||||
if anim.TPAnim then
|
||||
local aseq = self:GetOwner():SelectWeightedSequence(anim.TPAnim)
|
||||
if aseq then
|
||||
self:GetOwner():AddVCDSequenceToGestureSlot( GESTURE_SLOT_ATTACK_AND_RELOAD, aseq, anim.TPAnimStartTime or 0, true )
|
||||
if !game.SinglePlayer() and SERVER then
|
||||
net.Start("arccw_networktpanim")
|
||||
net.WriteEntity(self:GetOwner())
|
||||
net.WriteUInt(aseq, 16)
|
||||
net.WriteFloat(anim.TPAnimStartTime or 0)
|
||||
net.SendPVS(self:GetOwner():GetPos())
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if !(game.SinglePlayer() and CLIENT) and (game.SinglePlayer() or IsFirstTimePredicted() or self.ReadySoundTableHack) then
|
||||
self:PlaySoundTable(anim.SoundTable or {}, 1 / mult, startfrom, key)
|
||||
self.ReadySoundTableHack = nil
|
||||
end
|
||||
|
||||
if seq then
|
||||
vm:SendViewModelMatchingSequence(seq)
|
||||
local dur = vm:SequenceDuration()
|
||||
vm:SetPlaybackRate(math.Clamp(dur / (ttime + startfrom), -4, 12))
|
||||
self.LastAnimStartTime = ct
|
||||
self.LastAnimFinishTime = ct + dur
|
||||
self.LastAnimKey = key
|
||||
end
|
||||
|
||||
-- Grabs the current angle of the cam attachment bone and use it as the common offset for all cambone changes.
|
||||
-- Problem: If this animation interrupted a previous animation with cambone movement,
|
||||
-- it will start with an incorrect offset and snap at the end.
|
||||
-- Therefore this now only ever sets it once.
|
||||
local att = self:GetBuff_Override("Override_CamAttachment", self.CamAttachment)
|
||||
if att and vm:GetAttachment(att) and (anim.ForceCamReset or self.Cam_Offset_Ang == nil) then
|
||||
local ang = vm:GetAttachment(att).Ang
|
||||
ang = vm:WorldToLocalAngles(ang)
|
||||
self.Cam_Offset_Ang = Angle(ang)
|
||||
end
|
||||
|
||||
self:SetNextIdle(CurTime() + ttime)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function SWEP:PlayIdleAnimation(pred)
|
||||
local ianim = self:SelectAnimation("idle")
|
||||
if self:GetGrenadePrimed() then
|
||||
ianim = self:GetGrenadeAlt() and self:SelectAnimation("pre_throw_hold_alt") or self:SelectAnimation("pre_throw_hold")
|
||||
end
|
||||
|
||||
-- (key, mult, pred, startfrom, tt, skipholster, ignorereload)
|
||||
if self:GetBuff_Override("UBGL_BaseAnims") and self:GetInUBGL()
|
||||
and self.Animations.idle_ubgl_empty and self:Clip2() <= 0 then
|
||||
ianim = "idle_ubgl_empty"
|
||||
elseif self:GetBuff_Override("UBGL_BaseAnims") and self:GetInUBGL() and self.Animations.idle_ubgl then
|
||||
ianim = "idle_ubgl"
|
||||
end
|
||||
|
||||
if self.LastAnimKey ~= ianim then
|
||||
ianim = self:GetBuff_Hook("Hook_IdleReset", ianim) or ianim
|
||||
end
|
||||
|
||||
self:PlayAnimation(ianim, 1, pred, nil, nil, nil, true)
|
||||
end
|
||||
|
||||
function SWEP:GetAnimKeyTime(key, min)
|
||||
if !self:GetOwner() then return 1 end
|
||||
|
||||
local anim = self.Animations[key]
|
||||
|
||||
if !anim then return 1 end
|
||||
|
||||
if self:GetOwner():IsNPC() then return anim.Time or 1 end
|
||||
|
||||
local vm = self:GetOwner():GetViewModel()
|
||||
|
||||
if !vm or !IsValid(vm) then return 1 end
|
||||
|
||||
local t = anim.Time
|
||||
if !t then
|
||||
local tseq = anim.Source
|
||||
|
||||
if istable(tseq) then
|
||||
tseq["BaseClass"] = nil -- god I hate Lua inheritance
|
||||
tseq = tseq[1]
|
||||
end
|
||||
|
||||
if !tseq then return 1 end
|
||||
tseq = vm:LookupSequence(tseq)
|
||||
|
||||
-- to hell with it, just spits wrong on draw sometimes
|
||||
t = vm:SequenceDuration(tseq) or 1
|
||||
end
|
||||
|
||||
if min and anim.MinProgress then
|
||||
t = anim.MinProgress
|
||||
end
|
||||
|
||||
if anim.Mult then
|
||||
t = t * anim.Mult
|
||||
end
|
||||
|
||||
return t
|
||||
end
|
||||
|
||||
if CLIENT then
|
||||
net.Receive("arccw_networktpanim", function()
|
||||
local ent = net.ReadEntity()
|
||||
local aseq = net.ReadUInt(16)
|
||||
local starttime = net.ReadFloat()
|
||||
if IsValid(ent) and ent ~= LocalPlayer() and ent:IsPlayer() then
|
||||
ent:AddVCDSequenceToGestureSlot( GESTURE_SLOT_ATTACK_AND_RELOAD, aseq, starttime, true )
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function SWEP:QueueAnimation() end
|
||||
function SWEP:NextAnimation() end
|
||||
1777
lua/weapons/arccw_base/sh_attach.lua
Normal file
1777
lua/weapons/arccw_base/sh_attach.lua
Normal file
File diff suppressed because it is too large
Load Diff
271
lua/weapons/arccw_base/sh_bash.lua
Normal file
271
lua/weapons/arccw_base/sh_bash.lua
Normal file
@@ -0,0 +1,271 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
function SWEP:CanBackstab(melee2, ent)
|
||||
if !self:GetBuff_Override("Override_Backstab", self.Backstab) then return false end
|
||||
local reach = 32 + self:GetBuff_Add("Add_MeleeRange") + (melee2 and self.Melee2Range or self.MeleeRange)
|
||||
|
||||
if (!IsValid(ent)) then
|
||||
local tr = util.TraceLine({
|
||||
start = self:GetOwner():GetShootPos(),
|
||||
endpos = self:GetOwner():GetShootPos() + self:GetOwner():GetAimVector() * reach,
|
||||
filter = {self:GetOwner()},
|
||||
mask = MASK_SHOT_HULL
|
||||
})
|
||||
if tr.Entity:IsPlayer() or tr.Entity:IsNPC() or tr.Entity:IsNextBot() then
|
||||
ent = tr.Entity
|
||||
end
|
||||
end
|
||||
|
||||
if (!IsValid(ent)) then
|
||||
local tr = util.TraceHull({
|
||||
start = self:GetOwner():GetShootPos(),
|
||||
endpos = self:GetOwner():GetShootPos() + self:GetOwner():GetAimVector() * reach,
|
||||
filter = {self:GetOwner()},
|
||||
mins = Vector(-16, -16, -8),
|
||||
maxs = Vector(16, 16, 8),
|
||||
mask = MASK_SHOT_HULL
|
||||
})
|
||||
if tr.Entity:IsPlayer() or tr.Entity:IsNPC() or tr.Entity:IsNextBot() then
|
||||
ent = tr.Entity
|
||||
end
|
||||
end
|
||||
|
||||
if IsValid(ent) then
|
||||
local angle = math.NormalizeAngle(self:GetOwner():GetAngles().y - ent:GetAngles().y)
|
||||
return angle <= 90 and angle >= -90
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function SWEP:DoLunge(melee2)
|
||||
if ArcCW.ConVars["override_lunge_off"]:GetBool() then return end
|
||||
local var = self:GetBuff_Override("Override_Lunge", self.Lunge)
|
||||
if var == false or var == nil and self.PrimaryBash then return end
|
||||
if !self:GetOwner():IsPlayer() or self:GetOwner():Crouching() then return end
|
||||
|
||||
local reach = 32 + self:GetBuff_Add("Add_MeleeRange") + (melee2 and self.Melee2Range or self.MeleeRange)
|
||||
local tr = self:GetOwner():GetEyeTrace()
|
||||
local tgt = tr.Entity
|
||||
|
||||
if IsValid(tgt) and (tgt:IsPlayer() or tgt:IsNPC() or tgt:IsNextBot()) then
|
||||
|
||||
local dist = (tr.HitPos - tr.StartPos):Length()
|
||||
|
||||
if dist > reach and dist < reach + self:GetBuff("LungeLength") then
|
||||
local dir = tr.Normal
|
||||
dir.z = math.min(dir.z, 0)
|
||||
dir:Normalize()
|
||||
self:GetOwner():SetVelocity(dir * (self:GetOwner():IsOnGround() and 5 or 2.5) * dist)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:Bash(melee2)
|
||||
melee2 = melee2 or false
|
||||
if self:GetState() == ArcCW.STATE_SIGHTS
|
||||
or (self:GetState() == ArcCW.STATE_SPRINT and !self:CanShootWhileSprint())
|
||||
or self:GetState() == ArcCW.STATE_CUSTOMIZE then
|
||||
return
|
||||
end
|
||||
if self:GetNextPrimaryFire() > CurTime() or self:GetGrenadePrimed() or self:GetPriorityAnim() then return end
|
||||
|
||||
if !self.CanBash and !self:GetBuff_Override("Override_CanBash") then return end
|
||||
|
||||
self:GetBuff_Hook("Hook_PreBash")
|
||||
|
||||
self.Primary.Automatic = true
|
||||
|
||||
local mult = self:GetBuff_Mult("Mult_MeleeTime")
|
||||
local mt = self.MeleeTime * mult
|
||||
|
||||
if melee2 then
|
||||
mt = self.Melee2Time * mult
|
||||
end
|
||||
|
||||
mt = mt * self:GetBuff_Mult("Mult_MeleeWaitTime")
|
||||
|
||||
local bashanim = "bash"
|
||||
local canbackstab = self:CanBackstab(melee2)
|
||||
|
||||
if melee2 then
|
||||
bashanim = canbackstab and self:SelectAnimation("bash2_backstab") or self:SelectAnimation("bash2") or bashanim
|
||||
else
|
||||
bashanim = canbackstab and self:SelectAnimation("bash_backstab") or self:SelectAnimation("bash") or bashanim
|
||||
end
|
||||
|
||||
bashanim = self:GetBuff_Hook("Hook_SelectBashAnim", bashanim) or bashanim
|
||||
|
||||
if bashanim and self.Animations[bashanim] then
|
||||
if SERVER then self:PlayAnimation(bashanim, mult, true, 0, true) end
|
||||
else
|
||||
self:ProceduralBash()
|
||||
|
||||
self:MyEmitSound(self.MeleeSwingSound, 75, 100, 1, CHAN_USER_BASE + 1)
|
||||
end
|
||||
|
||||
if CLIENT then
|
||||
self:OurViewPunch(-self.BashPrepareAng * 0.05)
|
||||
end
|
||||
self:SetNextPrimaryFire(CurTime() + mt )
|
||||
|
||||
if melee2 then
|
||||
if self.HoldtypeActive == "pistol" or self.HoldtypeActive == "revolver" then
|
||||
self:GetOwner():DoAnimationEvent(self.Melee2Gesture or ACT_HL2MP_GESTURE_RANGE_ATTACK_GRENADE)
|
||||
else
|
||||
self:GetOwner():DoAnimationEvent(self.Melee2Gesture or ACT_GMOD_GESTURE_MELEE_SHOVE_2HAND)
|
||||
end
|
||||
else
|
||||
if self.HoldtypeActive == "pistol" or self.HoldtypeActive == "revolver" then
|
||||
self:GetOwner():DoAnimationEvent(self.MeleeGesture or ACT_HL2MP_GESTURE_RANGE_ATTACK_GRENADE)
|
||||
else
|
||||
self:GetOwner():DoAnimationEvent(self.MeleeGesture or ACT_GMOD_GESTURE_MELEE_SHOVE_2HAND)
|
||||
end
|
||||
end
|
||||
|
||||
local mat = self.MeleeAttackTime
|
||||
|
||||
if melee2 then
|
||||
mat = self.Melee2AttackTime
|
||||
end
|
||||
|
||||
mat = mat * self:GetBuff_Mult("Mult_MeleeAttackTime") * math.pow(mult, 1.5)
|
||||
|
||||
self:SetTimer(mat or (0.125 * mt), function()
|
||||
if !IsValid(self) then return end
|
||||
if !IsValid(self:GetOwner()) then return end
|
||||
if self:GetOwner():GetActiveWeapon() != self then return end
|
||||
|
||||
if CLIENT then
|
||||
self:OurViewPunch(-self.BashAng * 0.05)
|
||||
end
|
||||
|
||||
self:MeleeAttack(melee2)
|
||||
end)
|
||||
|
||||
self:DoLunge()
|
||||
end
|
||||
|
||||
function SWEP:MeleeAttack(melee2)
|
||||
local reach = 32 + self:GetBuff_Add("Add_MeleeRange") + self.MeleeRange
|
||||
local dmg = self:GetBuff_Override("Override_MeleeDamage", self.MeleeDamage) or 20
|
||||
|
||||
if melee2 then
|
||||
reach = 32 + self:GetBuff_Add("Add_MeleeRange") + self.Melee2Range
|
||||
dmg = self:GetBuff_Override("Override_MeleeDamage", self.Melee2Damage) or 20
|
||||
end
|
||||
|
||||
dmg = dmg * self:GetBuff_Mult("Mult_MeleeDamage")
|
||||
|
||||
self:GetOwner():LagCompensation(true)
|
||||
|
||||
local filter = {self:GetOwner()}
|
||||
|
||||
table.Add(filter, self.Shields)
|
||||
|
||||
local tr = util.TraceLine({
|
||||
start = self:GetOwner():GetShootPos(),
|
||||
endpos = self:GetOwner():GetShootPos() + self:GetOwner():GetAimVector() * reach,
|
||||
filter = filter,
|
||||
mask = MASK_SHOT_HULL
|
||||
})
|
||||
|
||||
if (!IsValid(tr.Entity)) then
|
||||
tr = util.TraceHull({
|
||||
start = self:GetOwner():GetShootPos(),
|
||||
endpos = self:GetOwner():GetShootPos() + self:GetOwner():GetAimVector() * reach,
|
||||
filter = filter,
|
||||
mins = Vector(-16, -16, -8),
|
||||
maxs = Vector(16, 16, 8),
|
||||
mask = MASK_SHOT_HULL
|
||||
})
|
||||
end
|
||||
|
||||
-- Backstab damage if applicable
|
||||
local backstab = tr.Hit and self:CanBackstab(melee2, tr.Entity)
|
||||
if backstab then
|
||||
if melee2 then
|
||||
local bs_dmg = self:GetBuff_Override("Override_Melee2DamageBackstab", self.Melee2DamageBackstab)
|
||||
if bs_dmg then
|
||||
dmg = bs_dmg * self:GetBuff_Mult("Mult_MeleeDamage")
|
||||
else
|
||||
dmg = dmg * self:GetBuff("BackstabMultiplier") * self:GetBuff_Mult("Mult_MeleeDamage")
|
||||
end
|
||||
else
|
||||
local bs_dmg = self:GetBuff_Override("Override_MeleeDamageBackstab", self.MeleeDamageBackstab)
|
||||
if bs_dmg then
|
||||
dmg = bs_dmg * self:GetBuff_Mult("Mult_MeleeDamage")
|
||||
else
|
||||
dmg = dmg * self:GetBuff("BackstabMultiplier") * self:GetBuff_Mult("Mult_MeleeDamage")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- We need the second part for single player because SWEP:Think is ran shared in SP
|
||||
if !(game.SinglePlayer() and CLIENT) then
|
||||
if tr.Hit then
|
||||
if tr.Entity:IsNPC() or tr.Entity:IsNextBot() or tr.Entity:IsPlayer() then
|
||||
self:MyEmitSound(self.MeleeHitNPCSound, 75, 100, 1, CHAN_USER_BASE + 2)
|
||||
else
|
||||
self:MyEmitSound(self.MeleeHitSound, 75, 100, 1, CHAN_USER_BASE + 2)
|
||||
end
|
||||
|
||||
if tr.MatType == MAT_FLESH or tr.MatType == MAT_ALIENFLESH or tr.MatType == MAT_ANTLION or tr.MatType == MAT_BLOODYFLESH then
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(tr.HitPos)
|
||||
|
||||
util.Effect("BloodImpact", fx)
|
||||
end
|
||||
else
|
||||
self:MyEmitSound(self.MeleeMissSound, 75, 100, 1, CHAN_USER_BASE + 3)
|
||||
end
|
||||
end
|
||||
|
||||
if SERVER and IsValid(tr.Entity) and (tr.Entity:IsNPC() or tr.Entity:IsPlayer() or tr.Entity:Health() > 0) then
|
||||
local dmginfo = DamageInfo()
|
||||
|
||||
local attacker = self:GetOwner()
|
||||
if !IsValid(attacker) then attacker = self end
|
||||
dmginfo:SetAttacker(attacker)
|
||||
|
||||
local relspeed = (tr.Entity:GetVelocity() - self:GetOwner():GetAbsVelocity()):Length()
|
||||
|
||||
relspeed = relspeed / 225
|
||||
|
||||
relspeed = math.Clamp(relspeed, 1, 1.5)
|
||||
|
||||
dmginfo:SetInflictor(self)
|
||||
dmginfo:SetDamage(dmg * relspeed)
|
||||
dmginfo:SetDamageType(self:GetBuff_Override("Override_MeleeDamageType") or self.MeleeDamageType or DMG_CLUB)
|
||||
|
||||
dmginfo:SetDamageForce(self:GetOwner():GetRight() * -4912 + self:GetOwner():GetForward() * 9989)
|
||||
|
||||
SuppressHostEvents(NULL)
|
||||
tr.Entity:TakeDamageInfo(dmginfo)
|
||||
SuppressHostEvents(self:GetOwner())
|
||||
|
||||
if tr.Entity:GetClass() == "func_breakable_surf" then
|
||||
tr.Entity:Fire("Shatter", "0.5 0.5 256")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if SERVER and IsValid(tr.Entity) then
|
||||
local phys = tr.Entity:GetPhysicsObject()
|
||||
if IsValid(phys) then
|
||||
phys:ApplyForceOffset(self:GetOwner():GetAimVector() * 80 * phys:GetMass(), tr.HitPos)
|
||||
end
|
||||
end
|
||||
|
||||
self:GetBuff_Hook("Hook_PostBash", {tr = tr, dmg = dmg})
|
||||
|
||||
self:GetOwner():LagCompensation(false)
|
||||
end
|
||||
147
lua/weapons/arccw_base/sh_bipod.lua
Normal file
147
lua/weapons/arccw_base/sh_bipod.lua
Normal file
@@ -0,0 +1,147 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
function SWEP:InBipod()
|
||||
local bip = self:GetInBipod()
|
||||
|
||||
-- if !self:CanBipod() then
|
||||
-- self:ExitBipod()
|
||||
-- end
|
||||
|
||||
if IsValid(self:GetOwner()) and self:GetBipodPos() != self:GetOwner():EyePos() then
|
||||
self:ExitBipod()
|
||||
end
|
||||
|
||||
return bip
|
||||
end
|
||||
|
||||
SWEP.CachedCanBipod = true
|
||||
SWEP.CachedCanBipodTime = 0
|
||||
|
||||
local dist = 24
|
||||
function SWEP:CanBipod()
|
||||
if !(self:GetBuff_Override("Bipod") or self.Bipod_Integral) then return false end
|
||||
|
||||
if self:GetOwner():InVehicle() then return false end
|
||||
|
||||
if self.CachedCanBipodTime >= CurTime() then return self.CachedCanBipod end
|
||||
|
||||
local pos = self:GetOwner():EyePos()
|
||||
local angle = self:GetOwner():EyeAngles()
|
||||
if self:GetOwner():GetVelocity():Length() > 0 then
|
||||
return false
|
||||
end
|
||||
|
||||
local rangemult = 2
|
||||
if self:IsProne() then
|
||||
rangemult = rangemult * 1.25
|
||||
end
|
||||
rangemult = rangemult * self:GetBuff_Mult("Mult_BipodRange")
|
||||
|
||||
local tr = util.TraceLine({
|
||||
start = pos,
|
||||
endpos = pos + (angle:Forward() * dist * rangemult),
|
||||
filter = self:GetOwner(),
|
||||
mask = MASK_PLAYERSOLID
|
||||
})
|
||||
|
||||
if tr.Hit then -- check for stuff in front of us
|
||||
return false
|
||||
end
|
||||
|
||||
local maxs = Vector(8, 8, 16)
|
||||
local mins = Vector(-8, -8, 0)
|
||||
|
||||
angle.p = angle.p + 45
|
||||
|
||||
tr = util.TraceHull({
|
||||
start = pos,
|
||||
endpos = pos + (angle:Forward() * dist * rangemult),
|
||||
filter = self:GetOwner(),
|
||||
maxs = maxs,
|
||||
mins = mins,
|
||||
mask = MASK_PLAYERSOLID
|
||||
})
|
||||
|
||||
self.CachedCanBipodTime = CurTime()
|
||||
|
||||
if tr.Hit then
|
||||
local tr2 = util.TraceHull({
|
||||
start = tr.HitPos,
|
||||
endpos = tr.HitPos + Vector(0, 0, -24),
|
||||
filter = self:GetOwner(),
|
||||
maxs = maxs,
|
||||
mins = mins,
|
||||
mask = MASK_PLAYERSOLID
|
||||
})
|
||||
if tr2.Hit then
|
||||
self.CachedCanBipod = true
|
||||
return true, tr2
|
||||
end
|
||||
end
|
||||
|
||||
self.CachedCanBipod = false
|
||||
return false
|
||||
end
|
||||
|
||||
function SWEP:EnterBipod(sp)
|
||||
if !sp and self:GetInBipod() then return end
|
||||
local can, tr = self:CanBipod()
|
||||
if !sp and !can then return end
|
||||
|
||||
if SERVER and game.SinglePlayer() then self:CallOnClient("EnterBipod", "true") end
|
||||
|
||||
if self.Animations.enter_bipod then
|
||||
self:PlayAnimation("enter_bipod", nil, nil, 0, true)
|
||||
else
|
||||
-- Block actions for a tiny bit even if there is no animation
|
||||
self:SetNextPrimaryFire(CurTime() + 0.25)
|
||||
end
|
||||
|
||||
if CLIENT and self:GetBuff_Override("LHIK") then
|
||||
self:DoLHIKAnimation("enter")
|
||||
end
|
||||
|
||||
local bipodang = tr.HitNormal:Cross(self:GetOwner():EyeAngles():Right()):Angle()
|
||||
|
||||
debugoverlay.Axis(tr.HitPos, tr.HitNormal:Angle(), 16, 5, true)
|
||||
debugoverlay.Line(tr.HitPos, tr.HitPos + bipodang:Forward() * 32, 5, color_white, true)
|
||||
debugoverlay.Line(tr.HitPos, tr.HitPos + self:GetOwner():EyeAngles():Forward() * 32, 5, Color(255, 255, 0), true)
|
||||
|
||||
self:SetBipodPos(self:GetOwner():EyePos())
|
||||
self:SetBipodAngle(bipodang)
|
||||
self.BipodStartAngle = self:GetOwner():EyeAngles()
|
||||
|
||||
if game.SinglePlayer() and CLIENT then return end
|
||||
|
||||
self:MyEmitSound(self.EnterBipodSound)
|
||||
self:SetInBipod(true)
|
||||
end
|
||||
|
||||
function SWEP:ExitBipod(sp)
|
||||
if !sp and !self:GetInBipod() then return end
|
||||
|
||||
if SERVER and game.SinglePlayer() then self:CallOnClient("ExitBipod", "true") end
|
||||
|
||||
if self.Animations.exit_bipod then
|
||||
self:PlayAnimation("exit_bipod", nil, nil, 0, true)
|
||||
else
|
||||
self:SetNextPrimaryFire(CurTime() + 0.25)
|
||||
end
|
||||
|
||||
if CLIENT and self:GetBuff_Override("LHIK") then
|
||||
self:DoLHIKAnimation("exit")
|
||||
end
|
||||
|
||||
if game.SinglePlayer() and CLIENT then return end
|
||||
|
||||
self:MyEmitSound(self.ExitBipodSound)
|
||||
self:SetInBipod(false)
|
||||
end
|
||||
2101
lua/weapons/arccw_base/sh_customize.lua
Normal file
2101
lua/weapons/arccw_base/sh_customize.lua
Normal file
File diff suppressed because it is too large
Load Diff
408
lua/weapons/arccw_base/sh_deploy.lua
Normal file
408
lua/weapons/arccw_base/sh_deploy.lua
Normal file
@@ -0,0 +1,408 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
local ang0 = Angle(0, 0, 0)
|
||||
local dev_alwaysready = ArcCW.ConVars["dev_alwaysready"]
|
||||
|
||||
function SWEP:Deploy()
|
||||
if !IsValid(self:GetOwner()) or self:GetOwner():IsNPC() then
|
||||
return
|
||||
end
|
||||
|
||||
if self.UnReady then
|
||||
local sp = game.SinglePlayer()
|
||||
|
||||
if sp then
|
||||
if SERVER then
|
||||
self:CallOnClient("LoadPreset", "autosave")
|
||||
else
|
||||
self:LoadPreset("autosave")
|
||||
end
|
||||
else
|
||||
if SERVER then
|
||||
-- the server... can't get the client's attachments in time.
|
||||
-- can make it so client has to do a thing and tell the server it's ready,
|
||||
-- and that's probably what i'll do later.
|
||||
else
|
||||
self:LoadPreset("autosave")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self:InitTimers()
|
||||
|
||||
self:SetShouldHoldType()
|
||||
|
||||
self:SetReloading(false)
|
||||
self:SetPriorityAnim(false)
|
||||
self:SetInUBGL(false)
|
||||
self:SetMagUpCount(0)
|
||||
self:SetMagUpIn(0)
|
||||
self:SetShotgunReloading(0)
|
||||
self:SetHolster_Time(0)
|
||||
self:SetHolster_Entity(NULL)
|
||||
|
||||
self:SetFreeAimAngle(ang0)
|
||||
self:SetLastAimAngle(ang0)
|
||||
|
||||
self.LHIKAnimation = nil
|
||||
self.CrosshairDelta = 0
|
||||
|
||||
self:SetBurstCount(0)
|
||||
|
||||
self:WepSwitchCleanup()
|
||||
if game.SinglePlayer() then self:CallOnClient("WepSwitchCleanup") end
|
||||
|
||||
if !self:GetOwner():InVehicle() then -- Don't play anim if in vehicle. This can be caused by HL2 level changes
|
||||
local prd = false
|
||||
|
||||
local r_anim = self:SelectAnimation("ready")
|
||||
local d_anim = self:SelectAnimation("draw")
|
||||
|
||||
if (CLIENT and !game.SinglePlayer() and LocalPlayer():IsListenServerHost()) then
|
||||
self.ReadySoundTableHack = true
|
||||
end
|
||||
|
||||
if self.Animations[r_anim] and ( dev_alwaysready:GetBool() or self.UnReady ) then
|
||||
self:PlayAnimation(r_anim, 1, true, 0, false)
|
||||
prd = self.Animations[r_anim].ProcDraw
|
||||
|
||||
self:SetPriorityAnim(CurTime() + self:GetAnimKeyTime(r_anim, true))
|
||||
|
||||
if CLIENT then
|
||||
self:SetTimer(self:GetAnimKeyTime(r_anim, true), function() self.UnReady = false end, "UnReady")
|
||||
end
|
||||
elseif self.Animations[d_anim] then
|
||||
self:PlayAnimation(d_anim, self:GetBuff_Mult("Mult_DrawTime"), true, 0, false)
|
||||
prd = self.Animations[d_anim].ProcDraw
|
||||
|
||||
self:SetPriorityAnim(CurTime() + self:GetAnimKeyTime(d_anim, true) * self:GetBuff_Mult("Mult_DrawTime"))
|
||||
end
|
||||
|
||||
if prd or (!self.Animations[r_anim] and !self.Animations[d_anim]) then
|
||||
self:ProceduralDraw()
|
||||
end
|
||||
end
|
||||
|
||||
self:SetState(ArcCW.STATE_DISABLE)
|
||||
|
||||
if (SERVER or game.SinglePlayer()) and self.UnReady then
|
||||
if SERVER then
|
||||
self:InitialDefaultClip()
|
||||
end
|
||||
self.UnReady = false
|
||||
end
|
||||
|
||||
if self:GetBuff_Override("Override_AutoReload", self.AutoReload) then
|
||||
self:RestoreAmmo()
|
||||
end
|
||||
|
||||
timer.Simple(0, function()
|
||||
if IsValid(self) then self:SetupModel(false) end
|
||||
end)
|
||||
|
||||
if SERVER then
|
||||
self:SetupShields()
|
||||
-- Networking the weapon at this time is too early - entity is not yet valid on client
|
||||
-- Also not a good idea because networking many weapons will cause mass lag (e.g. TTT round setup)
|
||||
-- Instead, make client send a request when it is valid there
|
||||
--self:NetworkWeapon()
|
||||
self:GetOwner():SetSaveValue("m_flNextAttack", 0) -- the magic fix-it-all solution for custom deploy problems including sounds
|
||||
elseif CLIENT and !self.CertainAboutAtts and !self.AttReqSent and IsValid(self:GetOwner()) then
|
||||
-- If client is aware of this weapon and it's not on the ground, ask for attachment info
|
||||
-- If it is not on a player, delay networking until it is rendered (in cl_viewmodel)
|
||||
-- print(self, "network weapon from sh_deploy")
|
||||
self.AttReqSent = true
|
||||
net.Start("arccw_rqwpnnet")
|
||||
net.WriteEntity(self)
|
||||
net.SendToServer()
|
||||
end
|
||||
|
||||
-- self:RefreshBGs()
|
||||
|
||||
self:GetBuff_Hook("Hook_OnDeploy")
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function SWEP:ResetCheckpoints()
|
||||
self.CheckpointAnimation = nil
|
||||
|
||||
if game.SinglePlayer() and SERVER then
|
||||
net.Start("arccw_sp_checkpoints")
|
||||
net.Broadcast()
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:InitialDefaultClip()
|
||||
if !self.Primary.Ammo then return end
|
||||
if engine.ActiveGamemode() == "darkrp" then return end -- DarkRP is god's second biggest mistake after gmod
|
||||
|
||||
if self:GetOwner() and self:GetOwner():IsPlayer() then
|
||||
if self:HasBottomlessClip() then
|
||||
self:SetClip1(0)
|
||||
end
|
||||
if self.ForceDefaultAmmo then
|
||||
self:GetOwner():GiveAmmo(self.ForceDefaultAmmo, self.Primary.Ammo)
|
||||
elseif engine.ActiveGamemode() != "terrortown" then
|
||||
self:GetOwner():GiveAmmo(self:GetCapacity() * ArcCW.ConVars["mult_defaultammo"]:GetInt(), self.Primary.Ammo)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:Initialize()
|
||||
if SERVER and game.SinglePlayer() and IsValid(self:GetOwner()) and self:GetOwner():IsPlayer() then
|
||||
self:CallOnClient("Initialize")
|
||||
end
|
||||
|
||||
if CLIENT then
|
||||
local class = self:GetClass()
|
||||
|
||||
if self.KillIconAlias then
|
||||
killicon.AddAlias(class, self.KillIconAlias)
|
||||
class = self.KillIconAlias
|
||||
end
|
||||
|
||||
local path = "arccw/weaponicons/" .. class
|
||||
local mat = Material(path)
|
||||
|
||||
if !mat:IsError() then
|
||||
|
||||
local tex = mat:GetTexture("$basetexture")
|
||||
if tex then
|
||||
local texpath = tex:GetName()
|
||||
killicon.Add(class, texpath, Color(255, 255, 255))
|
||||
self.WepSelectIcon = surface.GetTextureID(texpath)
|
||||
|
||||
if self.ShootEntity then
|
||||
killicon.Add(self.ShootEntity, texpath, Color(255, 255, 255))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Check for incompatibile addons once
|
||||
if LocalPlayer().ArcCW_IncompatibilityCheck != true and game.SinglePlayer() then
|
||||
LocalPlayer().ArcCW_IncompatibilityCheck = true
|
||||
|
||||
local incompatList = {}
|
||||
local addons = engine.GetAddons()
|
||||
for _, addon in pairs(addons) do
|
||||
if ArcCW.IncompatibleAddons[tostring(addon.wsid)] and addon.mounted then
|
||||
incompatList[tostring(addon.wsid)] = addon
|
||||
end
|
||||
end
|
||||
|
||||
local predrawvmhooks = hook.GetTable().PreDrawViewModel
|
||||
if predrawvmhooks and (predrawvmhooks.DisplayDistancePlaneLS or predrawvmhooks.DisplayDistancePlane) then -- vtools lua breaks arccw with stupid return in vm hook, ya dont need it if you going to play with guns
|
||||
hook.Remove("PreDrawViewModel", "DisplayDistancePlane")
|
||||
hook.Remove("PreDrawViewModel", "DisplayDistancePlaneLS")
|
||||
incompatList["DisplayDistancePlane"] = {
|
||||
title = "Light Sprayer / Scenic Dispenser tool",
|
||||
wsid = "DisplayDistancePlane",
|
||||
nourl = true,
|
||||
}
|
||||
end
|
||||
local shouldDo = true
|
||||
-- If never show again is on, verify we have no new addons
|
||||
if file.Exists("arccw_incompatible.txt", "DATA") then
|
||||
shouldDo = false
|
||||
local oldTbl = util.JSONToTable(file.Read("arccw_incompatible.txt"))
|
||||
for id, addon in pairs(incompatList) do
|
||||
if !oldTbl[id] then shouldDo = true break end
|
||||
end
|
||||
if shouldDo then file.Delete("arccw_incompatible.txt") end
|
||||
end
|
||||
if shouldDo and !table.IsEmpty(incompatList) then
|
||||
ArcCW.MakeIncompatibleWindow(incompatList)
|
||||
elseif !table.IsEmpty(incompatList) then
|
||||
print("ArcCW ignored " .. table.Count(incompatList) .. " incompatible addons. If things break, it's your fault.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if ArcCW.ConVars["equipmentsingleton"]:GetBool() and self.Throwing then
|
||||
self.Singleton = true
|
||||
self.Primary.ClipSize = -1
|
||||
self.Primary.Ammo = ""
|
||||
end
|
||||
|
||||
self:SetState(0)
|
||||
self:SetClip2(0)
|
||||
self:SetLastLoad(self:Clip1())
|
||||
|
||||
self.Attachments["BaseClass"] = nil
|
||||
|
||||
if !self:GetOwner():IsNPC() then
|
||||
self:SetHoldType(self.HoldtypeActive)
|
||||
end
|
||||
|
||||
local og = weapons.Get(self:GetClass())
|
||||
|
||||
self.RegularClipSize = og.Primary.ClipSize
|
||||
|
||||
self.OldPrintName = self.PrintName
|
||||
|
||||
self:InitTimers()
|
||||
|
||||
if engine.ActiveGamemode() == "terrortown" then
|
||||
self:TTT_Init()
|
||||
end
|
||||
|
||||
hook.Run("ArcCW_WeaponInit", self)
|
||||
|
||||
if (!IsValid(self:GetOwner()) or self:GetOwner():IsNPC()) and self:IsValid() and self.NPC_Initialize then
|
||||
self:NPC_Initialize()
|
||||
else
|
||||
self:AdjustAtts()
|
||||
self:RefreshBGs()
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:Holster(wep)
|
||||
if !IsFirstTimePredicted() then return end
|
||||
if self:GetOwner():IsNPC() then return end
|
||||
|
||||
if CLIENT and self:GetOwner() == LocalPlayer() and ArcCW.InvHUD then ArcCW.InvHUD:Remove() end
|
||||
|
||||
if self:GetBurstCount() > 0 and self:Clip1() > self:GetBuff("AmmoPerShot") then return false end
|
||||
|
||||
if CLIENT and LocalPlayer() != self:GetOwner() then
|
||||
return
|
||||
end
|
||||
|
||||
if self:GetGrenadePrimed() then
|
||||
self:GrenadeDrop(true)
|
||||
end
|
||||
|
||||
self:WepSwitchCleanup()
|
||||
if game.SinglePlayer() then self:CallOnClient("WepSwitchCleanup") end
|
||||
|
||||
if wep == self then self:Deploy() return false end
|
||||
if self:GetHolster_Time() > CurTime() then return false end
|
||||
|
||||
self.UnReady = false
|
||||
|
||||
-- Props deploy to NULL, finish holster on NULL too
|
||||
if (self:GetHolster_Time() != 0 and self:GetHolster_Time() <= CurTime()) or !IsValid(wep) then
|
||||
self:SetHolster_Time(0)
|
||||
self:SetHolster_Entity(NULL)
|
||||
self:FinishHolster()
|
||||
self:GetBuff_Hook("Hook_OnHolsterEnd")
|
||||
return true
|
||||
else
|
||||
self:SetHolster_Entity(wep)
|
||||
|
||||
if self:GetGrenadePrimed() then
|
||||
self:Throw()
|
||||
end
|
||||
|
||||
self.Sighted = false
|
||||
self.Sprinted = false
|
||||
self:SetShotgunReloading(0)
|
||||
self:SetMagUpCount(0)
|
||||
self:SetMagUpIn(0)
|
||||
|
||||
local time = 0.25
|
||||
local anim = self:SelectAnimation("holster")
|
||||
if anim then
|
||||
local prd = self.Animations[anim].ProcHolster
|
||||
time = self:GetAnimKeyTime(anim)
|
||||
if prd then
|
||||
self:ProceduralHolster()
|
||||
time = 0.25
|
||||
end
|
||||
self:PlayAnimation(anim, self:GetBuff_Mult("Mult_DrawTime"), true, nil, nil, nil, true)
|
||||
self:SetHolster_Time(CurTime() + time * self:GetBuff_Mult("Mult_DrawTime"))
|
||||
else
|
||||
self:ProceduralHolster()
|
||||
self:SetHolster_Time(CurTime() + time * self:GetBuff_Mult("Mult_DrawTime"))
|
||||
end
|
||||
self:SetPriorityAnim(CurTime() + time * self:GetBuff_Mult("Mult_DrawTime"))
|
||||
self:SetWeaponOpDelay(CurTime() + time * self:GetBuff_Mult("Mult_DrawTime"))
|
||||
|
||||
self:GetBuff_Hook("Hook_OnHolster")
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:FinishHolster()
|
||||
self:KillTimers()
|
||||
|
||||
if CLIENT then
|
||||
self:KillFlashlights()
|
||||
else
|
||||
if self:GetBuff_Override("UBGL_UnloadOnDequip") then
|
||||
local clip = self:Clip2()
|
||||
|
||||
local ammo = self:GetBuff_Override("UBGL_Ammo") or "smg1_grenade"
|
||||
|
||||
if IsValid(self:GetOwner()) then
|
||||
self:GetOwner():GiveAmmo(clip, ammo, true)
|
||||
end
|
||||
|
||||
self:SetClip2(0)
|
||||
end
|
||||
|
||||
self:KillShields()
|
||||
|
||||
local vm = self:GetOwner():GetViewModel()
|
||||
if IsValid(vm) then
|
||||
for i = 0, vm:GetNumBodyGroups() do
|
||||
vm:SetBodygroup(i, 0)
|
||||
end
|
||||
vm:SetSkin(0)
|
||||
vm:SetPlaybackRate(1)
|
||||
end
|
||||
|
||||
if self.Disposable and self:Clip1() == 0 and self:Ammo1() == 0 then
|
||||
self:GetOwner():StripWeapon(self:GetClass())
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- doesn't work if they dont call in prediction blah blah
|
||||
|
||||
function SWEP:ProceduralDraw()
|
||||
if SERVER and self:GetOwner():IsValid() then
|
||||
self:CallOnClient("ProceduralDraw")
|
||||
end
|
||||
|
||||
self.InProcDraw = true
|
||||
self.ProcDrawTime = CurTime()
|
||||
end
|
||||
|
||||
function SWEP:ProceduralHolster()
|
||||
if SERVER and self:GetOwner():IsValid() then
|
||||
self:CallOnClient("ProceduralHolster")
|
||||
end
|
||||
|
||||
self.InProcHolster = true
|
||||
self.ProcHolsterTime = CurTime()
|
||||
end
|
||||
|
||||
function SWEP:WepSwitchCleanup()
|
||||
-- table.Empty(self.EventTable)
|
||||
self.InProcDraw = false
|
||||
self.InProcHolster = false
|
||||
end
|
||||
|
||||
function SWEP:ProceduralBash()
|
||||
if game.SinglePlayer() and self:GetOwner():IsValid() then
|
||||
self:CallOnClient("ProceduralBash")
|
||||
end
|
||||
|
||||
local mult = self:GetBuff_Mult("Mult_MeleeTime")
|
||||
local mt = self.MeleeTime * mult
|
||||
|
||||
self.InProcBash = true
|
||||
self.ProcBashTime = CurTime()
|
||||
self:SetTimer(mt, function()
|
||||
self.InProcBash = false
|
||||
end)
|
||||
end
|
||||
174
lua/weapons/arccw_base/sh_firemodes.lua
Normal file
174
lua/weapons/arccw_base/sh_firemodes.lua
Normal file
@@ -0,0 +1,174 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
function SWEP:ChangeFiremode(pred)
|
||||
pred = pred or true
|
||||
local fmt = self:GetBuff_Override("Override_Firemodes", self.Firemodes)
|
||||
fmt["BaseClass"] = nil
|
||||
|
||||
local check = self:GetBuff_Hook("Hook_ChangeFiremode")
|
||||
if check then return end
|
||||
local count = table.Count(fmt)
|
||||
if count == 1 then return end
|
||||
if self:GetNextPrimaryFire() > CurTime() then return end
|
||||
if self:GetGrenadePrimed() then return end
|
||||
|
||||
local fmi = self:GetFireMode()
|
||||
local lastfmi = fmi
|
||||
|
||||
fmi = fmi + 1
|
||||
|
||||
if fmi > count then
|
||||
fmi = 1
|
||||
end
|
||||
|
||||
local altsafety = SERVER and (self:GetOwner():GetInfo("arccw_altsafety") == "1") or CLIENT and (ArcCW.ConVars["altsafety"]:GetBool())
|
||||
if altsafety and !self:GetOwner():KeyDown(IN_WALK) and fmt[fmi] and fmt[fmi].Mode == 0 then
|
||||
-- Skip safety when walk key is not down
|
||||
fmi = (fmi + 1 > count) and 1 or (fmi + 1)
|
||||
elseif altsafety and self:GetOwner():KeyDown(IN_WALK) then
|
||||
if fmt[lastfmi] and fmt[lastfmi].Mode == 0 then
|
||||
-- Find the first non-safety firemode
|
||||
local nonsafe_fmi = nil
|
||||
for i, fm in pairs(fmt) do
|
||||
if fm.Mode != 0 then nonsafe_fmi = i break end
|
||||
end
|
||||
fmi = nonsafe_fmi or fmi
|
||||
else
|
||||
-- Find the safety firemode
|
||||
local safety_fmi = nil
|
||||
for i, fm in pairs(fmt) do
|
||||
if fm.Mode == 0 then safety_fmi = i break end
|
||||
end
|
||||
fmi = safety_fmi or fmi
|
||||
end
|
||||
end
|
||||
|
||||
if !fmt[fmi] then fmi = 1 end
|
||||
|
||||
local a = tostring(lastfmi) .. "_to_" .. tostring(fmi)
|
||||
|
||||
if !self.Animations[a] then a = "changefiremode" end
|
||||
|
||||
if self.Animations[a] then
|
||||
self:PlayAnimationEZ(a, 1, true)
|
||||
local t = CurTime() + self:GetAnimKeyTime(a, true)
|
||||
self:SetPriorityAnim(t)
|
||||
self:SetNextPrimaryFire(t)
|
||||
end
|
||||
|
||||
local old_inf = self:HasInfiniteAmmo()
|
||||
|
||||
self:SetFireMode(fmi)
|
||||
--timer.Simple(0, function() self:RecalcAllBuffs() end)
|
||||
-- Absolutely, totally, completely ENSURE client has changed the value before attempting recalculation
|
||||
-- Waiting one tick will not work on dedicated servers
|
||||
local id = "ArcCW_RecalcWait_" .. self:EntIndex()
|
||||
timer.Create(id, 0.01, 0, function()
|
||||
if !IsValid(self) then timer.Remove(id) return end
|
||||
if self:GetFireMode() == fmi then
|
||||
self:RecalcAllBuffs()
|
||||
self:GetActiveElements(true)
|
||||
|
||||
-- Timers solve everything!
|
||||
timer.Simple(0.01, function()
|
||||
if !IsValid(self) then return end
|
||||
self:AdjustAmmo(old_inf)
|
||||
if self:GetCurrentFiremode().RestoreAmmo then
|
||||
-- No seriously, they really do
|
||||
timer.Simple(0.01, function()
|
||||
if !IsValid(self) then return end
|
||||
self:RestoreAmmo()
|
||||
end)
|
||||
end
|
||||
end)
|
||||
timer.Remove(id)
|
||||
end
|
||||
end)
|
||||
|
||||
if lastfmi != fmi then
|
||||
local snd = self:GetBuff_Override("Override_FiremodeSound", self.FiremodeSound)
|
||||
if SERVER then
|
||||
if pred then
|
||||
SuppressHostEvents(self:GetOwner())
|
||||
end
|
||||
self:MyEmitSound(snd, 75, 100, 1, CHAN_ITEM + 2)
|
||||
if pred then
|
||||
SuppressHostEvents(NULL)
|
||||
end
|
||||
else
|
||||
self:MyEmitSound(snd, 75, 100, 1, CHAN_ITEM + 2)
|
||||
end
|
||||
end
|
||||
|
||||
self:SetShouldHoldType()
|
||||
|
||||
if self:GetCurrentFiremode().Mode == 0 or self:GetBuff_Hook("Hook_ShouldNotSight") then
|
||||
self:ExitSights()
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:GetCurrentFiremode()
|
||||
local fmt = self:GetBuff_Override("Override_Firemodes", self.Firemodes)
|
||||
fmt.BaseClass = nil
|
||||
|
||||
if self:GetFireMode() > table.Count(fmt) or self:GetFireMode() < 1 then
|
||||
self:SetFireMode(1)
|
||||
end
|
||||
|
||||
fmt[self:GetFireMode()].BaseClass = nil
|
||||
return fmt[self:GetFireMode()]
|
||||
end
|
||||
|
||||
function SWEP:GetFiremodeName()
|
||||
if self:GetBuff_Hook("Hook_FiremodeName") then return self:GetBuff_Hook("Hook_FiremodeName") end
|
||||
|
||||
local abbrev = ArcCW.ConVars["hud_fcgabbrev"]:GetBool() and ".abbrev" or ""
|
||||
|
||||
if self:GetInUBGL() then
|
||||
return self:GetBuff_Override("UBGL_PrintName") and self:GetBuff_Override("UBGL_PrintName") or ArcCW.GetTranslation("fcg.ubgl" .. abbrev)
|
||||
end
|
||||
|
||||
local fm = self:GetCurrentFiremode()
|
||||
|
||||
if fm.PrintName then
|
||||
local phrase = ArcCW.GetPhraseFromString(fm.PrintName)
|
||||
return phrase and ArcCW.GetTranslation(phrase .. abbrev) or ArcCW.TryTranslation(fm.PrintName)
|
||||
end
|
||||
|
||||
local mode = fm.Mode
|
||||
if mode == 0 then return ArcCW.GetTranslation("fcg.safe" .. abbrev) end
|
||||
if mode == 1 then return ArcCW.GetTranslation("fcg.semi" .. abbrev) end
|
||||
if mode >= 2 then return ArcCW.GetTranslation("fcg.auto" .. abbrev) end
|
||||
if mode < 0 then return string.format(ArcCW.GetTranslation("fcg.burst" .. abbrev), tostring(-mode)) end
|
||||
end
|
||||
|
||||
function SWEP:GetFiremodeBars()
|
||||
if self:GetBuff_Hook("Hook_FiremodeBars") then return self:GetBuff_Hook("Hook_FiremodeBars") end
|
||||
|
||||
if self:GetInUBGL() then
|
||||
return "____-"
|
||||
end
|
||||
|
||||
local fm = self:GetCurrentFiremode()
|
||||
|
||||
if fm.CustomBars then return fm.CustomBars end
|
||||
|
||||
local mode = fm.Mode
|
||||
|
||||
if mode == 0 then return "_____" end
|
||||
if mode == 1 then return "-____" end
|
||||
if mode >= 2 then return "-----" end
|
||||
if mode == -2 then return "--___" end
|
||||
if mode == -3 then return "---__" end
|
||||
if mode == -4 then return "----_" end
|
||||
|
||||
return "-----"
|
||||
end
|
||||
923
lua/weapons/arccw_base/sh_firing.lua
Normal file
923
lua/weapons/arccw_base/sh_firing.lua
Normal file
@@ -0,0 +1,923 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
function SWEP:CanPrimaryAttack()
|
||||
local owner = self:GetOwner()
|
||||
|
||||
-- Should we not fire? But first.
|
||||
if self:GetBuff_Hook("Hook_ShouldNotFireFirst") then return end
|
||||
|
||||
-- We're holstering
|
||||
if IsValid(self:GetHolster_Entity()) then return end
|
||||
if self:GetHolster_Time() > 0 then return end
|
||||
|
||||
-- Disabled (currently used only by deploy)
|
||||
if self:GetState() == ArcCW.STATE_DISABLE then return end
|
||||
|
||||
-- Coostimzing
|
||||
if self:GetState() == ArcCW.STATE_CUSTOMIZE then
|
||||
if CLIENT and ArcCW.Inv_Hidden then
|
||||
ArcCW.Inv_Hidden = false
|
||||
gui.EnableScreenClicker(true)
|
||||
elseif game.SinglePlayer() then
|
||||
-- Kind of ugly hack: in SP this is only called serverside so we ask client to do the same check
|
||||
self:CallOnClient("CanPrimaryAttack")
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- A priority animation is playing (reloading, cycling, firemode etc)
|
||||
if self:GetPriorityAnim() then return end
|
||||
|
||||
-- Inoperable, but internally (burst resetting for example)
|
||||
if self:GetWeaponOpDelay() > CurTime() then return end
|
||||
|
||||
-- Safety's on, dipshit
|
||||
if self:GetCurrentFiremode().Mode == 0 then
|
||||
self:ChangeFiremode(false)
|
||||
self:SetNextPrimaryFire(CurTime())
|
||||
self.Primary.Automatic = false
|
||||
return
|
||||
end
|
||||
|
||||
-- If we are an NPC, do our own little methods
|
||||
if owner:IsNPC() then self:NPC_Shoot() return end
|
||||
|
||||
-- If we are in a UBGL, shoot the UBGL, not the gun
|
||||
if self:GetInUBGL() then self:ShootUBGL() return end
|
||||
|
||||
-- Too early, come back later.
|
||||
if self:GetNextPrimaryFire() >= CurTime() then return end
|
||||
|
||||
-- Gun is locked from heat.
|
||||
if self:GetHeatLocked() then return end
|
||||
|
||||
-- Attempting a bash
|
||||
if self:GetState() != ArcCW.STATE_SIGHTS and owner:KeyDown(IN_USE) or self.PrimaryBash then self:Bash() return end
|
||||
|
||||
-- Throwing weapon
|
||||
if self.Throwing then self:PreThrow() return end
|
||||
|
||||
-- Too close to a wall
|
||||
if self:BarrelHitWall() > 0 then return end
|
||||
|
||||
-- Can't shoot while sprinting
|
||||
if self:GetNWState() == ArcCW.STATE_SPRINT and !self:CanShootWhileSprint() then return end
|
||||
|
||||
-- Maximum burst shots
|
||||
if (self:GetBurstCount() or 0) >= self:GetBurstLength() then return end
|
||||
|
||||
-- We need to cycle
|
||||
if self:GetNeedCycle() then return end
|
||||
|
||||
-- If we have a trigger delay, make sure its progress is done
|
||||
if self:GetBuff_Override("Override_TriggerDelay", self.TriggerDelay) and ((!self:GetBuff_Override("Override_TriggerCharge", self.TriggerCharge) and self:GetTriggerDelta() < 1)
|
||||
or (self:GetBuff_Override("Override_TriggerCharge", self.TriggerCharge) and self:IsTriggerHeld())) then
|
||||
return
|
||||
end
|
||||
|
||||
-- Should we not fire?
|
||||
if self:GetBuff_Hook("Hook_ShouldNotFire") then return end
|
||||
|
||||
-- We made it
|
||||
return true
|
||||
end
|
||||
|
||||
function SWEP:TakePrimaryAmmo(num)
|
||||
if self:HasBottomlessClip() or self:Clip1() <= 0 then
|
||||
if self:Ammo1() <= 0 then return end
|
||||
if self:HasInfiniteAmmo() then return end
|
||||
self:GetOwner():RemoveAmmo(num, self:GetPrimaryAmmoType())
|
||||
return end
|
||||
self:SetClip1(self:Clip1() - num)
|
||||
end
|
||||
|
||||
function SWEP:ApplyRandomSpread(dir, spread)
|
||||
local radius = math.Rand(0, 1)
|
||||
local theta = math.Rand(0, math.rad(360))
|
||||
local bulletang = dir:Angle()
|
||||
local forward, right, up = bulletang:Forward(), bulletang:Right(), bulletang:Up()
|
||||
local x = radius * math.sin(theta)
|
||||
local y = radius * math.cos(theta)
|
||||
|
||||
dir:Set(dir + right * spread * x + up * spread * y)
|
||||
end
|
||||
|
||||
function SWEP:PrimaryAttack()
|
||||
local owner = self:GetOwner()
|
||||
|
||||
self.Primary.Automatic = true
|
||||
|
||||
if !self:CanPrimaryAttack() then return end
|
||||
|
||||
local clip = self:Clip1()
|
||||
local aps = self:GetBuff("AmmoPerShot")
|
||||
|
||||
if self:HasBottomlessClip() then
|
||||
clip = self:Ammo1()
|
||||
if self:HasInfiniteAmmo() then
|
||||
clip = math.huge
|
||||
end
|
||||
end
|
||||
|
||||
if clip < aps then
|
||||
self:SetBurstCount(0)
|
||||
self:DryFire()
|
||||
|
||||
self.Primary.Automatic = false
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
local dir = (owner:EyeAngles() + self:GetFreeAimOffset()):Forward() --owner:GetAimVector()
|
||||
local src = self:GetShootSrc()
|
||||
|
||||
if bit.band(util.PointContents(src), CONTENTS_WATER) == CONTENTS_WATER and !(self.CanFireUnderwater or self:GetBuff_Override("Override_CanFireUnderwater")) then
|
||||
self:DryFire()
|
||||
return
|
||||
end
|
||||
|
||||
if self:GetMalfunctionJam() then
|
||||
self:DryFire()
|
||||
return
|
||||
end
|
||||
|
||||
-- Try malfunctioning
|
||||
local mal = self:DoMalfunction(false)
|
||||
if mal == true then
|
||||
local anim = "fire_jammed"
|
||||
self:PlayAnimation(anim, 1, true, 0, true)
|
||||
return
|
||||
end
|
||||
|
||||
self:GetBuff_Hook("Hook_PreFireBullets")
|
||||
|
||||
local desync = ArcCW.ConVars["desync"]:GetBool()
|
||||
local desyncnum = (desync and math.random()) or 0
|
||||
math.randomseed(math.Round(util.SharedRandom(self:GetBurstCount(), -1337, 1337, !game.SinglePlayer() and self:GetOwner():GetCurrentCommand():CommandNumber() or CurTime()) * (self:EntIndex() % 30241)) + desyncnum)
|
||||
|
||||
self.Primary.Automatic = true
|
||||
|
||||
local spread = ArcCW.MOAToAcc * self:GetBuff("AccuracyMOA")
|
||||
local disp = self:GetDispersion() * ArcCW.MOAToAcc / 10
|
||||
|
||||
--dir:Rotate(Angle(0, ArcCW.StrafeTilt(self), 0))
|
||||
--dir = dir + VectorRand() * disp
|
||||
|
||||
self:ApplyRandomSpread(dir, disp)
|
||||
|
||||
if (CLIENT or game.SinglePlayer()) and ArcCW.ConVars["dev_shootinfo"]:GetInt() >= 3 and disp > 0 then
|
||||
local dev_tr = util.TraceLine({
|
||||
start = src,
|
||||
endpos = src + owner:GetAimVector() * 33000,
|
||||
mask = MASK_SHOT,
|
||||
filter = {self, self:GetOwner()}
|
||||
})
|
||||
local dist = (dev_tr.HitPos - src):Length()
|
||||
local r = dist / (1 / math.tan(disp)) -- had to google "trig cheat sheet to figure this one out"
|
||||
local a = owner:GetAimVector():Angle()
|
||||
local r_sqrt = r / math.sqrt(2)
|
||||
debugoverlay.Line(dev_tr.HitPos - a:Up() * r, dev_tr.HitPos + a:Up() * r, 5, color_white, true)
|
||||
debugoverlay.Line(dev_tr.HitPos - a:Right() * r, dev_tr.HitPos + a:Right() * r, 5, color_white, true)
|
||||
debugoverlay.Line(dev_tr.HitPos - a:Right() * r_sqrt - a:Up() * r_sqrt, dev_tr.HitPos + a:Right() * r_sqrt + a:Up() * r_sqrt, 5, color_white, true)
|
||||
debugoverlay.Line(dev_tr.HitPos - a:Right() * r_sqrt + a:Up() * r_sqrt, dev_tr.HitPos + a:Right() * r_sqrt - a:Up() * r_sqrt, 5, color_white, true)
|
||||
debugoverlay.Text(dev_tr.HitPos, math.Round(self:GetDispersion(), 1) .. "MOA (" .. math.Round(disp, 3) .. "°)", 5)
|
||||
end
|
||||
|
||||
local delay = self:GetFiringDelay()
|
||||
|
||||
local curtime = CurTime()
|
||||
local curatt = self:GetNextPrimaryFire()
|
||||
local diff = curtime - curatt
|
||||
|
||||
if diff > engine.TickInterval() or diff < 0 then
|
||||
curatt = curtime
|
||||
end
|
||||
|
||||
self:SetNextPrimaryFire(curatt + delay)
|
||||
self:SetNextPrimaryFireSlowdown(curatt + delay) -- shadow for ONLY fire time
|
||||
|
||||
local num = self:GetBuff("Num")
|
||||
|
||||
num = num + self:GetBuff_Add("Add_Num")
|
||||
|
||||
local tracer = self:GetBuff_Override("Override_Tracer", self.Tracer)
|
||||
local tracernum = self:GetBuff_Override("Override_TracerNum", self.TracerNum)
|
||||
local lastout = self:GetBuff_Override("Override_TracerFinalMag", self.TracerFinalMag)
|
||||
if lastout >= clip then
|
||||
tracernum = 1
|
||||
tracer = self:GetBuff_Override("Override_TracerFinal", self.TracerFinal) or self:GetBuff_Override("Override_Tracer", self.Tracer)
|
||||
end
|
||||
local dmgtable = self.BodyDamageMults
|
||||
dmgtable = self:GetBuff_Override("Override_BodyDamageMults") or dmgtable
|
||||
|
||||
-- drive by is cool
|
||||
src = ArcCW:GetVehicleFireTrace(self:GetOwner(), src, dir) or src
|
||||
|
||||
local bullet = {}
|
||||
bullet.Attacker = owner
|
||||
bullet.Dir = dir
|
||||
bullet.Src = src
|
||||
bullet.Spread = Vector(0, 0, 0) --Vector(spread, spread, spread)
|
||||
bullet.Damage = 0
|
||||
bullet.Num = num
|
||||
|
||||
local sglove = math.ceil(num / 3)
|
||||
bullet.Force = self:GetBuff("Force", true) or math.Clamp( ( (50 / sglove) / ( (self:GetBuff("Damage") + self:GetBuff("DamageMin")) / (self:GetBuff("Num") * 2) ) ) * sglove, 1, 3 )
|
||||
-- Overperforming weapons get the jerf, underperforming gets boost
|
||||
bullet.Distance = self:GetBuff("Distance", true) or 33300
|
||||
-- Setting AmmoType makes the engine look for the tracer effect on the ammo instead of TracerName!
|
||||
--bullet.AmmoType = self.Primary.Ammo
|
||||
bullet.HullSize = self:GetBuff("HullSize")
|
||||
bullet.Tracer = tracernum or 0
|
||||
bullet.TracerName = tracer
|
||||
bullet.Weapon = self
|
||||
bullet.Callback = function(att, tr, dmg)
|
||||
ArcCW:BulletCallback(att, tr, dmg, self)
|
||||
end
|
||||
|
||||
local shootent = self:GetBuff("ShootEntity", true) --self:GetBuff_Override("Override_ShootEntity", self.ShootEntity)
|
||||
local shpatt = self:GetBuff_Override("Override_ShotgunSpreadPattern", self.ShotgunSpreadPattern)
|
||||
local shpattov = self:GetBuff_Override("Override_ShotgunSpreadPatternOverrun", self.ShotgunSpreadPatternOverrun)
|
||||
|
||||
local extraspread = AngleRand() * self:GetDispersion() * ArcCW.MOAToAcc / 10
|
||||
|
||||
local projectiledata = {}
|
||||
|
||||
if shpatt or shpattov or shootent then
|
||||
if shootent then
|
||||
projectiledata.ent = shootent
|
||||
projectiledata.vel = self:GetBuff("MuzzleVelocity")
|
||||
end
|
||||
|
||||
bullet = self:GetBuff_Hook("Hook_FireBullets", bullet)
|
||||
|
||||
if !bullet then return end
|
||||
|
||||
local doent = shootent and num or bullet.Num
|
||||
local minnum = shootent and 1 or 0
|
||||
|
||||
if doent > minnum then
|
||||
for n = 1, bullet.Num do
|
||||
bullet.Num = 1
|
||||
|
||||
local dispers = self:GetBuff_Override("Override_ShotgunSpreadDispersion", self.ShotgunSpreadDispersion)
|
||||
local offset = self:GetShotgunSpreadOffset(n)
|
||||
local calcoff = dispers and (offset * self:GetDispersion() * ArcCW.MOAToAcc / 10) or offset
|
||||
|
||||
local ang = owner:EyeAngles() + self:GetFreeAimOffset()
|
||||
local ang2 = Angle(ang)
|
||||
ang2:RotateAroundAxis(ang:Right(), -1 * calcoff.p)
|
||||
ang2:RotateAroundAxis(ang:Up(), calcoff.y)
|
||||
ang2:RotateAroundAxis(ang:Forward(), calcoff.r)
|
||||
|
||||
if !self:GetBuff_Override("Override_NoRandSpread", self.NoRandSpread) then -- Needs testing
|
||||
ang2 = ang2 + AngleRand() * spread / 5
|
||||
end
|
||||
|
||||
if shootent then
|
||||
projectiledata.ang = ang2
|
||||
|
||||
self:DoPrimaryFire(true, projectiledata)
|
||||
else
|
||||
bullet.Dir = ang2:Forward()
|
||||
|
||||
self:DoPrimaryFire(false, bullet)
|
||||
end
|
||||
end
|
||||
elseif shootent then
|
||||
local ang = owner:EyeAngles() + self:GetFreeAimOffset()
|
||||
|
||||
if !self:GetBuff_Override("Override_NoRandSpread", self.NoRandSpread) then
|
||||
-- ang = (dir + VectorRand() * spread / 5):Angle()
|
||||
|
||||
local newdir = Vector(dir)
|
||||
self:ApplyRandomSpread(newdir, spread / 5)
|
||||
ang = newdir:Angle()
|
||||
end
|
||||
|
||||
projectiledata.ang = ang
|
||||
|
||||
self:DoPrimaryFire(true, projectiledata)
|
||||
end
|
||||
else
|
||||
if !bullet then return end
|
||||
|
||||
for n = 1, bullet.Num do
|
||||
bullet.Num = 1
|
||||
local dirry = Vector(dir.x, dir.y, dir.z)
|
||||
math.randomseed(math.Round(util.SharedRandom(n, -1337, 1337, !game.SinglePlayer() and self:GetOwner():GetCurrentCommand():CommandNumber() or CurTime()) * (self:EntIndex() % 30241)) + desyncnum)
|
||||
if !self:GetBuff_Override("Override_NoRandSpread", self.NoRandSpread) then
|
||||
self:ApplyRandomSpread(dirry, spread)
|
||||
bullet.Dir = dirry
|
||||
end
|
||||
bullet = self:GetBuff_Hook("Hook_FireBullets", bullet) or bullet
|
||||
|
||||
self:DoPrimaryFire(false, bullet)
|
||||
end
|
||||
end
|
||||
|
||||
self:DoRecoil()
|
||||
|
||||
self:SetNthShot(self:GetNthShot() + 1)
|
||||
|
||||
owner:DoAnimationEvent(self:GetBuff_Override("Override_AnimShoot") or self.AnimShoot)
|
||||
|
||||
local shouldsupp = SERVER and !game.SinglePlayer()
|
||||
|
||||
if shouldsupp then SuppressHostEvents(owner) end
|
||||
|
||||
self:DoEffects()
|
||||
|
||||
self:SetBurstCount(self:GetBurstCount() + 1)
|
||||
|
||||
self:TakePrimaryAmmo(aps)
|
||||
|
||||
self:DoShootSound()
|
||||
self:DoPrimaryAnim()
|
||||
|
||||
if self:GetCurrentFiremode().Mode < 0 and self:GetBurstCount() == self:GetBurstLength() then
|
||||
local postburst = (self:GetCurrentFiremode().PostBurstDelay or 0)
|
||||
self:SetWeaponOpDelay(CurTime() + postburst * self:GetBuff_Mult("Mult_PostBurstDelay") + self:GetBuff_Add("Add_PostBurstDelay"))
|
||||
end
|
||||
|
||||
if (self:GetIsManualAction()) and !(self.NoLastCycle and self:Clip1() == 0) then
|
||||
local fireanim = self:GetBuff_Hook("Hook_SelectFireAnimation") or self:SelectAnimation("fire")
|
||||
local firedelay = self.Animations[fireanim].MinProgress or 0
|
||||
self:SetNeedCycle(true)
|
||||
self:SetWeaponOpDelay(CurTime() + (firedelay * self:GetBuff_Mult("Mult_CycleTime")))
|
||||
self:SetNextPrimaryFire(CurTime() + 0.1)
|
||||
end
|
||||
|
||||
self:ApplyAttachmentShootDamage()
|
||||
|
||||
self:AddHeat(self:GetBuff("HeatGain"))
|
||||
|
||||
mal = self:DoMalfunction(true)
|
||||
if mal == true then
|
||||
local anim = "fire_jammed"
|
||||
self:PlayAnimation(anim, 1, true, 0, true)
|
||||
end
|
||||
|
||||
if self:GetCurrentFiremode().Mode == 1 then
|
||||
self.LastTriggerTime = -1 -- Cannot fire again until trigger released
|
||||
self.LastTriggerDuration = 0
|
||||
end
|
||||
|
||||
self:GetBuff_Hook("Hook_PostFireBullets")
|
||||
|
||||
if shouldsupp then SuppressHostEvents(nil) end
|
||||
end
|
||||
|
||||
function SWEP:TryBustDoor(ent, dmg)
|
||||
ArcCW.TryBustDoor(ent, dmg)
|
||||
end
|
||||
|
||||
function SWEP:DoShootSound(sndoverride, dsndoverride, voloverride, pitchoverride)
|
||||
local fsound = self.ShootSound
|
||||
local suppressed = self:GetBuff_Override("Silencer")
|
||||
|
||||
if suppressed then
|
||||
fsound = self.ShootSoundSilenced
|
||||
end
|
||||
|
||||
local firstsound = self.FirstShootSound
|
||||
|
||||
if self:GetBurstCount() == 1 and firstsound then
|
||||
fsound = firstsound
|
||||
|
||||
local firstsil = self.FirstShootSoundSilenced
|
||||
|
||||
if suppressed then
|
||||
fsound = firstsil and firstsil or self.ShootSoundSilenced
|
||||
end
|
||||
end
|
||||
|
||||
local lastsound = self.LastShootSound
|
||||
|
||||
local clip = self:Clip1()
|
||||
|
||||
if clip == 1 and lastsound then
|
||||
fsound = lastsound
|
||||
|
||||
local lastsil = self.LastShootSoundSilenced
|
||||
|
||||
if suppressed then
|
||||
fsound = lastsil and lastsil or self.ShootSoundSilenced
|
||||
end
|
||||
end
|
||||
|
||||
fsound = self:GetBuff_Hook("Hook_GetShootSound", fsound)
|
||||
|
||||
local distancesound = self.DistantShootSound
|
||||
|
||||
if suppressed then
|
||||
distancesound = self.DistantShootSoundSilenced
|
||||
end
|
||||
|
||||
distancesound = self:GetBuff_Hook("Hook_GetDistantShootSound", distancesound)
|
||||
|
||||
local spv = self.ShootPitchVariation
|
||||
local volume = self.ShootVol
|
||||
local pitch = self.ShootPitch * math.Rand(1 - spv, 1 + spv) * self:GetBuff_Mult("Mult_ShootPitch")
|
||||
|
||||
local v = ArcCW.ConVars["weakensounds"]:GetFloat()
|
||||
|
||||
volume = volume - v
|
||||
|
||||
volume = volume * self:GetBuff_Mult("Mult_ShootVol")
|
||||
|
||||
volume = math.Clamp(volume, 51, 149)
|
||||
pitch = math.Clamp(pitch, 0, 255)
|
||||
|
||||
if sndoverride then fsound = sndoverride end
|
||||
if dsndoverride then distancesound = dsndoverride end
|
||||
if voloverride then volume = voloverride end
|
||||
if pitchoverride then pitch = pitchoverride end
|
||||
|
||||
if distancesound then self:MyEmitSound(distancesound, 149, pitch, 0.5, CHAN_WEAPON + 1) end
|
||||
|
||||
if fsound then self:MyEmitSound(fsound, volume, pitch, 1, CHAN_WEAPON) end
|
||||
|
||||
local data = {
|
||||
sound = fsound,
|
||||
volume = volume,
|
||||
pitch = pitch,
|
||||
}
|
||||
|
||||
self:GetBuff_Hook("Hook_AddShootSound", data)
|
||||
end
|
||||
|
||||
function SWEP:GetMuzzleVelocity()
|
||||
local vel = self:GetBuff_Override("Override_PhysBulletMuzzleVelocity", self.PhysBulletMuzzleVelocity)
|
||||
|
||||
if !vel then
|
||||
vel = self:GetBuff("Range") * 3.5
|
||||
|
||||
if self:GetBuff("DamageMin") > self:GetBuff("Damage") then
|
||||
vel = vel * 2
|
||||
end
|
||||
vel = math.Clamp(vel, 200, 1000)
|
||||
end
|
||||
|
||||
vel = vel / ArcCW.HUToM
|
||||
|
||||
vel = vel * self:GetBuff_Mult("Mult_PhysBulletMuzzleVelocity")
|
||||
|
||||
vel = vel * ArcCW.ConVars["bullet_velocity"]:GetFloat()
|
||||
|
||||
return vel
|
||||
end
|
||||
|
||||
function SWEP:DoPrimaryFire(isent, data)
|
||||
local clip = self:Clip1()
|
||||
if self:HasBottomlessClip() then
|
||||
if !self:GetOwner():IsPlayer() then
|
||||
clip = math.huge
|
||||
else
|
||||
clip = self:Ammo1()
|
||||
end
|
||||
end
|
||||
local owner = self:GetOwner()
|
||||
|
||||
local shouldphysical = ArcCW.ConVars["bullet_enable"]:GetBool()
|
||||
|
||||
if self.AlwaysPhysBullet or self:GetBuff_Override("Override_AlwaysPhysBullet") then
|
||||
shouldphysical = true
|
||||
end
|
||||
|
||||
if self.NeverPhysBullet or self:GetBuff_Override("Override_NeverPhysBullet") then
|
||||
shouldphysical = false
|
||||
end
|
||||
|
||||
if isent then
|
||||
self:FireRocket(data.ent, data.vel, data.ang, self.PhysBulletDontInheritPlayerVelocity)
|
||||
else
|
||||
-- if !game.SinglePlayer() and !IsFirstTimePredicted() then return end
|
||||
if !IsFirstTimePredicted() then return end
|
||||
|
||||
if shouldphysical then
|
||||
local tracernum = data.Tracer or 1
|
||||
local phystracer = self:GetBuff_Override("Override_PhysTracerProfile", self.PhysTracerProfile)
|
||||
local lastout = self:GetBuff_Override("Override_TracerFinalMag", self.TracerFinalMag)
|
||||
if lastout >= self:Clip1() then
|
||||
phystracer = self:GetBuff_Override("Override_PhysTracerProfileFinal", self.PhysTracerProfileFinal) or phystracer
|
||||
elseif tracernum == 0 or clip % tracernum != 0 then
|
||||
phystracer = 7
|
||||
end
|
||||
|
||||
local vel = self:GetMuzzleVelocity()
|
||||
|
||||
vel = vel * data.Dir:GetNormalized()
|
||||
|
||||
ArcCW:ShootPhysBullet(self, data.Src, vel, phystracer or 0)
|
||||
else
|
||||
owner:FireBullets(data, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:DoPrimaryAnim()
|
||||
local anim = "fire"
|
||||
|
||||
local inbipod = self:InBipod()
|
||||
local iron = self:GetState() == ArcCW.STATE_SIGHTS
|
||||
|
||||
-- Needs testing
|
||||
if inbipod then
|
||||
anim = self:SelectAnimation("fire_bipod") or self:SelectAnimation("fire") or anim
|
||||
else
|
||||
anim = self:SelectAnimation("fire") or anim
|
||||
end
|
||||
|
||||
if (self.ProceduralIronFire and iron) or (self.ProceduralRegularFire and !iron) then anim = nil end
|
||||
|
||||
anim = self:GetBuff_Hook("Hook_SelectFireAnimation", anim) or anim
|
||||
|
||||
local time = self:GetBuff_Mult("Mult_FireAnimTime", anim) or 1
|
||||
|
||||
if anim then self:PlayAnimation(anim, time, true, 0, false) end
|
||||
end
|
||||
|
||||
function SWEP:DoPenetration(tr, penleft, alreadypenned)
|
||||
local bullet = {
|
||||
Damage = self:GetDamage((tr.HitPos - tr.StartPos):Length() * ArcCW.HUToM),
|
||||
DamageType = self:GetBuff_Override("Override_DamageType") or self.DamageType,
|
||||
Weapon = self,
|
||||
Penetration = self:GetBuff("Penetration"),
|
||||
Attacker = self:GetOwner(),
|
||||
Travelled = (tr.HitPos - tr.StartPos):Length()
|
||||
}
|
||||
|
||||
ArcCW:DoPenetration(tr, bullet.Damage, bullet, penleft, false, alreadypenned)
|
||||
end
|
||||
|
||||
function SWEP:GetFiringDelay()
|
||||
local delay = (self.Delay * (1 / self:GetBuff_Mult("Mult_RPM")))
|
||||
delay = self:GetBuff_Hook("Hook_ModifyRPM", delay) or delay
|
||||
|
||||
return delay
|
||||
end
|
||||
|
||||
function SWEP:GetShootSrc()
|
||||
local owner = self:GetOwner()
|
||||
|
||||
if !IsValid(owner) then return self:GetPos() end
|
||||
if owner:IsNPC() then return owner:GetShootPos() end
|
||||
|
||||
local dir = owner:EyeAngles()
|
||||
local offset = Vector(0, 0, 0)
|
||||
|
||||
if self:GetOwner():Crouching() then
|
||||
offset = self:GetBuff_Override("Override_BarrelOffsetCrouch") or self.BarrelOffsetCrouch or offset
|
||||
end
|
||||
|
||||
if self:GetNWState() == ArcCW.STATE_SIGHTS then
|
||||
offset = LerpVector(self:GetNWSightDelta(), offset, self:GetBuff_Override("Override_BarrelOffsetSighted", self.BarrelOffsetSighted) or offset)
|
||||
else
|
||||
offset = LerpVector(1 - self:GetNWSightDelta(), offset, self:GetBuff_Override("Override_BarrelOffsetHip", self.BarrelOffsetHip) or offset)
|
||||
end
|
||||
|
||||
local src = owner:EyePos()
|
||||
|
||||
|
||||
src = src + dir:Right() * offset[1]
|
||||
src = src + dir:Forward() * offset[2]
|
||||
src = src + dir:Up() * offset[3]
|
||||
|
||||
return src
|
||||
end
|
||||
|
||||
function SWEP:GetShotgunSpreadOffset(num)
|
||||
local rotate = Angle()
|
||||
local spreadpt = self:GetBuff_Override("Override_ShotgunSpreadPattern") or self.ShotgunSpreadPattern or {}
|
||||
local spreadov = self:GetBuff_Override("Override_ShotgunSpreadPatternOverrun") or self.ShotgunSpreadPatternOverrun or { Angle() }
|
||||
|
||||
if istable(spreadpt) and istable(spreadov) then
|
||||
spreadpt["BaseClass"] = nil
|
||||
spreadov["BaseClass"] = nil
|
||||
|
||||
if num > #spreadpt then
|
||||
if spo then
|
||||
num = num - #spreadpt
|
||||
num = math.fmod(num, #spreadov) + 1
|
||||
rotate = spreadov[num]
|
||||
else
|
||||
num = math.fmod(num, #spreadpt) + 1
|
||||
rotate = spreadpt[num]
|
||||
end
|
||||
else
|
||||
rotate = spreadpt[num]
|
||||
end
|
||||
end
|
||||
|
||||
local rottoang = {}
|
||||
rottoang.num = num
|
||||
rottoang.ang = rotate
|
||||
|
||||
rotate = self:GetBuff_Hook("Hook_ShotgunSpreadOffset", rottoang).ang
|
||||
|
||||
return rotate or Angle()
|
||||
end
|
||||
|
||||
function SWEP:GetDispersion()
|
||||
local owner = self:GetOwner()
|
||||
|
||||
if vrmod and vrmod.IsPlayerInVR(owner) then return 0 end
|
||||
|
||||
local hipdisp = self:GetBuff("HipDispersion")
|
||||
local sights = self:GetState() == ArcCW.STATE_SIGHTS
|
||||
|
||||
local hip = hipdisp
|
||||
|
||||
local sightdisp = self:GetBuff("SightsDispersion")
|
||||
if sights then hip = Lerp(self:GetNWSightDelta(), sightdisp, hipdisp) end
|
||||
|
||||
local speed = owner:GetAbsVelocity():Length()
|
||||
local maxspeed = owner:GetWalkSpeed() * self:GetBuff("SpeedMult")
|
||||
if sights then maxspeed = maxspeed * self:GetBuff("SightedSpeedMult") end
|
||||
speed = math.Clamp(speed / maxspeed, 0, 2)
|
||||
|
||||
if owner:OnGround() or owner:WaterLevel() > 0 and owner:GetMoveType() != MOVETYPE_NOCLIP then
|
||||
hip = hip + speed * self:GetBuff("MoveDispersion")
|
||||
elseif owner:GetMoveType() != MOVETYPE_NOCLIP then
|
||||
hip = hip + math.max(speed * self:GetBuff("MoveDispersion"), self:GetBuff("JumpDispersion"))
|
||||
end
|
||||
|
||||
if self:InBipod() then hip = hip * (self.BipodDispersion * self:GetBuff_Mult("Mult_BipodDispersion")) end
|
||||
|
||||
if ArcCW.ConVars["mult_crouchdisp"]:GetFloat() != 1 and owner:OnGround() and owner:Crouching() then
|
||||
hip = hip * ArcCW.ConVars["mult_crouchdisp"]:GetFloat()
|
||||
end
|
||||
|
||||
if ArcCW.ConVars["freeaim"]:GetInt() == 1 and !sights then
|
||||
hip = hip ^ 0.9
|
||||
end
|
||||
|
||||
--local t = hook.Run("ArcCW_ModDispersion", self, {dispersion = hip})
|
||||
--hip = t and t.dispersion or hip
|
||||
hip = self:GetBuff_Hook("Hook_ModDispersion", hip) or hip
|
||||
|
||||
return hip
|
||||
end
|
||||
|
||||
function SWEP:DoShellEject(atti)
|
||||
local eff = self:GetBuff_Override("Override_ShellEffect") or self.ShellEffect or "arccw_shelleffect"
|
||||
|
||||
if eff == "NONE" then return end
|
||||
|
||||
local owner = self:GetOwner()
|
||||
|
||||
if !IsValid(owner) then return end
|
||||
|
||||
local vm = self
|
||||
|
||||
if !owner:IsNPC() then owner:GetViewModel() end
|
||||
|
||||
local att = vm:GetAttachment(atti or self:GetBuff_Override("Override_CaseEffectAttachment") or self.CaseEffectAttachment or 2)
|
||||
|
||||
if !att then return end
|
||||
|
||||
local pos, ang = att.Pos, att.Ang
|
||||
|
||||
if pos and ang and self.ShellEjectPosCorrection then
|
||||
local up = ang:Up()
|
||||
local right = ang:Right()
|
||||
local forward = ang:Forward()
|
||||
pos = pos + up * self.ShellEjectPosCorrection.z + right * self.ShellEjectPosCorrection.x + forward * self.ShellEjectPosCorrection.y
|
||||
end
|
||||
|
||||
local ed = EffectData()
|
||||
ed:SetOrigin(pos)
|
||||
ed:SetAngles(ang)
|
||||
ed:SetAttachment(atti or self:GetBuff_Override("Override_CaseEffectAttachment") or self.CaseEffectAttachment or 2)
|
||||
ed:SetScale(1)
|
||||
ed:SetEntity(self)
|
||||
ed:SetNormal(ang:Forward())
|
||||
ed:SetMagnitude(100)
|
||||
|
||||
local efov = {}
|
||||
efov.eff = eff
|
||||
efov.fx = ed
|
||||
|
||||
if self:GetBuff_Hook("Hook_PreDoEffects", efov) == true then return end
|
||||
|
||||
util.Effect(eff, ed)
|
||||
end
|
||||
|
||||
function SWEP:DoEffects(att)
|
||||
if !game.SinglePlayer() and !IsFirstTimePredicted() then return end
|
||||
|
||||
local ed = EffectData()
|
||||
ed:SetStart(self:GetShootSrc())
|
||||
ed:SetOrigin(self:GetShootSrc())
|
||||
ed:SetScale(1)
|
||||
ed:SetEntity(self)
|
||||
ed:SetAttachment(att or self:GetBuff_Override("Override_MuzzleEffectAttachment") or self.MuzzleEffectAttachment or 1)
|
||||
|
||||
local efov = {}
|
||||
efov.eff = "arccw_muzzleeffect"
|
||||
efov.fx = ed
|
||||
|
||||
if self:GetBuff_Hook("Hook_PreDoEffects", efov) == true then return end
|
||||
|
||||
util.Effect("arccw_muzzleeffect", ed)
|
||||
end
|
||||
|
||||
function SWEP:DryFire()
|
||||
|
||||
if self.Animations.fire_dry then
|
||||
return self:PlayAnimation("fire_dry", 1, true, 0, true)
|
||||
end
|
||||
self:MyEmitSound(self.ShootDrySound or "weapons/arccw/dryfire.wav", 75, 100, 1, CHAN_ITEM)
|
||||
self:SetNextPrimaryFire(CurTime() + 0.25)
|
||||
end
|
||||
|
||||
function SWEP:DoRecoil()
|
||||
local single = game.SinglePlayer()
|
||||
|
||||
if !single and !IsFirstTimePredicted() then return end
|
||||
|
||||
if single and self:GetOwner():IsValid() and SERVER then self:CallOnClient("DoRecoil") end
|
||||
|
||||
-- math.randomseed(self:GetBurstLength() + (self.Recoil * 409) + (self.RecoilSide * 519))
|
||||
|
||||
local rec = {
|
||||
Recoil = 1,
|
||||
RecoilSide = 1,
|
||||
VisualRecoilMul = 1
|
||||
}
|
||||
rec = self:GetBuff_Hook("Hook_ModifyRecoil", rec) or rec
|
||||
|
||||
local recoil = rec.Recoil
|
||||
local side = rec.RecoilSide
|
||||
local visual = rec.VisualRecoilMul
|
||||
|
||||
local rmul = (recoil or 1) * self:GetBuff_Mult("Mult_Recoil")
|
||||
local recv = (visual or 1) * self:GetBuff_Mult("Mult_VisualRecoilMult")
|
||||
local recs = (side or 1) * self:GetBuff_Mult("Mult_RecoilSide")
|
||||
|
||||
-- local rrange = math.Rand(-recs, recs) * self.RecoilSide
|
||||
|
||||
-- local irec = math.Rand(rrange - 1, rrange + 1)
|
||||
-- local recu = math.Rand(0.5, 1)
|
||||
|
||||
local irec = math.Rand(-1, 1)
|
||||
local recu = 1
|
||||
|
||||
if self:InBipod() then
|
||||
local b = self.BipodRecoil * self:GetBuff_Mult("Mult_BipodRecoil")
|
||||
|
||||
rmul = rmul * b
|
||||
recs = recs * b
|
||||
recv = recv * b
|
||||
end
|
||||
|
||||
local recoiltbl = self:GetBuff_Override("Override_ShotRecoilTable") or self.ShotRecoilTable
|
||||
|
||||
if recoiltbl and recoiltbl[self:GetBurstCount()] then rmul = rmul * recoiltbl[self:GetBurstCount()] end
|
||||
|
||||
if ArcCW.ConVars["mult_crouchrecoil"]:GetFloat() != 1 and self:GetOwner():OnGround() and self:GetOwner():Crouching() then
|
||||
rmul = rmul * ArcCW.ConVars["mult_crouchrecoil"]:GetFloat()
|
||||
end
|
||||
|
||||
local punch = Angle()
|
||||
|
||||
punch = punch + (self:GetBuff_Override("Override_RecoilDirection", self.RecoilDirection) * math.max(self.Recoil, 0.25) * recu * recv * rmul)
|
||||
punch = punch + (self:GetBuff_Override("Override_RecoilDirectionSide", self.RecoilDirectionSide) * math.max(self.RecoilSide, 0.25) * irec * recv * rmul)
|
||||
punch = punch + Angle(0, 0, 90) * math.Rand(-1, 1) * math.Clamp(self.Recoil, 0.25, 1) * recv * rmul * 0.01
|
||||
punch = punch * (self.RecoilPunch or 1) * self:GetBuff_Mult("Mult_RecoilPunch")
|
||||
|
||||
self:SetFreeAimAngle(self:GetFreeAimAngle() - punch)
|
||||
|
||||
if CLIENT then self:OurViewPunch(punch) end
|
||||
|
||||
if CLIENT or single then
|
||||
recv = recv * self.VisualRecoilMult
|
||||
|
||||
self.RecoilAmount = self.RecoilAmount + (self.Recoil * rmul * recu)
|
||||
self.RecoilAmountSide = self.RecoilAmountSide + (self.RecoilSide * irec * recs * rmul)
|
||||
self.RecoilPunchBack = math.Clamp(self.RecoilAmount * recv * 5, 1, 5)
|
||||
|
||||
if self.MaxRecoilBlowback > 0 then
|
||||
self.RecoilPunchBack = math.Clamp(self.RecoilPunchBack, 0, self.MaxRecoilBlowback)
|
||||
end
|
||||
|
||||
self.RecoilPunchSide = self.RecoilSide * 0.1 * irec * recv * rmul
|
||||
self.RecoilPunchUp = self.RecoilRise * 0.1 * recu
|
||||
end
|
||||
|
||||
-- math.randomseed(CurTime() + (self:EntIndex() * 3))
|
||||
end
|
||||
|
||||
function SWEP:GetBurstLength()
|
||||
local clip = self:Clip1()
|
||||
if self:HasBottomlessClip() then
|
||||
clip = self:Ammo1()
|
||||
if self:HasInfiniteAmmo() then
|
||||
clip = math.huge
|
||||
end
|
||||
end
|
||||
--if clip == 0 then return 1 end
|
||||
|
||||
local len = self:GetCurrentFiremode().Mode
|
||||
|
||||
if !len then return self:GetBurstCount() + 10 end
|
||||
|
||||
local hookedlen = self:GetBuff_Hook("Hook_GetBurstLength", len)
|
||||
|
||||
if len == 1 then return 1 end
|
||||
if len >= 2 then return self:GetBurstCount() + 10 end
|
||||
|
||||
if hookedlen != len then return hookedlen end
|
||||
|
||||
if len < 0 then return -len end
|
||||
|
||||
return self:GetBurstCount() + 10
|
||||
end
|
||||
|
||||
function SWEP:FireAnimationEvent(pos, ang, event, options)
|
||||
return true
|
||||
end
|
||||
|
||||
function SWEP:IsRampupWeapon()
|
||||
local ovr = self:GetBuff_Override("Override_IsRampupWeapon")
|
||||
if ovr != nil then return ovr end
|
||||
return self:GetBuff("Damage") < self:GetBuff("DamageMin")
|
||||
end
|
||||
|
||||
function SWEP:GetMinMaxRange()
|
||||
local decrease = !self:IsRampupWeapon()
|
||||
|
||||
local min = self:GetBuff_Override("Override_RangeMin", self.RangeMin or 0)
|
||||
local max = self:GetBuff_Override("Override_Range", self.Range)
|
||||
local min_add = self:GetBuff_Add("Add_RangeMin")
|
||||
local max_add = self:GetBuff_Add("Add_Range")
|
||||
local min_mult = self:GetBuff_Mult("Mult_RangeMin")
|
||||
local max_mult = self:GetBuff_Mult("Mult_Range")
|
||||
|
||||
if decrease then
|
||||
-- MinRange is also affected by Mult_Range, this is intentional
|
||||
local total_min = math.max((min + min_add) * min_mult * max_mult, 0)
|
||||
return total_min, math.max((max + max_add) * max_mult, total_min)
|
||||
else
|
||||
-- For "rampup weapons" (dmgmin > dmg), range buffs *decrease* range, as it ramps up damage quicker
|
||||
-- After all, +Range is supposed to be a positive buff no matter the kind of gun
|
||||
local total_min = math.max((min - min_add) / min_mult / max_mult, 0)
|
||||
return total_min, math.max((max - max_add) / max_mult, total_min)
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:GetRangeFraction(range)
|
||||
local min, max = self:GetMinMaxRange()
|
||||
if range < min then
|
||||
return 0
|
||||
else
|
||||
return math.Clamp((range - min) / (max - min), 0, 1)
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:GetDamage(range, pellet)
|
||||
local ovr = self:GetBuff_Override("Override_Num")
|
||||
local add = self:GetBuff_Add("Add_Num")
|
||||
local mul = self:GetBuff_Mult("Mult_Num")
|
||||
|
||||
local num = self.Num
|
||||
local nbr = (ovr or num) * mul + add
|
||||
local factor = 1
|
||||
|
||||
-- Total damage should be unchanged regardless of whether the weapon originally fired 1 pellet or > 1
|
||||
-- If pellet is set, we return per-pellet damage instead of total damage
|
||||
if pellet and num == 1 then
|
||||
factor = 1 / ((ovr or 1) * mul + add)
|
||||
elseif num != nbr then
|
||||
factor = num / nbr
|
||||
end
|
||||
|
||||
--factor = ((pellet and num == 1) and (1 / ((ovr or 1) + add))) or ((num != nbr) and (num / nbr)) or 1
|
||||
|
||||
if !pellet then factor = factor * nbr end
|
||||
|
||||
local dmgmax = self:GetBuff("Damage") * factor
|
||||
local dmgmin = self:GetBuff("DamageMin") * factor
|
||||
local delta = self:GetRangeFraction(range)
|
||||
|
||||
local lerped = Lerp(delta, dmgmax, dmgmin)
|
||||
|
||||
return lerped
|
||||
end
|
||||
|
||||
function SWEP:SecondaryAttack()
|
||||
return self.Melee2 and self:Bash(true)
|
||||
end
|
||||
|
||||
function SWEP:CanShootWhileSprint()
|
||||
return ArcCW.ConVars["mult_shootwhilesprinting"]:GetBool() or self:GetBuff_Override("Override_ShootWhileSprint", self.ShootWhileSprint)
|
||||
end
|
||||
73
lua/weapons/arccw_base/sh_freeaim.lua
Normal file
73
lua/weapons/arccw_base/sh_freeaim.lua
Normal file
@@ -0,0 +1,73 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
local ang0 = Angle(0, 0, 0)
|
||||
SWEP.ClientFreeAimAng = Angle(ang0)
|
||||
|
||||
function SWEP:ShouldFreeAim()
|
||||
if self:GetOwner():IsNPC() then return false end
|
||||
if (ArcCW.ConVars["freeaim"]:GetInt() == 0 or self:GetBuff_Override("NeverFreeAim", self.NeverFreeAim)) and !self:GetBuff_Override("AlwaysFreeAim", self.AlwaysFreeAim) then return false end
|
||||
return true
|
||||
end
|
||||
|
||||
function SWEP:FreeAimMaxAngle()
|
||||
local ang = self.FreeAimAngle and self:GetBuff("FreeAimAngle") or math.Clamp(self:GetBuff("HipDispersion") / 80, 3, 10)
|
||||
return ang
|
||||
end
|
||||
|
||||
function SWEP:ThinkFreeAim()
|
||||
if self:ShouldFreeAim() then
|
||||
local diff = self:GetOwner():EyeAngles() - self:GetLastAimAngle()
|
||||
--diff = diff * 2
|
||||
|
||||
local freeaimang = Angle(self:GetFreeAimAngle())
|
||||
|
||||
local max = self:FreeAimMaxAngle()
|
||||
|
||||
local delta = math.min(self:GetSightDelta(),
|
||||
self:CanShootWhileSprint() and 1 or (1 - self:GetSprintDelta()),
|
||||
self:GetState() == ArcCW.STATE_CUSTOMIZE and 0 or 1)
|
||||
|
||||
max = max * delta
|
||||
|
||||
diff.p = math.NormalizeAngle(diff.p)
|
||||
diff.y = math.NormalizeAngle(diff.y)
|
||||
|
||||
diff = diff * Lerp(delta, 1, 0.25)
|
||||
|
||||
freeaimang.p = math.Clamp(math.NormalizeAngle(freeaimang.p) + math.NormalizeAngle(diff.p), -max, max)
|
||||
freeaimang.y = math.Clamp(math.NormalizeAngle(freeaimang.y) + math.NormalizeAngle(diff.y), -max, max)
|
||||
|
||||
local ang2d = math.atan2(freeaimang.p, freeaimang.y)
|
||||
local mag2d = math.sqrt(math.pow(freeaimang.p, 2) + math.pow(freeaimang.y, 2))
|
||||
|
||||
mag2d = math.min(mag2d, max)
|
||||
|
||||
freeaimang.p = mag2d * math.sin(ang2d)
|
||||
freeaimang.y = mag2d * math.cos(ang2d)
|
||||
|
||||
self:SetFreeAimAngle(freeaimang)
|
||||
|
||||
if CLIENT then
|
||||
self.ClientFreeAimAng = freeaimang
|
||||
end
|
||||
end
|
||||
|
||||
self:SetLastAimAngle(self:GetOwner():EyeAngles())
|
||||
end
|
||||
|
||||
function SWEP:GetFreeAimOffset()
|
||||
if !self:ShouldFreeAim() then return ang0 end
|
||||
if CLIENT then
|
||||
return self.ClientFreeAimAng
|
||||
else
|
||||
return self:GetFreeAimAngle()
|
||||
end
|
||||
end
|
||||
200
lua/weapons/arccw_base/sh_grenade.lua
Normal file
200
lua/weapons/arccw_base/sh_grenade.lua
Normal file
@@ -0,0 +1,200 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
SWEP.GrenadePrimeTime = 0
|
||||
|
||||
function SWEP:PreThrow()
|
||||
|
||||
if self:GetNWState() == ArcCW.STATE_SPRINT and !self:CanShootWhileSprint() then return end
|
||||
|
||||
local bot, inf = self:HasBottomlessClip(), self:HasInfiniteAmmo()
|
||||
local aps = self:GetBuff("AmmoPerShot")
|
||||
|
||||
if !inf and (bot and self:Ammo1() or self:Clip1()) < aps then
|
||||
if self:Ammo1() == 0 and self:Clip1() == 0 and !self:GetBuff_Override("Override_KeepIfEmpty", self.KeepIfEmpty) then
|
||||
self:GetOwner():StripWeapon(self:GetClass())
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if self:GetGrenadePrimed() then return end
|
||||
|
||||
if engine.ActiveGamemode() == "terrortown" and GetRoundState and GetRoundState() == ROUND_PREP and
|
||||
((GetConVar("ttt_no_nade_throw_during_prep") and GetConVar("ttt_no_nade_throw_during_prep"):GetBool())
|
||||
or (GetConVar("ttt_nade_throw_during_prep") and !GetConVar("ttt_nade_throw_during_prep"):GetBool())) then
|
||||
return
|
||||
end
|
||||
|
||||
self.GrenadePrimeTime = CurTime()
|
||||
local alt = self:GetOwner():KeyDown(IN_ATTACK2)
|
||||
self:SetGrenadeAlt(alt)
|
||||
self:SetGrenadePrimed(true)
|
||||
|
||||
local pulltime = self:GetBuff("PullPinTime")
|
||||
local anim = alt and self:SelectAnimation("pre_throw_alt") or self:SelectAnimation("pre_throw")
|
||||
self:PlayAnimation(anim, self.PullPinTime / pulltime, true, 0, true, nil, true)
|
||||
|
||||
self.isCooked = (!alt and self:GetBuff("CookPrimFire", true)) or (alt and self:GetBuff("CookAltFire", true)) or nil
|
||||
|
||||
self:SetNextPrimaryFire(CurTime() + pulltime)
|
||||
self:SetPriorityAnim(CurTime() + pulltime)
|
||||
|
||||
self:SetShouldHoldType()
|
||||
|
||||
self:GetBuff_Hook("Hook_PreThrow")
|
||||
|
||||
if pulltime == 0 then
|
||||
self:Throw()
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:Throw()
|
||||
if self:GetNextPrimaryFire() > CurTime() then return end
|
||||
|
||||
local isCooked = self.isCooked
|
||||
self:SetGrenadePrimed(false)
|
||||
self.isCooked = nil
|
||||
|
||||
local alt = self:GetGrenadeAlt()
|
||||
|
||||
local anim = alt and self:SelectAnimation("throw_alt") or self:SelectAnimation("throw")
|
||||
self:PlayAnimation(anim, self:GetBuff_Mult("Mult_ThrowTime"), false, 0, true)
|
||||
|
||||
local animevent = alt and self:GetBuff_Override("Override_AnimShootAlt", self.AnimShootAlt) or self:GetBuff_Override("Override_AnimShoot", self.AnimShoot)
|
||||
self:GetOwner():DoAnimationEvent(animevent)
|
||||
|
||||
local heldtime = CurTime() - self.GrenadePrimeTime
|
||||
|
||||
local mv = 0
|
||||
|
||||
if alt then
|
||||
mv = self:GetBuff("MuzzleVelocityAlt", true) or self:GetBuff("MuzzleVelocity")
|
||||
else
|
||||
mv = self:GetBuff("MuzzleVelocity")
|
||||
local chg = self:GetBuff("WindupTime")
|
||||
if chg > 0 then
|
||||
mv = Lerp(math.Clamp(heldtime / chg, 0, 1), mv * self:GetBuff("WindupMinimum"), mv)
|
||||
end
|
||||
end
|
||||
|
||||
local force = mv * ArcCW.HUToM
|
||||
|
||||
self:SetTimer(self:GetBuff("ShootEntityDelay"), function()
|
||||
|
||||
local ft = self:GetBuff("FuseTime", true)
|
||||
local data = {
|
||||
dodefault = true,
|
||||
force = force,
|
||||
shootentity = self:GetBuff_Override("Override_ShootEntity", self.ShootEntity),
|
||||
fusetime = ft and (ft - (isCooked and heldtime or 0)),
|
||||
}
|
||||
local ovr = self:GetBuff_Hook("Hook_Throw", data)
|
||||
if !ovr or ovr.dodefault then
|
||||
local rocket = self:FireRocket(self:GetBuff_Override("Override_ShootEntity", self.ShootEntity), force / ArcCW.HUToM)
|
||||
if !rocket then return end
|
||||
|
||||
if ft then
|
||||
if isCooked then
|
||||
rocket.FuseTime = ft - heldtime
|
||||
else
|
||||
rocket.FuseTime = ft
|
||||
end
|
||||
else
|
||||
rocket.FuseTime = math.huge
|
||||
end
|
||||
|
||||
local phys = rocket:GetPhysicsObject()
|
||||
|
||||
local inertia = self:GetBuff_Override("Override_ThrowInertia", self.ThrowInertia)
|
||||
if inertia == nil then inertia = ArcCW.ConVars["throwinertia"]:GetBool() end
|
||||
if inertia and mv > 100 then
|
||||
phys:AddVelocity(self:GetOwner():GetVelocity())
|
||||
end
|
||||
|
||||
phys:AddAngleVelocity( Vector(0, 750, 0) )
|
||||
end
|
||||
if !self:HasInfiniteAmmo() then
|
||||
local aps = self:GetBuff("AmmoPerShot")
|
||||
local a1 = self:Ammo1()
|
||||
if self:HasBottomlessClip() or a1 >= aps then
|
||||
self:TakePrimaryAmmo(aps)
|
||||
elseif a1 < aps then
|
||||
self:SetClip1(math.min(self:GetCapacity() + self:GetChamberSize(), self:Clip1() + a1))
|
||||
self:TakePrimaryAmmo(a1)
|
||||
end
|
||||
|
||||
if (self.Singleton or self:Ammo1() == 0) and !self:GetBuff_Override("Override_KeepIfEmpty", self.KeepIfEmpty) then
|
||||
self:GetOwner():StripWeapon(self:GetClass())
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
end)
|
||||
local t = self:GetAnimKeyTime(anim) * self:GetBuff_Mult("Mult_ThrowTime")
|
||||
self:SetPriorityAnim(CurTime() + t)
|
||||
self:SetTimer(t, function()
|
||||
if !self:IsValid() then return end
|
||||
local a = self:SelectAnimation("reload") or self:SelectAnimation("draw")
|
||||
self:PlayAnimation(a, self:GetBuff_Mult("Mult_ReloadTime"), true, 0, nil, nil, true)
|
||||
self:SetPriorityAnim(CurTime() + self:GetAnimKeyTime(a, true) * self:GetBuff_Mult("Mult_ReloadTime"))
|
||||
end)
|
||||
|
||||
self:SetNextPrimaryFire(CurTime() + self:GetFiringDelay())
|
||||
|
||||
self:SetGrenadeAlt(false)
|
||||
|
||||
self:SetShouldHoldType()
|
||||
|
||||
self:GetBuff_Hook("Hook_PostThrow")
|
||||
end
|
||||
|
||||
function SWEP:GrenadeDrop(doammo)
|
||||
local rocket = self:FireRocket(self.ShootEntity, 0)
|
||||
|
||||
if IsValid(rocket) then
|
||||
local phys = rocket:GetPhysicsObject()
|
||||
|
||||
if ArcCW.ConVars["throwinertia"]:GetBool() then
|
||||
phys:AddVelocity(self:GetOwner():GetVelocity())
|
||||
end
|
||||
|
||||
local ft = self:GetBuff_Override("Override_FuseTime") or self.FuseTime
|
||||
|
||||
if ft then
|
||||
if self.isCooked then
|
||||
rocket.FuseTime = ft - (CurTime() - self.GrenadePrimeTime)
|
||||
else
|
||||
rocket.FuseTime = ft
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if doammo then
|
||||
if !self:HasInfiniteAmmo() then
|
||||
local aps = self:GetBuff("AmmoPerShot")
|
||||
local a1 = self:Ammo1()
|
||||
if self:HasBottomlessClip() or a1 >= aps then
|
||||
self:TakePrimaryAmmo(aps)
|
||||
elseif a1 < aps then
|
||||
self:SetClip1(math.min(self:GetCapacity() + self:GetChamberSize(), self:Clip1() + a1))
|
||||
self:TakePrimaryAmmo(a1)
|
||||
end
|
||||
|
||||
if (self.Singleton or self:Ammo1() == 0) and !self:GetBuff_Override("Override_KeepIfEmpty", self.KeepIfEmpty) then
|
||||
self:GetOwner():StripWeapon(self:GetClass())
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
self:SetNextPrimaryFire(CurTime() + 1)
|
||||
self:SetGrenadePrimed(false)
|
||||
end
|
||||
end
|
||||
222
lua/weapons/arccw_base/sh_heat.lua
Normal file
222
lua/weapons/arccw_base/sh_heat.lua
Normal file
@@ -0,0 +1,222 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
SWEP.NextHeatDissipateTime = 0
|
||||
SWEP.Heat = 0
|
||||
|
||||
function SWEP:GetMaxHeat()
|
||||
return self:GetBuff("HeatCapacity")
|
||||
end
|
||||
|
||||
function SWEP:AddHeat(a)
|
||||
local single = game.SinglePlayer()
|
||||
a = tonumber(a)
|
||||
|
||||
if !(self.Jamming or self:GetBuff_Override("Override_Jamming")) then return end
|
||||
|
||||
if single and self:GetOwner():IsValid() and SERVER then self:CallOnClient("AddHeat", a) end
|
||||
-- if !single and !IsFirstTimePredicted() then return end
|
||||
|
||||
local max = self:GetBuff("HeatCapacity")
|
||||
local mult = 1 * self:GetBuff_Mult("Mult_FixTime")
|
||||
local heat = self:GetHeat()
|
||||
local anim = self:SelectAnimation("fix")
|
||||
anim = self:GetBuff_Hook("Hook_SelectFixAnim", anim) or anim
|
||||
local amount = a or 1
|
||||
local t = CurTime() + self:GetAnimKeyTime(anim) * mult
|
||||
self.Heat = math.max(0, heat + amount * ArcCW.ConVars["mult_heat"]:GetFloat())
|
||||
|
||||
self.NextHeatDissipateTime = CurTime() + (self:GetBuff("HeatDelayTime"))
|
||||
local overheat = self.Heat >= max
|
||||
if overheat then
|
||||
local h = self:GetBuff_Hook("Hook_Overheat", self.Heat)
|
||||
if h == true then overheat = false end
|
||||
end
|
||||
if overheat then
|
||||
self.Heat = math.min(self.Heat, max)
|
||||
if self:GetBuff_Override("Override_HeatFix", self.HeatFix) then
|
||||
self.NextHeatDissipateTime = t
|
||||
elseif self:GetBuff_Override("Override_HeatLockout", self.HeatLockout) then
|
||||
self.NextHeatDissipateTime = t
|
||||
end
|
||||
elseif !self:GetBuff_Override("Override_HeatOverflow", self.HeatOverflow) then
|
||||
self.Heat = math.min(self.Heat, max)
|
||||
end
|
||||
|
||||
if single and CLIENT then return end
|
||||
|
||||
self:SetHeat(self.Heat)
|
||||
|
||||
if overheat then
|
||||
|
||||
local ret = self:GetBuff_Hook("Hook_OnOverheat")
|
||||
if ret then return end
|
||||
|
||||
if anim then
|
||||
self:PlayAnimation(anim, mult, true, 0, true)
|
||||
self:SetPriorityAnim(t)
|
||||
self:SetNextPrimaryFire(t)
|
||||
|
||||
if self:GetBuff_Override("Override_HeatFix", self.HeatFix) then
|
||||
self:SetTimer(t - CurTime(),
|
||||
function()
|
||||
self:SetHeat(0)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
if self.HeatLockout or self:GetBuff_Override("Override_HeatLockout") then
|
||||
self:SetHeatLocked(true)
|
||||
end
|
||||
|
||||
self:GetBuff_Hook("Hook_PostOverheat")
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:DoHeat()
|
||||
if self.NextHeatDissipateTime > CurTime() then return end
|
||||
|
||||
--local diss = self.HeatDissipation or 2
|
||||
--diss = diss * self:GetBuff_Mult("Mult_HeatDissipation")
|
||||
local diss = self:GetBuff("HeatDissipation") or 2
|
||||
local ft = FrameTime()
|
||||
self.Heat = self:GetHeat() - (ft * diss)
|
||||
|
||||
self.Heat = math.max(self.Heat, 0)
|
||||
|
||||
self:SetHeat(self.Heat)
|
||||
|
||||
if self.Heat <= 0 and self:GetHeatLocked() then
|
||||
self:SetHeatLocked(false)
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:HeatEnabled()
|
||||
return self.Jamming or self:GetBuff_Override("Override_Jamming")
|
||||
end
|
||||
|
||||
function SWEP:MalfunctionEnabled()
|
||||
local cvar = ArcCW.ConVars["malfunction"]:GetInt()
|
||||
return cvar == 2 or (cvar == 1 and self:GetBuff_Override("Override_Malfunction", self.Malfunction))
|
||||
end
|
||||
|
||||
function SWEP:GetMalfunctionAnimation()
|
||||
local anim = self:SelectAnimation("unjam")
|
||||
if !self.Animations[anim] then
|
||||
anim = self:SelectAnimation("fix")
|
||||
anim = self:GetBuff_Hook("Hook_SelectFixAnim", anim) or anim
|
||||
end
|
||||
if !self.Animations[anim] then anim = self:SelectAnimation("cycle") end
|
||||
if !self.Animations[anim] then anim = nil end
|
||||
return anim
|
||||
end
|
||||
|
||||
function SWEP:DoMalfunction(post)
|
||||
|
||||
if !IsFirstTimePredicted() then return end
|
||||
if !self:MalfunctionEnabled() then return false end
|
||||
local shouldpost = self:GetBuff_Override("Override_MalfunctionPostFire", self.MalfunctionPostFire)
|
||||
if post != shouldpost then return false end
|
||||
|
||||
-- Auto calculated malfunction mean
|
||||
if self.MalfunctionMean == nil then
|
||||
local mm
|
||||
if self.Jamming then mm = self.HeatCapacity * 4
|
||||
else mm = self.Primary.ClipSize * 8 end
|
||||
|
||||
if self.ManualAction then
|
||||
-- Manual guns are less likely to jam
|
||||
mm = mm * 2
|
||||
else
|
||||
-- Burst and semi only guns are less likely to jam
|
||||
local a, b = false, false
|
||||
for k, v in pairs(self.Firemodes) do
|
||||
if !v.Mode then continue end
|
||||
if v.Mode == 2 then a = true
|
||||
elseif v.Mode < 0 then b = true end
|
||||
end
|
||||
if !a and b then
|
||||
mm = mm * 1.25
|
||||
elseif !a and !b then
|
||||
mm = mm * 1.5
|
||||
end
|
||||
end
|
||||
self.MalfunctionMean = mm
|
||||
end
|
||||
|
||||
local cvar = math.max(ArcCW.ConVars["mult_malfunction"]:GetFloat(), 0.00000001)
|
||||
local mean = self:GetBuff("MalfunctionMean") / cvar
|
||||
local var = mean * math.Clamp(self:GetBuff("MalfunctionVariance") * math.max(1, math.sqrt(cvar)), 0, 1)
|
||||
local count = (self.ShotsSinceMalfunction or 0)
|
||||
|
||||
if !self.NextMalfunction then
|
||||
math.randomseed(math.Round(util.SharedRandom(count, -1337, 1337, !game.SinglePlayer() and self:GetOwner():GetCurrentCommand():CommandNumber() or CurTime()) * (self:EntIndex() % 30241)))
|
||||
self.NextMalfunction = math.ceil(math.sqrt(-2 * var * math.log(math.random())) * math.cos(2 * math.pi * math.random()))
|
||||
end
|
||||
|
||||
local ret = self:GetBuff_Hook("Hook_Malfunction", count, true)
|
||||
if ret != nil then return ret end
|
||||
|
||||
-- if self:Clip1() <= 1 then return false end -- Don't fucking
|
||||
|
||||
--print(mean, var, count, self.NextMalfunction)
|
||||
if count >= self.NextMalfunction + mean then
|
||||
local ret2 = self:GetBuff_Hook("Hook_OnMalfunction", count, true)
|
||||
if ret2 then return false end
|
||||
|
||||
self:MyEmitSound(self:GetBuff_Override("Override_MalfunctionSound") or self.MalfunctionSound, 75, 100, 1, CHAN_ITEM)
|
||||
|
||||
local wait = self:GetBuff("MalfunctionWait")
|
||||
self:SetNextPrimaryFire(CurTime() + wait)
|
||||
|
||||
local anim = self:GetMalfunctionAnimation()
|
||||
if !anim or self:GetBuff_Override("Override_MalfunctionJam", self.MalfunctionJam) then
|
||||
self:SetMalfunctionJam(true)
|
||||
else
|
||||
self:SetTimer(wait,
|
||||
function()
|
||||
self:MalfunctionClear()
|
||||
end)
|
||||
end
|
||||
|
||||
self:GetBuff_Hook("Hook_PostMalfunction")
|
||||
self.ShotsSinceMalfunction = 0
|
||||
self.NextMalfunction = nil
|
||||
|
||||
self:SetBurstCount(0)
|
||||
|
||||
return true
|
||||
else
|
||||
self.ShotsSinceMalfunction = (self.ShotsSinceMalfunction or 0) + 1
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:MalfunctionClear()
|
||||
|
||||
if self:GetBuff_Override("Override_MalfunctionTakeRound", self.MalfunctionTakeRound) then
|
||||
self:TakePrimaryAmmo(self:GetBuff("AmmoPerShot"))
|
||||
end
|
||||
|
||||
local anim = self:GetMalfunctionAnimation()
|
||||
if anim then
|
||||
self:PlayAnimation(anim, self:GetBuff_Mult("Mult_MalfunctionFixTime"), true, 0, true)
|
||||
local wait = self:GetAnimKeyTime(anim) - 0.01
|
||||
self:SetTimer(wait,
|
||||
function()
|
||||
self:SetMalfunctionJam(false)
|
||||
self:PlayIdleAnimation(true)
|
||||
end)
|
||||
return true
|
||||
else
|
||||
self:SetMalfunctionJam(false)
|
||||
return false
|
||||
end
|
||||
end
|
||||
1063
lua/weapons/arccw_base/sh_model.lua
Normal file
1063
lua/weapons/arccw_base/sh_model.lua
Normal file
File diff suppressed because it is too large
Load Diff
476
lua/weapons/arccw_base/sh_reload.lua
Normal file
476
lua/weapons/arccw_base/sh_reload.lua
Normal file
@@ -0,0 +1,476 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
|
||||
|
||||
function SWEP:GetReloadTime()
|
||||
-- Only works with classic mag-fed weapons.
|
||||
local mult = self:GetBuff_Mult("Mult_ReloadTime")
|
||||
local anim = self:SelectReloadAnimation()
|
||||
|
||||
if !self.Animations[anim] then return false end
|
||||
|
||||
local full = self:GetAnimKeyTime(anim) * mult
|
||||
local magin = self:GetAnimKeyTime(anim, true) * mult
|
||||
|
||||
return { full, magin }
|
||||
end
|
||||
|
||||
function SWEP:SetClipInfo(load)
|
||||
load = self:GetBuff_Hook("Hook_SetClipInfo", load) or load
|
||||
self.LastLoadClip1 = load - self:Clip1()
|
||||
self.LastClip1 = load
|
||||
end
|
||||
|
||||
function SWEP:Reload()
|
||||
if IsValid(self:GetHolster_Entity()) then return end
|
||||
if self:GetHolster_Time() > 0 then return end
|
||||
|
||||
if self:GetOwner():IsNPC() then
|
||||
return
|
||||
end
|
||||
|
||||
if self:GetState() == ArcCW.STATE_CUSTOMIZE then
|
||||
return
|
||||
end
|
||||
|
||||
-- Switch to UBGL
|
||||
if self:GetBuff_Override("UBGL") and self:GetOwner():KeyDown(IN_USE) then
|
||||
if self:GetInUBGL() then
|
||||
--net.Start("arccw_ubgl")
|
||||
--net.WriteBool(false)
|
||||
--net.SendToServer()
|
||||
|
||||
self:DeselectUBGL()
|
||||
else
|
||||
--net.Start("arccw_ubgl")
|
||||
--net.WriteBool(true)
|
||||
--net.SendToServer()
|
||||
|
||||
self:SelectUBGL()
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
if self:GetInUBGL() then
|
||||
if self:GetNextSecondaryFire() > CurTime() then return end
|
||||
self:ReloadUBGL()
|
||||
return
|
||||
end
|
||||
|
||||
if self:GetNextPrimaryFire() >= CurTime() then return end
|
||||
-- if !game.SinglePlayer() and !IsFirstTimePredicted() then return end
|
||||
|
||||
|
||||
if self.Throwing then return end
|
||||
if self.PrimaryBash then return end
|
||||
|
||||
-- with the lite 3D HUD, you may want to check your ammo without reloading
|
||||
local Lite3DHUD = self:GetOwner():GetInfo("arccw_hud_3dfun") == "1"
|
||||
if self:GetOwner():KeyDown(IN_WALK) and Lite3DHUD then
|
||||
return
|
||||
end
|
||||
|
||||
if self:GetMalfunctionJam() then
|
||||
local r = self:MalfunctionClear()
|
||||
if r then return end
|
||||
end
|
||||
|
||||
if !self:GetMalfunctionJam() and self:Ammo1() <= 0 and !self:HasInfiniteAmmo() then return end
|
||||
|
||||
if self:HasBottomlessClip() then return end
|
||||
|
||||
if self:GetBuff_Hook("Hook_PreReload") then return end
|
||||
|
||||
-- if we must dump our clip when reloading, our reserve ammo should be more than our clip
|
||||
local dumpclip = self:GetBuff_Hook("Hook_ReloadDumpClip")
|
||||
if dumpclip and !self:HasInfiniteAmmo() and self:Clip1() >= self:Ammo1() then
|
||||
return
|
||||
end
|
||||
|
||||
self.LastClip1 = self:Clip1()
|
||||
|
||||
local reserve = self:Ammo1()
|
||||
|
||||
reserve = reserve + self:Clip1()
|
||||
if self:HasInfiniteAmmo() then reserve = self:GetCapacity() + self:Clip1() end
|
||||
|
||||
local clip = self:GetCapacity()
|
||||
|
||||
local chamber = math.Clamp(self:Clip1(), 0, self:GetChamberSize())
|
||||
if self:GetNeedCycle() then chamber = 0 end
|
||||
|
||||
local load = math.Clamp(clip + chamber, 0, reserve)
|
||||
|
||||
if !self:GetMalfunctionJam() and load <= self:Clip1() then return end
|
||||
|
||||
self:SetBurstCount(0)
|
||||
|
||||
local shouldshotgunreload = self:GetBuff_Override("Override_ShotgunReload")
|
||||
local shouldhybridreload = self:GetBuff_Override("Override_HybridReload")
|
||||
|
||||
if shouldshotgunreload == nil then shouldshotgunreload = self.ShotgunReload end
|
||||
if shouldhybridreload == nil then shouldhybridreload = self.HybridReload end
|
||||
|
||||
if shouldhybridreload then
|
||||
shouldshotgunreload = self:Clip1() != 0
|
||||
end
|
||||
|
||||
if shouldshotgunreload and self:GetShotgunReloading() > 0 then return end
|
||||
|
||||
local mult = self:GetBuff_Mult("Mult_ReloadTime")
|
||||
|
||||
if shouldshotgunreload then
|
||||
local anim = "sgreload_start"
|
||||
local insertcount = 0
|
||||
|
||||
local empty = self:Clip1() == 0 --or self:GetNeedCycle()
|
||||
|
||||
if self.Animations.sgreload_start_empty and empty then
|
||||
anim = "sgreload_start_empty"
|
||||
empty = false
|
||||
if (self.Animations.sgreload_start_empty or {}).ForceEmpty == true then
|
||||
empty = true
|
||||
end
|
||||
|
||||
insertcount = (self.Animations.sgreload_start_empty or {}).RestoreAmmo or 1
|
||||
else
|
||||
insertcount = (self.Animations.sgreload_start or {}).RestoreAmmo or 0
|
||||
end
|
||||
|
||||
anim = self:GetBuff_Hook("Hook_SelectReloadAnimation", anim) or anim
|
||||
|
||||
local time = self:GetAnimKeyTime(anim)
|
||||
local time2 = self:GetAnimKeyTime(anim, true)
|
||||
|
||||
if time2 >= time then
|
||||
time2 = 0
|
||||
end
|
||||
|
||||
if insertcount > 0 then
|
||||
self:SetMagUpCount(insertcount)
|
||||
self:SetMagUpIn(CurTime() + time2 * mult)
|
||||
end
|
||||
self:PlayAnimation(anim, mult, true, 0, true, nil, true)
|
||||
|
||||
self:SetReloading(CurTime() + time * mult)
|
||||
|
||||
self:SetShotgunReloading(empty and 4 or 2)
|
||||
else
|
||||
local anim = self:SelectReloadAnimation()
|
||||
|
||||
if !self.Animations[anim] then print("Invalid animation \"" .. anim .. "\"") return end
|
||||
|
||||
self:PlayAnimation(anim, mult, true, 0, false, nil, true)
|
||||
|
||||
local reloadtime = self:GetAnimKeyTime(anim, true) * mult
|
||||
local reloadtime2 = self:GetAnimKeyTime(anim, false) * mult
|
||||
|
||||
self:SetNextPrimaryFire(CurTime() + reloadtime2)
|
||||
self:SetReloading(CurTime() + reloadtime2)
|
||||
|
||||
self:SetMagUpCount(0)
|
||||
self:SetMagUpIn(CurTime() + reloadtime)
|
||||
end
|
||||
|
||||
self:SetClipInfo(load)
|
||||
if game.SinglePlayer() then
|
||||
self:CallOnClient("SetClipInfo", tostring(load))
|
||||
end
|
||||
|
||||
for i, k in pairs(self.Attachments) do
|
||||
if !k.Installed then continue end
|
||||
local atttbl = ArcCW.AttachmentTable[k.Installed]
|
||||
|
||||
if atttbl.DamageOnReload then
|
||||
self:DamageAttachment(i, atttbl.DamageOnReload)
|
||||
end
|
||||
end
|
||||
|
||||
if !self.ReloadInSights then
|
||||
self:ExitSights()
|
||||
self.Sighted = false
|
||||
end
|
||||
|
||||
self:GetBuff_Hook("Hook_PostReload")
|
||||
end
|
||||
|
||||
function SWEP:ReloadTimed()
|
||||
-- yeah my function names are COOL and QUIRKY and you can't say a DAMN thing about it.
|
||||
self:RestoreAmmo(self:GetMagUpCount() != 0 and self:GetMagUpCount())
|
||||
self:SetMagUpCount(0)
|
||||
self:SetLastLoad(self:Clip1())
|
||||
self:SetNthReload(self:GetNthReload() + 1)
|
||||
end
|
||||
|
||||
function SWEP:Unload()
|
||||
if !self:GetOwner():IsPlayer() then return end
|
||||
if SERVER and self:Clip1() != ArcCW.BottomlessMagicNumber then
|
||||
self:GetOwner():GiveAmmo(self:Clip1(), self.Primary.Ammo or "", true)
|
||||
end
|
||||
self:SetClip1(0)
|
||||
end
|
||||
|
||||
function SWEP:HasBottomlessClip()
|
||||
if ArcCW.ConVars["mult_bottomlessclip"]:GetBool() then return true end
|
||||
if self.BottomlessClip or self:GetBuff_Override("Override_BottomlessClip") then return true end
|
||||
return false
|
||||
end
|
||||
|
||||
function SWEP:HasInfiniteAmmo()
|
||||
if ArcCW.ConVars["mult_infiniteammo"]:GetBool() then return true end
|
||||
if self:GetBuff_Override("Override_InfiniteAmmo", self.InfiniteAmmo) then return true end
|
||||
return false
|
||||
end
|
||||
|
||||
function SWEP:RestoreAmmo(count)
|
||||
if self:GetOwner():IsNPC() then return end
|
||||
|
||||
local chamber = math.Clamp(self:Clip1(), 0, self:GetChamberSize())
|
||||
if self:GetNeedCycle() then chamber = 0 end
|
||||
|
||||
local clip = self:GetCapacity()
|
||||
|
||||
count = count or (clip + chamber)
|
||||
|
||||
local reserve = (self:HasInfiniteAmmo() and math.huge or self:Ammo1())
|
||||
|
||||
local dumpclip = self:GetBuff_Hook("Hook_ReloadDumpClip")
|
||||
if !dumpclip then
|
||||
reserve = reserve + self:Clip1()
|
||||
end
|
||||
|
||||
local load = math.Clamp(self:Clip1() + count, 0, reserve)
|
||||
load = math.Clamp(load, 0, clip + chamber)
|
||||
reserve = reserve - load
|
||||
|
||||
if !self:HasInfiniteAmmo() then
|
||||
self:GetOwner():SetAmmo(reserve, self.Primary.Ammo, true)
|
||||
end
|
||||
self:SetClip1(load)
|
||||
end
|
||||
|
||||
-- local lastframeclip1 = 0
|
||||
|
||||
SWEP.LastClipOutTime = 0
|
||||
|
||||
function SWEP:GetVisualBullets()
|
||||
local h = self:GetBuff_Hook("Hook_GetVisualBullets")
|
||||
if h then return h end
|
||||
|
||||
local _clip = self:Clip1()
|
||||
local _ammo = self:Ammo1()
|
||||
|
||||
if self:HasInfiniteAmmo() then
|
||||
_ammo = math.huge
|
||||
end
|
||||
if self:HasBottomlessClip() then
|
||||
_clip = _ammo
|
||||
end
|
||||
|
||||
if self.LastClipOutTime > CurTime() then
|
||||
return self.LastClip1_B or _clip
|
||||
else
|
||||
self.LastClip1_B = _clip
|
||||
|
||||
if self:GetReloading() and !(self.ShotgunReload or (self.HybridReload and _clip == 0)) then
|
||||
return math.Clamp(_clip + _ammo, 0, self:GetCapacity() + self:GetChamberSize())
|
||||
else
|
||||
return _clip
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:GetVisualClip()
|
||||
-- local reserve = self:Ammo1()
|
||||
-- local chamber = math.Clamp(self:Clip1(), 0, self:GetChamberSize())
|
||||
-- local abouttoload = math.Clamp(self:GetCapacity() + chamber, 0, reserve + self:Clip1())
|
||||
|
||||
-- local h = self:GetBuff_Hook("Hook_GetVisualClip")
|
||||
|
||||
-- if h then return h end
|
||||
-- if self.LastClipOutTime > CurTime() then
|
||||
-- return self.LastClip1 or self:Clip1()
|
||||
-- else
|
||||
-- if !self.RevolverReload then
|
||||
-- self.LastClip1 = self:Clip1()
|
||||
-- else
|
||||
-- if self:Clip1() > lastframeclip1 then
|
||||
-- self.LastClip1 = self:Clip1()
|
||||
-- end
|
||||
|
||||
-- lastframeclip1 = self:Clip1()
|
||||
-- end
|
||||
|
||||
-- if self:GetReloading() and !(self.ShotgunReload or (self.HybridReload and self:Clip1() == 0)) then
|
||||
-- return abouttoload
|
||||
-- else
|
||||
-- return self.LastClip1 or self:Clip1()
|
||||
-- end
|
||||
-- end
|
||||
|
||||
local reserve = self:Ammo1()
|
||||
if self:HasInfiniteAmmo() then
|
||||
reserve = math.huge
|
||||
end
|
||||
local chamber = math.Clamp(self:Clip1(), 0, self:GetChamberSize())
|
||||
local abouttoload = math.Clamp(self:GetCapacity() + chamber, 0, reserve + self:Clip1())
|
||||
|
||||
local h = self:GetBuff_Hook("Hook_GetVisualClip")
|
||||
|
||||
if h then return h end
|
||||
|
||||
if self.LastClipOutTime > CurTime() then
|
||||
return self:GetLastLoad() or self:Clip1()
|
||||
end
|
||||
|
||||
if self.RevolverReload then
|
||||
if self:GetReloading() and !(self.ShotgunReload or (self.HybridReload and self:Clip1() == 0)) then
|
||||
return abouttoload
|
||||
else
|
||||
return self:GetLastLoad() or self:Clip1()
|
||||
end
|
||||
else
|
||||
return self:Clip1()
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:GetVisualLoadAmount()
|
||||
return self.LastLoadClip1 or self:Clip1()
|
||||
end
|
||||
|
||||
function SWEP:SelectReloadAnimation()
|
||||
local ret
|
||||
|
||||
if self.Animations.reload_empty and self:Clip1() == 0 then
|
||||
ret = "reload_empty"
|
||||
else
|
||||
ret = "reload"
|
||||
end
|
||||
|
||||
ret = self:GetBuff_Hook("Hook_SelectReloadAnimation", ret) or ret
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function SWEP:ReloadInsert(empty)
|
||||
local total = self:GetCapacity()
|
||||
|
||||
-- if !game.SinglePlayer() and !IsFirstTimePredicted() then return end
|
||||
|
||||
if !empty and !self:GetNeedCycle() then
|
||||
total = total + (self:GetBuff("ChamberLoadNonEmpty", true) or self:GetChamberSize())
|
||||
else
|
||||
total = total + (self:GetBuff("ChamberLoadEmpty", true) or 0)
|
||||
end
|
||||
|
||||
local mult = self:GetBuff_Mult("Mult_ReloadTime")
|
||||
|
||||
if self:Clip1() >= total or (self:Ammo1() == 0 and !self:HasInfiniteAmmo()) or ((self:GetShotgunReloading() == 3 or self:GetShotgunReloading() == 5) and self:Clip1() > 0) then
|
||||
local ret = "sgreload_finish"
|
||||
|
||||
if empty then
|
||||
if self.Animations.sgreload_finish_empty then
|
||||
ret = "sgreload_finish_empty"
|
||||
end
|
||||
if self:GetNeedCycle() then
|
||||
self:SetNeedCycle(false)
|
||||
end
|
||||
end
|
||||
|
||||
ret = self:GetBuff_Hook("Hook_SelectReloadAnimation", ret) or ret
|
||||
|
||||
self:PlayAnimation(ret, mult, true, 0, true, nil, true)
|
||||
self:SetReloading(CurTime() + (self:GetAnimKeyTime(ret, true) * mult))
|
||||
|
||||
self:SetTimer(self:GetAnimKeyTime(ret, true) * mult,
|
||||
function()
|
||||
self:SetNthReload(self:GetNthReload() + 1)
|
||||
if self:GetOwner():KeyDown(IN_ATTACK2) then
|
||||
self:EnterSights()
|
||||
end
|
||||
end)
|
||||
|
||||
self:SetShotgunReloading(0)
|
||||
else
|
||||
local insertcount = self:GetBuff_Override("Override_InsertAmount") or 1
|
||||
local insertanim = "sgreload_insert"
|
||||
|
||||
local ret = self:GetBuff_Hook("Hook_SelectInsertAnimation", {count = insertcount, anim = insertanim, empty = empty})
|
||||
|
||||
if ret then
|
||||
insertcount = ret.count
|
||||
insertanim = ret.anim
|
||||
end
|
||||
|
||||
local load = self:GetCapacity() + math.min(self:Clip1(), self:GetChamberSize())
|
||||
if load - self:Clip1() > self:Ammo1() then load = self:Clip1() + self:Ammo1() end
|
||||
self:SetClipInfo(load)
|
||||
if game.SinglePlayer() then
|
||||
self:CallOnClient("SetClipInfo", tostring(load))
|
||||
end
|
||||
|
||||
local time = self:GetAnimKeyTime(insertanim, false)
|
||||
local time2 = self:GetAnimKeyTime(insertanim, true)
|
||||
|
||||
if time2 >= time then
|
||||
time2 = 0
|
||||
end
|
||||
|
||||
self:SetMagUpCount(insertcount)
|
||||
self:SetMagUpIn(CurTime() + time2 * mult)
|
||||
|
||||
self:SetReloading(CurTime() + time * mult)
|
||||
|
||||
self:PlayAnimation(insertanim, mult, true, 0, true, nil, true)
|
||||
self:SetShotgunReloading(empty and 4 or 2)
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:GetCapacity()
|
||||
local clip = self.RegularClipSize or self.Primary.ClipSize
|
||||
|
||||
if !self.RegularClipSize then
|
||||
self.RegularClipSize = self.Primary.ClipSize
|
||||
end
|
||||
|
||||
local level = 1
|
||||
|
||||
if self:GetBuff_Override("MagExtender") then
|
||||
level = level + 1
|
||||
end
|
||||
|
||||
if self:GetBuff_Override("MagReducer") then
|
||||
level = level - 1
|
||||
end
|
||||
|
||||
if level == 0 then
|
||||
clip = self.ReducedClipSize
|
||||
elseif level == 2 then
|
||||
clip = self.ExtendedClipSize
|
||||
end
|
||||
|
||||
clip = self:GetBuff("ClipSize", true, clip) or clip
|
||||
|
||||
local ret = self:GetBuff_Hook("Hook_GetCapacity", clip)
|
||||
|
||||
clip = ret or clip
|
||||
|
||||
clip = math.Clamp(math.Round(clip), 0, math.huge)
|
||||
|
||||
self.Primary.ClipSize = clip
|
||||
|
||||
return clip
|
||||
end
|
||||
|
||||
function SWEP:GetChamberSize()
|
||||
return self:GetBuff("ChamberSize") --(self:GetBuff_Override("Override_ChamberSize") or self.ChamberSize) + self:GetBuff_Add("Add_ChamberSize")
|
||||
end
|
||||
79
lua/weapons/arccw_base/sh_rocket.lua
Normal file
79
lua/weapons/arccw_base/sh_rocket.lua
Normal file
@@ -0,0 +1,79 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
function SWEP:FireRocket(ent, vel, ang, dontinheritvel)
|
||||
if CLIENT then return end
|
||||
|
||||
local rocket = ents.Create(ent)
|
||||
|
||||
ang = ang or (self:GetOwner():EyeAngles() + self:GetFreeAimOffset())
|
||||
|
||||
local src = self:GetShootSrc()
|
||||
|
||||
if !rocket:IsValid() then print("!!! INVALID ROUND " .. ent) return end
|
||||
|
||||
local rocketAng = Angle(ang.p, ang.y, ang.r)
|
||||
if ang and self.ShootEntityAngleCorrection then
|
||||
local up = ang:Up()
|
||||
local right = ang:Right()
|
||||
local forward = ang:Forward()
|
||||
rocketAng:RotateAroundAxis(up, self.ShootEntityAngleCorrection.y)
|
||||
rocketAng:RotateAroundAxis(right, self.ShootEntityAngleCorrection.p)
|
||||
rocketAng:RotateAroundAxis(forward, self.ShootEntityAngleCorrection.r)
|
||||
end
|
||||
|
||||
rocket:SetAngles(rocketAng)
|
||||
rocket:SetPos(src)
|
||||
|
||||
rocket:SetOwner(self:GetOwner())
|
||||
|
||||
rocket.Inflictor = self
|
||||
|
||||
local randfactor = self:GetBuff("DamageRand")
|
||||
local mul = 1
|
||||
if randfactor > 0 then
|
||||
mul = mul * math.Rand(1 - randfactor, 1 + randfactor)
|
||||
end
|
||||
rocket.Damage = self:GetBuff("Damage") * mul
|
||||
|
||||
if self.BlastRadius then
|
||||
local r_randfactor = self:GetBuff("DamageRand")
|
||||
local r_mul = 1
|
||||
if r_randfactor > 0 then
|
||||
r_mul = r_mul * math.Rand(1 - r_randfactor, 1 + r_randfactor)
|
||||
end
|
||||
rocket.BlastRadius = self:GetBuff("BlastRadius") * r_mul
|
||||
end
|
||||
|
||||
local RealVelocity = (!dontinheritvel and self:GetOwner():GetAbsVelocity() or Vector(0, 0, 0)) + ang:Forward() * vel
|
||||
rocket.CurVel = RealVelocity -- for non-physical projectiles that move themselves
|
||||
|
||||
rocket:Spawn()
|
||||
rocket:Activate()
|
||||
if !rocket.NoPhys and rocket:GetPhysicsObject():IsValid() then
|
||||
rocket:SetCollisionGroup(rocket.CollisionGroup or COLLISION_GROUP_DEBRIS)
|
||||
rocket:GetPhysicsObject():SetVelocityInstantaneous(RealVelocity)
|
||||
end
|
||||
|
||||
if rocket.Launch and rocket.SetState then
|
||||
rocket:SetState(1)
|
||||
rocket:Launch()
|
||||
end
|
||||
|
||||
if rocket.ArcCW_Killable == nil then
|
||||
rocket.ArcCW_Killable = true
|
||||
end
|
||||
|
||||
rocket.ArcCWProjectile = true
|
||||
|
||||
self:GetBuff_Hook("Hook_PostFireRocket", rocket)
|
||||
|
||||
return rocket
|
||||
end
|
||||
533
lua/weapons/arccw_base/sh_sights.lua
Normal file
533
lua/weapons/arccw_base/sh_sights.lua
Normal file
@@ -0,0 +1,533 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
SWEP.Sighted = false
|
||||
SWEP.Sprinted = false
|
||||
|
||||
local function linearlerp(a, b, c)
|
||||
return b + (c - b) * a
|
||||
end
|
||||
|
||||
function SWEP:GetSightTime()
|
||||
return self:GetBuff("SightTime")
|
||||
end
|
||||
|
||||
function SWEP:EnterSprint()
|
||||
if engine.ActiveGamemode() == "terrortown" and !(TTT2 and self:GetOwner().isSprinting) then return end
|
||||
if self:GetState() == ArcCW.STATE_SPRINT then return end
|
||||
if self:GetState() == ArcCW.STATE_CUSTOMIZE then return end
|
||||
if self:GetTriggerDelta() > 0 then return end
|
||||
if self:GetGrenadePrimed() and !self:CanShootWhileSprint() then return end
|
||||
self:SetState(ArcCW.STATE_SPRINT)
|
||||
self.Sighted = false
|
||||
self.Sprinted = true
|
||||
|
||||
local ct = CurTime()
|
||||
|
||||
-- self.SwayScale = 1
|
||||
-- self.BobScale = 5
|
||||
|
||||
self:SetShouldHoldType()
|
||||
|
||||
local s = self:CanShootWhileSprint()
|
||||
|
||||
if !s and self:GetNextPrimaryFire() <= ct then
|
||||
self:SetNextPrimaryFire(ct)
|
||||
end
|
||||
|
||||
local anim = self:SelectAnimation("enter_sprint")
|
||||
if anim and !s and self:GetNextSecondaryFire() <= ct then
|
||||
self:PlayAnimation(anim, self:GetBuff("SightTime") / self:GetAnimKeyTime(anim, true), true, nil, false, nil, false, false)
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:ExitSprint()
|
||||
if self:GetState() == ArcCW.STATE_IDLE then return end
|
||||
|
||||
local delta = self:GetNWSprintDelta()
|
||||
local ct = CurTime()
|
||||
|
||||
self:SetState(ArcCW.STATE_IDLE)
|
||||
self.Sighted = false
|
||||
self.Sprinted = false
|
||||
|
||||
-- self.SwayScale = 1
|
||||
-- self.BobScale = 1.5
|
||||
|
||||
self:SetShouldHoldType()
|
||||
|
||||
local s = self:CanShootWhileSprint()
|
||||
|
||||
if !s and self:GetNextPrimaryFire() <= ct then
|
||||
self:SetNextPrimaryFire(ct + self:GetSprintTime() * delta)
|
||||
end
|
||||
|
||||
if self:GetOwner():KeyDown(IN_ATTACK2) then
|
||||
self:EnterSights()
|
||||
end
|
||||
|
||||
local anim = self:SelectAnimation("exit_sprint")
|
||||
if anim and !s then -- and self:GetNextSecondaryFire() <= ct
|
||||
self:PlayAnimation(anim, self:GetBuff("SightTime") / self:GetAnimKeyTime(anim, true), true, nil, false, nil, false, false)
|
||||
end
|
||||
end
|
||||
|
||||
-- defined above already?
|
||||
|
||||
function SWEP:EnterSights()
|
||||
local asight = self:GetActiveSights()
|
||||
if !asight then return end
|
||||
if self:GetState() != ArcCW.STATE_IDLE then return end
|
||||
if self:GetCurrentFiremode().Mode == 0 then return end
|
||||
if !self.ReloadInSights and (self:GetReloading() or self:GetOwner():KeyDown(IN_RELOAD)) then return end
|
||||
if self.LockSightsInPriorityAnim and self:GetPriorityAnim() then return end
|
||||
if self:GetBuff_Hook("Hook_ShouldNotSight") then return end
|
||||
if (!game.SinglePlayer() and !IsFirstTimePredicted()) then return end
|
||||
|
||||
self:SetupActiveSights()
|
||||
|
||||
self:SetState(ArcCW.STATE_SIGHTS)
|
||||
self.Sighted = true
|
||||
self.Sprinted = false
|
||||
|
||||
self:SetShouldHoldType()
|
||||
|
||||
self:MyEmitSound(asight.SwitchToSound or "", 75, math.Rand(95, 105), 0.5, CHAN_AUTO)
|
||||
|
||||
local anim = self:SelectAnimation("enter_sight")
|
||||
if anim then
|
||||
self:PlayAnimation(anim, 1 * self:GetBuff_Mult("Mult_SightTime"), true)
|
||||
end
|
||||
|
||||
self:GetBuff_Hook("Hook_SightToggle", true)
|
||||
end
|
||||
|
||||
function SWEP:ExitSights()
|
||||
local asight = self:GetActiveSights()
|
||||
if self:GetState() != ArcCW.STATE_SIGHTS then return end
|
||||
if self.LockSightsInReload and self:GetReloading() then return end
|
||||
if self.LockSightsInPriorityAnim and self:GetPriorityAnim() then return end
|
||||
if (!game.SinglePlayer() and !IsFirstTimePredicted()) then return end
|
||||
|
||||
self:SetState(ArcCW.STATE_IDLE)
|
||||
self.Sighted = false
|
||||
self.Sprinted = false
|
||||
|
||||
self:SetShouldHoldType()
|
||||
|
||||
self:MyEmitSound(asight.SwitchFromSound or "", 75, math.Rand(80, 90), 0.5, CHAN_AUTO)
|
||||
|
||||
if self:InSprint() then
|
||||
self:EnterSprint()
|
||||
end
|
||||
|
||||
self:MyEmitSound(asight.SwitchFromSound or "", 75, math.Rand(80, 90), 0.5, CHAN_AUTO)
|
||||
|
||||
local anim = self:SelectAnimation("exit_sight")
|
||||
if anim then
|
||||
self:PlayAnimation(anim, 1 * self:GetBuff_Mult("Mult_SightTime"), true)
|
||||
end
|
||||
|
||||
self:GetBuff_Hook("Hook_SightToggle", false)
|
||||
end
|
||||
|
||||
function SWEP:GetSprintTime()
|
||||
return self:GetSightTime()
|
||||
end
|
||||
|
||||
SWEP.SightTable = {}
|
||||
SWEP.SightMagnifications = {}
|
||||
|
||||
function SWEP:SetupActiveSights()
|
||||
if !self.IronSightStruct then return end
|
||||
if self:GetBuff_Hook("Hook_ShouldNotSight") then return false end
|
||||
|
||||
if !self:GetOwner():IsPlayer() then return end
|
||||
|
||||
local sighttable = {}
|
||||
local vm = self:GetOwner():GetViewModel()
|
||||
|
||||
if !vm or !vm:IsValid() then return end
|
||||
|
||||
local kbi = self.KeepBaseIrons or true
|
||||
local bif = self.BaseIronsFirst or true
|
||||
|
||||
for i, k in pairs(self.Attachments) do
|
||||
if !k.Installed then continue end
|
||||
|
||||
local atttbl = ArcCW.AttachmentTable[k.Installed]
|
||||
|
||||
local addsights = self:GetBuff_Stat("AdditionalSights", i)
|
||||
if !addsights then continue end
|
||||
|
||||
if !k.KeepBaseIrons and !atttbl.KeepBaseIrons then kbi = false end
|
||||
if !k.BaseIronsFirst and !atttbl.BaseIronsFirst then bif = false end
|
||||
|
||||
for _, s in pairs(addsights) do
|
||||
local stab = table.Copy(s)
|
||||
|
||||
stab.Slot = i
|
||||
|
||||
if stab.HolosightData then atttbl = stab.HolosightData end
|
||||
|
||||
stab.HolosightData = atttbl
|
||||
|
||||
if atttbl.HolosightMagnification then
|
||||
stab.MagnifiedOptic = true
|
||||
stab.ScopeMagnification = atttbl.HolosightMagnification or 1
|
||||
|
||||
if atttbl.HolosightMagnificationMin then
|
||||
stab.ScopeMagnificationMin = atttbl.HolosightMagnificationMin
|
||||
stab.ScopeMagnificationMax = atttbl.HolosightMagnificationMax
|
||||
|
||||
stab.ScopeMagnification = math.max(stab.ScopeMagnificationMax, stab.ScopeMagnificationMin)
|
||||
|
||||
if !i and self.SightMagnifications[0] then
|
||||
stab.ScopeMagnification = self.SightMagnifications[0]
|
||||
elseif self.SightMagnifications[i] then
|
||||
stab.ScopeMagnification = self.SightMagnifications[i]
|
||||
end
|
||||
else
|
||||
stab.ScopeMagnification = atttbl.HolosightMagnification
|
||||
end
|
||||
end
|
||||
|
||||
if atttbl.Holosight then
|
||||
stab.Holosight = true
|
||||
end
|
||||
|
||||
if !k.Bone then return end
|
||||
|
||||
local boneid = vm:LookupBone(k.Bone)
|
||||
|
||||
if !boneid then return end
|
||||
|
||||
if CLIENT then
|
||||
|
||||
if atttbl.HolosightPiece then
|
||||
stab.HolosightPiece = (k.HSPElement or {}).Model
|
||||
end
|
||||
|
||||
if atttbl.Holosight then
|
||||
stab.HolosightModel = (k.VElement or {}).Model
|
||||
end
|
||||
|
||||
local bpos, bang = self:GetFromReference(boneid)
|
||||
|
||||
local offset
|
||||
local offset_ang
|
||||
|
||||
local vmang = Angle()
|
||||
|
||||
offset = k.Offset.vpos or Vector(0, 0, 0)
|
||||
|
||||
local attslot = k
|
||||
|
||||
local delta = attslot.SlidePos or 0.5
|
||||
|
||||
local vmelemod = nil
|
||||
local slidemod = nil
|
||||
|
||||
for _, e in pairs(self:GetActiveElements()) do
|
||||
local ele = self.AttachmentElements[e]
|
||||
|
||||
if !ele then continue end
|
||||
|
||||
if ((ele.AttPosMods or {})[i] or {}).vpos then
|
||||
vmelemod = ele.AttPosMods[i].vpos
|
||||
end
|
||||
|
||||
if ((ele.AttPosMods or {})[i] or {}).slide then
|
||||
slidemod = ele.AttPosMods[i].slide
|
||||
end
|
||||
|
||||
-- Refer to sh_model Line 837
|
||||
if ((ele.AttPosMods or {})[i] or {}).SlideAmount then
|
||||
slidemod = ele.AttPosMods[i].SlideAmount
|
||||
end
|
||||
end
|
||||
|
||||
offset = vmelemod or attslot.Offset.vpos or Vector()
|
||||
|
||||
if slidemod or attslot.SlideAmount then
|
||||
offset = LerpVector(delta, (slidemod or attslot.SlideAmount).vmin, (slidemod or attslot.SlideAmount).vmax)
|
||||
end
|
||||
|
||||
offset_ang = k.Offset.vang or Angle(0, 0, 0)
|
||||
offset_ang = offset_ang + (atttbl.OffsetAng or Angle(0, 0, 0))
|
||||
|
||||
offset_ang = k.VMOffsetAng or offset_ang
|
||||
|
||||
bpos, bang = WorldToLocal(Vector(0, 0, 0), Angle(0, 0, 0), bpos, bang)
|
||||
|
||||
bpos = bpos + bang:Forward() * offset.x
|
||||
bpos = bpos + bang:Right() * offset.y
|
||||
bpos = bpos + bang:Up() * offset.z
|
||||
|
||||
bang:RotateAroundAxis(bang:Right(), offset_ang.p)
|
||||
bang:RotateAroundAxis(bang:Up(), -offset_ang.y)
|
||||
bang:RotateAroundAxis(bang:Forward(), offset_ang.r)
|
||||
|
||||
local vpos = Vector()
|
||||
|
||||
vpos.y = -bpos.x
|
||||
vpos.x = bpos.y
|
||||
vpos.z = -bpos.z
|
||||
|
||||
local corpos = (k.CorrectivePos or Vector(0, 0, 0))
|
||||
|
||||
vpos = vpos + bang:Forward() * corpos.x
|
||||
vpos = vpos + bang:Right() * corpos.y
|
||||
vpos = vpos + bang:Up() * corpos.z
|
||||
|
||||
-- vpos = vpos + (bang:Forward() * s.Pos.x)
|
||||
-- vpos = vpos - (bang:Right() * s.Pos.y)
|
||||
-- vpos = vpos + (bang:Up() * s.Pos.z)
|
||||
|
||||
vmang:Set(-bang)
|
||||
|
||||
bang.r = -bang.r
|
||||
bang.p = -bang.p
|
||||
bang.y = -bang.y
|
||||
|
||||
corang = k.CorrectiveAng or Angle(0, 0, 0)
|
||||
|
||||
bang:RotateAroundAxis(bang:Right(), corang.p)
|
||||
bang:RotateAroundAxis(bang:Up(), corang.y)
|
||||
bang:RotateAroundAxis(bang:Forward(), corang.r)
|
||||
|
||||
-- vpos = LocalToWorld(s.Pos + Vector(0, self.ExtraSightDist or 0, 0), Angle(0, 0, 0), vpos, bang)
|
||||
|
||||
-- local vmf = (vmang):Forward():GetNormalized()
|
||||
-- local vmr = (vmang):Right():GetNormalized()
|
||||
-- local vmu = (vmang):Up():GetNormalized()
|
||||
|
||||
-- print(" ----- vmf, vmr, vmu")
|
||||
-- print(vmf)
|
||||
-- print(vmr)
|
||||
-- print(vmu)
|
||||
|
||||
-- vmf = -vmf
|
||||
-- vmf.x = -vmf.x
|
||||
|
||||
-- local r = vmf.y
|
||||
-- vmf.y = vmf.z
|
||||
-- vmf.z = r
|
||||
|
||||
-- vmr = -vmr
|
||||
-- vmr.y = -vmr.y
|
||||
|
||||
-- -- local r = vmr.y
|
||||
-- -- vmr.y = vmr.z
|
||||
-- -- vmr.z = r
|
||||
|
||||
-- vmu = -vmu
|
||||
-- vmu.z = vmu.z
|
||||
|
||||
-- local evpos = Vector(0, 0, 0)
|
||||
|
||||
-- evpos = evpos + (vmf * (s.Pos.x + k.CorrectivePos.x))
|
||||
-- evpos = evpos - (vmr * (s.Pos.y + (self.ExtraSightDist or 0) + k.CorrectivePos.y))
|
||||
-- evpos = evpos + (vmu * (s.Pos.z + k.CorrectivePos.z))
|
||||
|
||||
-- print(vmang:Forward())
|
||||
|
||||
local evpos = s.Pos
|
||||
|
||||
evpos = evpos * (k.VMScale or Vector(1, 1, 1))
|
||||
|
||||
if atttbl.Holosight and !atttbl.HolosightMagnification then
|
||||
evpos = evpos + Vector(0, k.ExtraSightDist or self.ExtraSightDist or 0, 0)
|
||||
end
|
||||
|
||||
evpos = evpos + (k.CorrectivePos or Vector(0, 0, 0))
|
||||
|
||||
stab.Pos, stab.Ang = vpos, bang
|
||||
|
||||
stab.EVPos = evpos
|
||||
stab.EVAng = s.Ang
|
||||
|
||||
if s.GlobalPos then
|
||||
stab.EVPos = Vector(0, 0, 0)
|
||||
stab.Pos = s.Pos
|
||||
end
|
||||
|
||||
if s.GlobalAng then
|
||||
stab.Ang = Angle(0, 0, 0)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
table.insert(sighttable, stab)
|
||||
end
|
||||
end
|
||||
|
||||
if kbi then
|
||||
local extra = self.ExtraIrons
|
||||
if extra then
|
||||
for _, ot in pairs(extra) do
|
||||
local t = table.Copy(ot)
|
||||
t.IronSight = true
|
||||
if bif then
|
||||
table.insert(sighttable, 1, t)
|
||||
else
|
||||
table.insert(sighttable, t)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local t = table.Copy(self:GetBuff_Override("Override_IronSightStruct") or self.IronSightStruct)
|
||||
t.IronSight = true
|
||||
if bif then
|
||||
table.insert(sighttable, 1, t)
|
||||
else
|
||||
table.insert(sighttable, t)
|
||||
end
|
||||
end
|
||||
|
||||
self.SightTable = sighttable
|
||||
end
|
||||
|
||||
function SWEP:SwitchActiveSights()
|
||||
if table.Count(self.SightTable) == 1 then return end
|
||||
|
||||
self.ActiveSight = (self.ActiveSight or 1) + 1
|
||||
|
||||
if self.ActiveSight > table.Count(self.SightTable) then
|
||||
self.ActiveSight = 1
|
||||
end
|
||||
|
||||
local asight = self:GetActiveSights()
|
||||
|
||||
local tbl = self:GetBuff_Hook("Hook_SwitchActiveSights", {active = self.ActiveSight, asight = asight})
|
||||
|
||||
self.ActiveSight = tbl.active or self.ActiveSight
|
||||
|
||||
if self.ActiveSight > table.Count(self.SightTable) then
|
||||
self.ActiveSight = 1
|
||||
end
|
||||
|
||||
local asight2 = self:GetActiveSights()
|
||||
|
||||
if asight2.SwitchToSound then
|
||||
self:MyEmitSound(asight2.SwitchToSound, 75, math.Rand(95, 105), 0.5, CHAN_VOICE2)
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:GetActiveSights()
|
||||
if (self.ActiveSight or 1) > table.Count(self.SightTable) then
|
||||
self.ActiveSight = 1
|
||||
end
|
||||
|
||||
if table.Count(self.SightTable) == 0 then
|
||||
return self.IronSightStruct
|
||||
else
|
||||
return self.SightTable[self.ActiveSight or 1]
|
||||
end
|
||||
end
|
||||
|
||||
local function ScaleFOVByWidthRatio( fovDegrees, ratio )
|
||||
local halfAngleRadians = fovDegrees * ( 0.5 * math.pi / 180 )
|
||||
local t = math.tan( halfAngleRadians )
|
||||
t = t * ratio
|
||||
local retDegrees = ( 180 / math.pi ) * math.atan( t )
|
||||
return retDegrees * 2
|
||||
end
|
||||
|
||||
function SWEP:QuickFOVix( fov )
|
||||
return ScaleFOVByWidthRatio( fov, (ScrW and ScrW() or 4)/(ScrH and ScrH() or 3)/(4/3) )
|
||||
end
|
||||
|
||||
SWEP.LastTranslateFOV = 0
|
||||
function SWEP:TranslateFOV(fov)
|
||||
local irons = self:GetActiveSights()
|
||||
|
||||
if CLIENT and ArcCW.ConVars["dev_benchgun"]:GetBool() then self.CurrentFOV = fov self.CurrentViewModelFOV = fov return fov end
|
||||
|
||||
self.ApproachFOV = self.ApproachFOV or fov
|
||||
self.CurrentFOV = self.CurrentFOV or fov
|
||||
|
||||
-- Only update every tick (this function is called multiple times per tick)
|
||||
if self.LastTranslateFOV == UnPredictedCurTime() then return self.CurrentFOV end
|
||||
local timed = UnPredictedCurTime() - self.LastTranslateFOV
|
||||
self.LastTranslateFOV = UnPredictedCurTime()
|
||||
|
||||
local app_vm = self.ViewModelFOV + self:GetOwner():GetInfoNum("arccw_vm_fov", 0)
|
||||
if CLIENT then
|
||||
app_vm = app_vm * (LocalPlayer():GetFOV()/GetConVar("fov_desired"):GetInt())
|
||||
end
|
||||
|
||||
if self:GetState() == ArcCW.STATE_SIGHTS then
|
||||
local asight = self:GetActiveSights()
|
||||
local mag = asight and asight.ScopeMagnification or 1
|
||||
|
||||
local delta = math.pow(self:GetSightDelta(), 2)
|
||||
|
||||
if CLIENT then
|
||||
local addads = math.Clamp(ArcCW.ConVars["vm_add_ads"]:GetFloat() or 0, -2, 14)
|
||||
local csratio = math.Clamp(GetConVar("arccw_cheapscopesv2_ratio"):GetFloat() or 0, 0, 1)
|
||||
local pfov = GetConVar("fov_desired"):GetInt()
|
||||
|
||||
if ArcCW.ConVars["cheapscopes"]:GetBool() and mag > 1 then
|
||||
fov = (pfov / (asight and asight.Magnification or 1)) / (mag / (1 + csratio * mag) + (addads or 0) / 3)
|
||||
else
|
||||
fov = ( (pfov / (asight and asight.Magnification or 1)) * (1 - delta)) + (GetConVar("fov_desired"):GetInt() * delta)
|
||||
end
|
||||
|
||||
app_vm = irons.ViewModelFOV or 45
|
||||
|
||||
app_vm = app_vm - (asight.MagnifiedOptic and (addads or 0) * 3 or 0)
|
||||
end
|
||||
end
|
||||
|
||||
self.ApproachFOV = fov
|
||||
|
||||
-- magic number? multiplier of 10 seems similar to previous behavior
|
||||
self.CurrentFOV = math.Approach(self.CurrentFOV, self.ApproachFOV, timed * 10 * (self.CurrentFOV - self.ApproachFOV))
|
||||
|
||||
self.CurrentViewModelFOV = self.CurrentViewModelFOV or self.ViewModelFOV
|
||||
self.CurrentViewModelFOV = math.Approach(self.CurrentViewModelFOV, app_vm, timed * 10 * (self.CurrentViewModelFOV - app_vm))
|
||||
|
||||
return self.CurrentFOV
|
||||
end
|
||||
|
||||
function SWEP:SetShouldHoldType()
|
||||
if self:GetCurrentFiremode().Mode == 0 then
|
||||
self:SetHoldType(self.HoldtypeHolstered)
|
||||
return
|
||||
end
|
||||
|
||||
if IsValid(self:GetOwner()) and self:GetOwner():IsNPC() and self.HoldtypeNPC then
|
||||
self:SetHoldType(self.HoldtypeNPC)
|
||||
return
|
||||
end
|
||||
|
||||
local ht = "normal"
|
||||
|
||||
if self:GetState() == ArcCW.STATE_SIGHTS then
|
||||
ht = self:GetBuff_Override("Override_HoldtypeSights", self.HoldtypeSights)
|
||||
elseif self:GetState() == ArcCW.STATE_SPRINT then
|
||||
if self:CanShootWhileSprint() then
|
||||
ht = self:GetBuff_Override("Override_HoldtypeSprintShoot", self.HoldtypeSprintShoot) or self:GetBuff_Override("Override_HoldtypeActive", self.HoldtypeActive)
|
||||
else
|
||||
ht = self:GetBuff_Override("Override_HoldtypeHolstered", self.HoldtypeHolstered)
|
||||
end
|
||||
elseif self:GetState() == ArcCW.STATE_CUSTOMIZE then
|
||||
ht = self:GetBuff_Override("Override_HoldtypeCustomize", self.HoldtypeCustomize)
|
||||
elseif self:GetCurrentFiremode().Mode == 0 then
|
||||
ht = self:GetBuff_Override("Override_HoldtypeHolstered", self.HoldtypeHolstered)
|
||||
elseif self.Throwing and self:GetGrenadePrimed() then
|
||||
ht = self:GetBuff_Override("Override_HoldtypeSights", self.HoldtypeSights)
|
||||
else
|
||||
ht = self:GetBuff_Override("Override_HoldtypeActive", self.HoldtypeActive)
|
||||
end
|
||||
|
||||
self:SetHoldType(ht)
|
||||
end
|
||||
445
lua/weapons/arccw_base/sh_think.lua
Normal file
445
lua/weapons/arccw_base/sh_think.lua
Normal file
@@ -0,0 +1,445 @@
|
||||
--[[
|
||||
| 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
|
||||
178
lua/weapons/arccw_base/sh_timers.lua
Normal file
178
lua/weapons/arccw_base/sh_timers.lua
Normal file
@@ -0,0 +1,178 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
local tbl = table
|
||||
local tbl_ins = tbl.insert
|
||||
|
||||
local tick = 0
|
||||
|
||||
function SWEP:InitTimers()
|
||||
self.ActiveTimers = {} -- { { time, id, func } }
|
||||
end
|
||||
|
||||
function SWEP:SetTimer(time, callback, id)
|
||||
if !IsFirstTimePredicted() then return end
|
||||
|
||||
tbl_ins(self.ActiveTimers, { time + CurTime(), id or "", callback })
|
||||
end
|
||||
|
||||
function SWEP:TimerExists(id)
|
||||
for _, v in pairs(self.ActiveTimers) do
|
||||
if v[2] == id then return true end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function SWEP:KillTimer(id)
|
||||
local keeptimers = {}
|
||||
|
||||
for _, v in pairs(self.ActiveTimers) do
|
||||
if v[2] != id then tbl_ins(keeptimers, v) end
|
||||
end
|
||||
|
||||
self.ActiveTimers = keeptimers
|
||||
end
|
||||
|
||||
function SWEP:KillTimers()
|
||||
self.ActiveTimers = {}
|
||||
end
|
||||
|
||||
function SWEP:ProcessTimers()
|
||||
local keeptimers, UCT = {}, CurTime()
|
||||
|
||||
if CLIENT and UCT == tick then return end
|
||||
|
||||
if !self.ActiveTimers then self:InitTimers() end
|
||||
|
||||
for _, v in pairs(self.ActiveTimers) do
|
||||
if v[1] <= UCT then v[3]() end
|
||||
end
|
||||
|
||||
for _, v in pairs(self.ActiveTimers) do
|
||||
if v[1] > UCT then tbl_ins(keeptimers, v) end
|
||||
end
|
||||
|
||||
self.ActiveTimers = keeptimers
|
||||
end
|
||||
|
||||
local function DoShell(wep, data)
|
||||
if !(IsValid(wep) and IsValid(wep:GetOwner())) then return end
|
||||
|
||||
local att = data.att or wep:GetBuff_Override("Override_CaseEffectAttachment") or wep.CaseEffectAttachment or 2
|
||||
|
||||
if !att then return end
|
||||
|
||||
local getatt = wep:GetAttachment(att)
|
||||
|
||||
if !getatt then return end
|
||||
|
||||
local pos, ang = getatt.Pos, getatt.Ang
|
||||
|
||||
local ed = EffectData()
|
||||
ed:SetOrigin(pos)
|
||||
ed:SetAngles(ang)
|
||||
ed:SetAttachment(att)
|
||||
ed:SetScale(1)
|
||||
ed:SetEntity(wep)
|
||||
ed:SetNormal(ang:Forward())
|
||||
ed:SetMagnitude(data.mag or 100)
|
||||
|
||||
util.Effect(data.e, ed)
|
||||
end
|
||||
|
||||
function SWEP:PlaySoundTable(soundtable, mult, start, key)
|
||||
--if CLIENT and game.SinglePlayer() then return end
|
||||
|
||||
local owner = self:GetOwner()
|
||||
|
||||
start = start or 0
|
||||
mult = 1 / (mult or 1)
|
||||
|
||||
for _, v in pairs(soundtable) do
|
||||
if table.IsEmpty(v) then continue end
|
||||
|
||||
local ttime
|
||||
if v.t then
|
||||
ttime = (v.t * mult) - start
|
||||
else
|
||||
continue
|
||||
end
|
||||
if ttime < 0 then continue end
|
||||
if !(IsValid(self) and IsValid(owner)) then continue end
|
||||
|
||||
local jhon = CurTime() + ttime
|
||||
|
||||
--[[if game.SinglePlayer() then
|
||||
if SERVER then
|
||||
net.Start("arccw_networksound")
|
||||
v.ntttime = ttime
|
||||
net.WriteTable(v)
|
||||
net.WriteEntity(self)
|
||||
net.Send(owner)
|
||||
end
|
||||
end]]
|
||||
|
||||
-- i may go fucking insane
|
||||
if !self.EventTable[1] then self.EventTable[1] = {} end
|
||||
|
||||
for i, de in ipairs(self.EventTable) do
|
||||
if de[jhon] then
|
||||
if !self.EventTable[i + 1] then
|
||||
--[[print(CurTime(), "Occupier at " .. i .. ", creating " .. i+1)]]
|
||||
self.EventTable[i + 1] = {}
|
||||
continue
|
||||
end
|
||||
else
|
||||
self.EventTable[i][jhon] = table.Copy(v)
|
||||
self.EventTable[i][jhon].StartTime = CurTime()
|
||||
self.EventTable[i][jhon].AnimKey = key
|
||||
-- print(CurTime(), "Clean at " .. i)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:PlayEvent(v)
|
||||
if !v or !istable(v) then error("no event to play") end
|
||||
v = self:GetBuff_Hook("Hook_PrePlayEvent", v) or v
|
||||
if v.e and IsFirstTimePredicted() then
|
||||
DoShell(self, v)
|
||||
end
|
||||
|
||||
if v.s then
|
||||
if v.s_km then
|
||||
self:StopSound(v.s)
|
||||
end
|
||||
self:MyEmitSound(v.s, v.l, v.p, v.v, v.c or CHAN_AUTO)
|
||||
end
|
||||
|
||||
if v.bg then
|
||||
self:SetBodygroupTr(v.ind or 0, v.bg)
|
||||
end
|
||||
|
||||
if v.pp then
|
||||
local vm = self:GetOwner():GetViewModel()
|
||||
|
||||
vm:SetPoseParameter(pp, ppv)
|
||||
end
|
||||
|
||||
v = self:GetBuff_Hook("Hook_PostPlayEvent", v) or v
|
||||
end
|
||||
|
||||
|
||||
if CLIENT then
|
||||
net.Receive("arccw_networksound", function(len)
|
||||
local v = net.ReadTable()
|
||||
local wep = net.ReadEntity()
|
||||
|
||||
wep.EventTable[CurTime() + v.ntttime] = v
|
||||
end)
|
||||
end
|
||||
153
lua/weapons/arccw_base/sh_ttt.lua
Normal file
153
lua/weapons/arccw_base/sh_ttt.lua
Normal file
@@ -0,0 +1,153 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
function SWEP:OnRestore()
|
||||
end
|
||||
|
||||
function SWEP:GetHeadshotMultiplier(victim, dmginfo)
|
||||
return 2.5 -- Hey hey hey, don't forget about me!!!
|
||||
end
|
||||
|
||||
function SWEP:IsEquipment()
|
||||
return WEPS.IsEquipment(self)
|
||||
end
|
||||
|
||||
SWEP.IsSilent = false
|
||||
|
||||
-- The OnDrop() hook is useless for this as it happens AFTER the drop. OwnerChange
|
||||
-- does not occur when a drop happens for some reason. Hence this thing.
|
||||
function SWEP:PreDrop()
|
||||
if self.Throwing then
|
||||
if self:GetGrenadePrimed() then
|
||||
self:Throw()
|
||||
end
|
||||
else
|
||||
if SERVER and IsValid(self:GetOwner()) and self.Primary.Ammo != "none" then
|
||||
local ammo = self:Ammo1()
|
||||
|
||||
-- Do not drop ammo if we have another gun that uses this type
|
||||
for _, w in ipairs(self:GetOwner():GetWeapons()) do
|
||||
if IsValid(w) and w != self and w:GetPrimaryAmmoType() == self:GetPrimaryAmmoType() then
|
||||
ammo = 0
|
||||
end
|
||||
end
|
||||
|
||||
self.StoredAmmo = ammo
|
||||
|
||||
if ammo > 0 then
|
||||
self:GetOwner():RemoveAmmo(ammo, self.Primary.Ammo)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
net.Start("arccw_togglecustomize")
|
||||
net.WriteBool(false)
|
||||
net.Send(self:GetOwner())
|
||||
self:ToggleCustomizeHUD(false)
|
||||
end
|
||||
|
||||
function SWEP:DampenDrop()
|
||||
-- For some reason gmod drops guns on death at a speed of 400 units, which
|
||||
-- catapults them away from the body. Here we want people to actually be able
|
||||
-- to find a given corpse's weapon, so we override the velocity here and call
|
||||
-- this when dropping guns on death.
|
||||
local phys = self:GetPhysicsObject()
|
||||
if IsValid(phys) then
|
||||
phys:SetVelocityInstantaneous(Vector(0,0,-75) + phys:GetVelocity() * 0.001)
|
||||
phys:AddAngleVelocity(phys:GetAngleVelocity() * -0.99)
|
||||
end
|
||||
end
|
||||
|
||||
SWEP.StoredAmmo = 0
|
||||
|
||||
-- Picked up by player. Transfer of stored ammo and such.
|
||||
function SWEP:Equip(newowner)
|
||||
if SERVER then
|
||||
if self:IsOnFire() then
|
||||
self:Extinguish()
|
||||
end
|
||||
|
||||
self.fingerprints = self.fingerprints or {}
|
||||
|
||||
if !table.HasValue(self.fingerprints, newowner) then
|
||||
table.insert(self.fingerprints, newowner)
|
||||
end
|
||||
end
|
||||
|
||||
if SERVER and IsValid(newowner) and self.StoredAmmo > 0 and self.Primary.Ammo != "none" then
|
||||
local ammo = newowner:GetAmmoCount(self.Primary.Ammo)
|
||||
local given = math.min(self.StoredAmmo, self.Primary.ClipMax - ammo)
|
||||
|
||||
newowner:GiveAmmo( given, self.Primary.Ammo)
|
||||
self.StoredAmmo = 0
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:WasBought(buyer)
|
||||
if self.TTT_DoNotAttachOnBuy then return end
|
||||
|
||||
for i, k in pairs(self.Attachments) do
|
||||
k.RandomChance = 100
|
||||
end
|
||||
-- if ArcCW.ConVars["ttt_atts"]:GetBool() then
|
||||
-- self:NPC_SetupAttachments()
|
||||
-- end
|
||||
end
|
||||
|
||||
function SWEP:TTT_PostAttachments()
|
||||
self.IsSilent = self:GetBuff_Override("Silencer")
|
||||
|
||||
if !self.IsSilent then
|
||||
self.IsSilent = true
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:TTT_Init()
|
||||
if engine.ActiveGamemode() != "terrortown" then return end
|
||||
|
||||
if SERVER then
|
||||
self.fingerprints = {}
|
||||
end
|
||||
|
||||
if self.Throwing then
|
||||
self.Primary.ClipMax = 0
|
||||
end
|
||||
|
||||
if ArcCW.ConVars["ttt_atts"]:GetBool() then
|
||||
if SERVER then
|
||||
self:NPC_SetupAttachments()
|
||||
end
|
||||
elseif !IsValid(self:GetOwner()) then
|
||||
-- If attachments aren't randomized, client will not need to ask for att info.
|
||||
self.CertainAboutAtts = true
|
||||
end
|
||||
|
||||
if self.ForgetDefaultBehavior then return end
|
||||
|
||||
self.Primary.ClipMax = ArcCW.TTTAmmoToClipMax[self.Primary.Ammo] or self.RegularClipSize * 2 or self.Primary.ClipSize * 2
|
||||
|
||||
-- This will overwrite mag reducers, so give it a bit of time
|
||||
timer.Simple(0.1, function()
|
||||
if !IsValid(self) then return end
|
||||
self:SetClip1(self:GetCapacity() or self.RegularClipSize or self.Primary.ClipSize)
|
||||
self.Primary.DefaultClip = self.ForceDefaultAmmo or self.ForceDefaultClip or self:GetCapacity()
|
||||
end)
|
||||
|
||||
if self.Throwing and self.Primary.Ammo and !self.ForceDefaultClip then
|
||||
self.Primary.Ammo = "none"
|
||||
self.Primary.DefaultClip = 0
|
||||
self:SetClip1(-1)
|
||||
self.Singleton = true
|
||||
end
|
||||
end
|
||||
|
||||
--- TTT2 uses this to populate custom convars in the equip menu
|
||||
function SWEP:AddToSettingsMenu(parent)
|
||||
end
|
||||
173
lua/weapons/arccw_base/sh_ubgl.lua
Normal file
173
lua/weapons/arccw_base/sh_ubgl.lua
Normal file
@@ -0,0 +1,173 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
|
||||
function SWEP:SelectUBGL()
|
||||
if !self:GetBuff_Override("UBGL") then return end
|
||||
if self:GetReloading() then return end
|
||||
if self:GetNextPrimaryFire() > CurTime() then return end
|
||||
if self:GetNextSecondaryFire() > CurTime() then return end
|
||||
if self:GetUBGLDebounce() then return end
|
||||
self:SetUBGLDebounce( true )
|
||||
|
||||
self:SetInUBGL(true)
|
||||
|
||||
self:SetFireMode(1)
|
||||
|
||||
if CLIENT and (game.SinglePlayer() or (!game.SinglePlayer() and IsFirstTimePredicted())) then
|
||||
-- if !ArcCW:ShouldDrawHUDElement("CHudAmmo") then
|
||||
-- self:GetOwner():ChatPrint("Selected " .. self:GetBuff_Override("UBGL_PrintName") or "UBGL")
|
||||
-- end
|
||||
if !self:GetLHIKAnim() then
|
||||
self:DoLHIKAnimation("enter")
|
||||
end
|
||||
self:MyEmitSound( self:GetBuff_Override("SelectUBGLSound") or self.SelectUBGLSound )
|
||||
end
|
||||
|
||||
if self:GetBuff_Override("UBGL_BaseAnims") and self.Animations.enter_ubgl_empty and self:Clip2() == 0 then
|
||||
self:PlayAnimation("enter_ubgl_empty", 1, true)
|
||||
self:SetNextSecondaryFire(CurTime() + self:GetAnimKeyTime("enter_ubgl_empty"))
|
||||
elseif self:GetBuff_Override("UBGL_BaseAnims") and self.Animations.enter_ubgl then
|
||||
self:PlayAnimation("enter_ubgl", 1, true)
|
||||
self:SetNextSecondaryFire(CurTime() + self:GetAnimKeyTime("enter_ubgl"))
|
||||
else
|
||||
self:PlayAnimationEZ("idle", 1, false)
|
||||
self:SetNextSecondaryFire(CurTime() + 0.1)
|
||||
end
|
||||
|
||||
self:GetBuff_Hook("Hook_OnSelectUBGL")
|
||||
end
|
||||
|
||||
function SWEP:DeselectUBGL()
|
||||
if !self:GetInUBGL() then return end
|
||||
if self:GetReloading() then return end
|
||||
if self:GetNextPrimaryFire() > CurTime() then return end
|
||||
if self:GetNextSecondaryFire() > CurTime() then return end
|
||||
if self:GetUBGLDebounce() then return end
|
||||
self:SetUBGLDebounce( true )
|
||||
|
||||
self:SetInUBGL(false)
|
||||
|
||||
if CLIENT and (game.SinglePlayer() or (!game.SinglePlayer() and IsFirstTimePredicted())) then
|
||||
-- if !ArcCW:ShouldDrawHUDElement("CHudAmmo") then
|
||||
-- self:GetOwner():ChatPrint("Deselected " .. self:GetBuff_Override("UBGL_PrintName") or "UBGL")
|
||||
-- end
|
||||
if !self:GetLHIKAnim() and bong then
|
||||
self:DoLHIKAnimation("exit")
|
||||
end
|
||||
self:MyEmitSound( self:GetBuff_Override("ExitUBGLSound") or self.ExitUBGLSound )
|
||||
end
|
||||
|
||||
if self:GetBuff_Override("UBGL_BaseAnims") and self.Animations.exit_ubgl_empty and self:Clip2() == 0 then
|
||||
self:PlayAnimation("exit_ubgl_empty", 1, true)
|
||||
elseif self:GetBuff_Override("UBGL_BaseAnims") and self.Animations.exit_ubgl then
|
||||
self:PlayAnimation("exit_ubgl", 1, true)
|
||||
else
|
||||
self:PlayAnimationEZ("idle", 1, false)
|
||||
self:SetNextSecondaryFire(CurTime() + 0.1)
|
||||
end
|
||||
|
||||
self:GetBuff_Hook("Hook_OnDeselectUBGL")
|
||||
end
|
||||
|
||||
function SWEP:RecoilUBGL()
|
||||
local single = game.SinglePlayer()
|
||||
|
||||
if !single and !IsFirstTimePredicted() then return end
|
||||
|
||||
if single and self:GetOwner():IsValid() and SERVER then self:CallOnClient("RecoilUBGL") end
|
||||
|
||||
local amt = self:GetBuff_Override("UBGL_Recoil")
|
||||
local amtside = self:GetBuff_Override("UBGL_RecoilSide") or (self:GetBuff_Override("UBGL_Recoil") * 0.5)
|
||||
local amtrise = self:GetBuff_Override("UBGL_RecoilRise") or 1
|
||||
|
||||
local r = math.Rand(-1, 1)
|
||||
local ru = math.Rand(0.75, 1.25)
|
||||
|
||||
local m = 1 * amt
|
||||
local rs = 1 * amtside
|
||||
local vsm = 1
|
||||
|
||||
local vpa = Angle(0, 0, 0)
|
||||
|
||||
vpa = vpa + (Angle(1, 0, 0) * amt * m * vsm)
|
||||
|
||||
vpa = vpa + (Angle(0, 1, 0) * r * amtside * m * vsm)
|
||||
|
||||
if CLIENT then
|
||||
self:OurViewPunch(vpa)
|
||||
end
|
||||
|
||||
if CLIENT or game.SinglePlayer() then
|
||||
|
||||
self.RecoilAmount = self.RecoilAmount + (amt * m)
|
||||
self.RecoilAmountSide = self.RecoilAmountSide + (r * amtside * m * rs)
|
||||
|
||||
self.RecoilPunchBack = amt * 2.5 * m
|
||||
|
||||
if self.MaxRecoilBlowback > 0 then
|
||||
self.RecoilPunchBack = math.Clamp(self.RecoilPunchBack, 0, self.MaxRecoilBlowback)
|
||||
end
|
||||
|
||||
self.RecoilPunchSide = r * rs * m * 0.1 * vsm
|
||||
self.RecoilPunchUp = math.Clamp(ru * amt * m * 0.6 * vsm * amtrise, 0, 0.1)
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:ShootUBGL()
|
||||
if self:GetNextSecondaryFire() > CurTime() then return end
|
||||
if self:GetState() == ArcCW.STATE_SPRINT and !self:CanShootWhileSprint() then return false end
|
||||
|
||||
self.Primary.Automatic = self:GetBuff_Override("UBGL_Automatic")
|
||||
|
||||
local ubglammo = self:GetBuff_Override("UBGL_Ammo")
|
||||
|
||||
if self:Clip2() <= 0 and self:GetOwner():GetAmmoCount(ubglammo) <= 0 then
|
||||
self:DeselectUBGL()
|
||||
return
|
||||
end
|
||||
|
||||
if self:Clip2() <= 0 then
|
||||
return
|
||||
end
|
||||
|
||||
self:RecoilUBGL()
|
||||
|
||||
local func, slot = self:GetBuff_Override("UBGL_Fire")
|
||||
|
||||
if func then
|
||||
func(self, self.Attachments[slot].VElement)
|
||||
end
|
||||
|
||||
self:SetNextSecondaryFire(CurTime() + (60 / self:GetBuff_Override("UBGL_RPM")))
|
||||
end
|
||||
|
||||
function SWEP:ReloadUBGL()
|
||||
if self:GetNextSecondaryFire() > CurTime() then return end
|
||||
|
||||
local reloadfunc, slot = self:GetBuff_Override("UBGL_Reload")
|
||||
|
||||
if reloadfunc then
|
||||
reloadfunc(self, self.Attachments[slot].VElement)
|
||||
end
|
||||
end
|
||||
|
||||
if SERVER then
|
||||
|
||||
function SWEP:DoLHIKAnimation(key, time)
|
||||
if game.SinglePlayer() then
|
||||
net.Start("arccw_sp_lhikanim")
|
||||
net.WriteString(key)
|
||||
net.WriteFloat(time or -1)
|
||||
net.Send(self:GetOwner())
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
29
lua/weapons/arccw_base/sh_util.lua
Normal file
29
lua/weapons/arccw_base/sh_util.lua
Normal file
@@ -0,0 +1,29 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
function SWEP:TableRandom(table)
|
||||
return table[math.random(#table)]
|
||||
end
|
||||
|
||||
function SWEP:MyEmitSound(fsound, level, pitch, vol, chan, useWorld)
|
||||
if !fsound then return end
|
||||
|
||||
fsound = self:GetBuff_Hook("Hook_TranslateSound", fsound) or fsound
|
||||
|
||||
if istable(fsound) then fsound = self:TableRandom(fsound) end
|
||||
|
||||
if fsound and fsound != "" then
|
||||
if useWorld then
|
||||
sound.Play(fsound, self:GetOwner():GetShootPos(), level, pitch, vol)
|
||||
else
|
||||
self:EmitSound(fsound, level, pitch, vol, chan or CHAN_AUTO)
|
||||
end
|
||||
end
|
||||
end
|
||||
1000
lua/weapons/arccw_base/shared.lua
Normal file
1000
lua/weapons/arccw_base/shared.lua
Normal file
File diff suppressed because it is too large
Load Diff
415
lua/weapons/arccw_base/sv_npc.lua
Normal file
415
lua/weapons/arccw_base/sv_npc.lua
Normal file
@@ -0,0 +1,415 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
-- NPC integration
|
||||
|
||||
function SWEP:NPC_Initialize()
|
||||
if CLIENT then return end
|
||||
|
||||
if !IsValid(self:GetOwner()) then return end
|
||||
if !self:GetOwner():IsNPC() then return end
|
||||
|
||||
self:NPC_SetupAttachments()
|
||||
|
||||
self:SetHoldType(self.HoldtypeNPC or self:GetBuff_Override("Override_HoldtypeActive") or self.HoldtypeActive)
|
||||
|
||||
self:SetNextPrimaryFire(CurTime())
|
||||
|
||||
self:SetClip1(self:GetCapacity() or self.Primary.ClipSize)
|
||||
|
||||
-- print(self:Clip1())
|
||||
|
||||
local range = self:GetBuff("Range") / ArcCW.HUToM
|
||||
|
||||
if self:GetBuff("DamageMin") >= self:GetBuff("Damage") or (self:GetBuff_Override("Override_ManualAction") or self.ManualAction) and self:GetBuff("Num") == 1 then
|
||||
range = math.max(range, 10000) * 2
|
||||
end
|
||||
|
||||
range = math.Clamp(range, 2048, 36000)
|
||||
|
||||
self:GetOwner():Input("SetMaxLookDistance", nil, nil, range)
|
||||
|
||||
self:SetNextPrimaryFire(CurTime())
|
||||
self:SetNextSecondaryFire(CurTime() + 30)
|
||||
self:GetOwner():NextThink(CurTime())
|
||||
end
|
||||
|
||||
function SWEP:AssignRandomAttToSlot(slot)
|
||||
if slot.DoNotRandomize then return end
|
||||
if slot.Installed then return end
|
||||
|
||||
local att = ArcCW:RollRandomAttachment(true, self, slot)
|
||||
if !att then return end
|
||||
slot.Installed = att
|
||||
|
||||
local atttbl = ArcCW.AttachmentTable[slot.Installed]
|
||||
|
||||
--if !ArcCW:SlotAcceptsAtt(slot.Slot, self, slot.Installed) then return end
|
||||
--if !self:CheckFlags(atttbl.ExcludeFlags, atttbl.RequireFlags) then return end
|
||||
|
||||
if atttbl.MountPositionOverride then
|
||||
slot.SlidePos = atttbl.MountPositionOverride
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:NPC_SetupAttachments()
|
||||
if self:GetOwner():IsNPC() and !ArcCW.ConVars["npc_atts"]:GetBool() then return end
|
||||
|
||||
local pick = self:GetPickX()
|
||||
|
||||
local chance = 25 * ArcCW.ConVars["mult_attchance"]:GetFloat()
|
||||
local chancestep = 0
|
||||
|
||||
if pick > 0 then
|
||||
chancestep = chance / pick
|
||||
--chance = chancestep
|
||||
else
|
||||
pick = 1000
|
||||
end
|
||||
|
||||
local n = 0
|
||||
|
||||
for i, slot in pairs(self.Attachments) do
|
||||
if n > pick then continue end
|
||||
if !self:CheckFlags(slot.ExcludeFlags, slot.RequireFlags) then continue end
|
||||
if math.Rand(0, 100) > (chance * (slot.RandomChance or 1)) then continue end
|
||||
|
||||
if slot.Hidden then continue end
|
||||
|
||||
local s = i
|
||||
|
||||
if slot.MergeSlots then
|
||||
local ss = {i}
|
||||
table.Add(ss, slot.MergeSlots)
|
||||
|
||||
s = table.Random(ss) or i
|
||||
end
|
||||
if !self.Attachments[s] then s = i end
|
||||
|
||||
chance = chance - chancestep
|
||||
|
||||
self:AssignRandomAttToSlot(self.Attachments[s])
|
||||
|
||||
n = n + 1
|
||||
end
|
||||
|
||||
self.ActiveElementCache = nil -- Reset cache so we have the proper attachments to check with
|
||||
for i, slot in pairs(self.Attachments) do
|
||||
if !slot.Installed then continue end
|
||||
local atttbl = ArcCW.AttachmentTable[slot.Installed]
|
||||
if !ArcCW:SlotAcceptsAtt(slot.Slot, self, slot.Installed) then slot.Installed = nil continue end
|
||||
if !self:CheckFlags(slot.ExcludeFlags, slot.RequireFlags) then slot.Installed = nil continue end
|
||||
if !self:CheckFlags(atttbl.ExcludeFlags, atttbl.RequireFlags) then slot.Installed = nil continue end
|
||||
end
|
||||
|
||||
if self:GetBuff_Override("UBGL") and self:GetBuff_Override("UBGL_Capacity") then
|
||||
self:SetClip2(self:GetBuff_Override("UBGL_Capacity"))
|
||||
end
|
||||
|
||||
self:AdjustAtts()
|
||||
self:RefreshBGs()
|
||||
|
||||
if self:GetOwner():IsNPC() then
|
||||
timer.Simple(0.1, function()
|
||||
if !IsValid(self) then return end
|
||||
self:NetworkWeapon()
|
||||
end)
|
||||
else
|
||||
self:NetworkWeapon()
|
||||
self:SetupModel(false)
|
||||
self:SetupModel(true)
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:NPC_Shoot()
|
||||
-- if self:GetNextPrimaryFire() > CurTime() then return end
|
||||
|
||||
if !IsValid(self:GetOwner()) then return end
|
||||
if self:Clip1() <= 0 then self:GetOwner():SetSchedule(SCHED_HIDE_AND_RELOAD) return end
|
||||
|
||||
if self:GetOwner().ArcCW_Smoked then return end
|
||||
|
||||
|
||||
self.Primary.Automatic = true
|
||||
|
||||
|
||||
local delay = self:GetFiringDelay()
|
||||
|
||||
if (self:GetBuff_Override("Override_ManualAction") or self.ManualAction) then
|
||||
delay = self:GetAnimKeyTime("cycle", true) * self:GetBuff("CycleTime")
|
||||
end
|
||||
|
||||
local num = self:GetBuff("Num")
|
||||
|
||||
if num > 0 then
|
||||
local spread = ArcCW.MOAToAcc * self:GetBuff("AccuracyMOA")
|
||||
|
||||
local btabl = {
|
||||
Attacker = self:GetOwner(),
|
||||
Damage = 0,
|
||||
Force = 1,
|
||||
Distance = 33000,
|
||||
Num = num,
|
||||
Tracer = self.TracerNum,
|
||||
AmmoType = self.Primary.Ammo,
|
||||
Dir = self:GetOwner():GetAimVector(),
|
||||
Src = self:GetShootSrc(),
|
||||
Spread = Vector(spread, spread, spread),
|
||||
Callback = function(att, tr, dmg)
|
||||
ArcCW:BulletCallback(att, tr, dmg, self)
|
||||
end,
|
||||
--[[]
|
||||
Callback = function(att, tr, dmg)
|
||||
local dist = (tr.HitPos - tr.StartPos):Length() * ArcCW.HUToM
|
||||
|
||||
local pen = self:GetBuff("Penetration")
|
||||
|
||||
-- local frags = math.random(1, self.Frangibility)
|
||||
|
||||
-- for i = 1, frags do
|
||||
-- self:DoPenetration(tr, (self.Penetration / frags) - 0.5, tr.Entity)
|
||||
-- end
|
||||
|
||||
if self.DamageMin > self.Damage then
|
||||
dist = -dist + self.Range + self.Range
|
||||
end
|
||||
|
||||
local m = 1 * self:GetBuff_Mult("Mult_DamageNPC")
|
||||
|
||||
local ret = self:GetBuff_Hook("Hook_BulletHit", {
|
||||
range = dist,
|
||||
damage = self:GetDamage(dist, true) * m,
|
||||
dmgtype = self:GetBuff_Override("Override_DamageType") or self.DamageType,
|
||||
penleft = pen,
|
||||
att = att,
|
||||
tr = tr,
|
||||
dmg = dmg
|
||||
})
|
||||
|
||||
if !ret then return end
|
||||
|
||||
dmg:SetDamageType(ret.dmgtype)
|
||||
dmg:SetDamage(ret.damage)
|
||||
|
||||
if dmg:IsDamageType(DMG_BURN) and hit.range <= self.Range then
|
||||
dmg:SetDamageType(dmg:GetDamageType() - DMG_BURN)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(tr.HitPos)
|
||||
util.Effect("arccw_incendiaryround", fx)
|
||||
|
||||
util.Decal("FadingScorch", tr.StartPos, tr.HitPos - (tr.HitNormal * 16), self:GetOwner())
|
||||
|
||||
tr.Entity:Ignite(1, 32)
|
||||
end
|
||||
end
|
||||
]]
|
||||
}
|
||||
|
||||
local sp = self:GetBuff_Override("Override_ShotgunSpreadPattern") or self.ShotgunSpreadPattern
|
||||
local spo = self:GetBuff_Override("Override_ShotgunSpreadPatternOverrun") or self.ShotgunSpreadPatternOverrun
|
||||
local se = self:GetBuff_Override("Override_ShootEntity") or self.ShootEntity
|
||||
|
||||
if sp or spo then
|
||||
btabl = self:GetBuff_Hook("Hook_FireBullets", btabl)
|
||||
|
||||
if !btabl then return end
|
||||
if btabl.Num == 0 then return end
|
||||
|
||||
for n = 1, btabl.Num do
|
||||
btabl.Num = 1
|
||||
local ang = self:GetOwner():GetAimVector():Angle() + self:GetShotgunSpreadOffset(n)
|
||||
|
||||
btabl.Dir = ang:Forward()
|
||||
|
||||
self:DoPrimaryFire(false, btabl)
|
||||
end
|
||||
elseif se then
|
||||
self:FireRocket(se, self:GetBuff("MuzzleVelocity"))
|
||||
else
|
||||
self:GetBuff_Hook("Hook_FireBullets", btabl)
|
||||
|
||||
for n = 1, btabl.Num do
|
||||
btabl.Num = 1
|
||||
|
||||
local dispers = self:GetBuff_Override("Override_ShotgunSpreadDispersion", self.ShotgunSpreadDispersion)
|
||||
local offset = self:GetShotgunSpreadOffset(n)
|
||||
local calcoff = dispers and (offset * self:GetDispersion() * ArcCW.MOAToAcc / 10) or offset
|
||||
|
||||
local ang = self:GetOwner():GetAimVector():Angle()
|
||||
-- ang:RotateAroundAxis(ang:Right(), -1 * calcoff.p)
|
||||
-- ang:RotateAroundAxis(ang:Up(), calcoff.y)
|
||||
-- ang:RotateAroundAxis(ang:Forward(), calcoff.r)
|
||||
|
||||
btabl.Dir = ang:Forward()
|
||||
|
||||
self:DoPrimaryFire(false, btabl)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self:DoEffects()
|
||||
|
||||
if !self.RevolverReload then
|
||||
self:DoShellEject()
|
||||
end
|
||||
|
||||
--[[]
|
||||
local ss = self.ShootSound
|
||||
|
||||
if self:GetBuff_Override("Silencer") then
|
||||
ss = self.ShootSoundSilenced
|
||||
end
|
||||
|
||||
ss = self:GetBuff_Hook("Hook_GetShootSound", ss)
|
||||
|
||||
local dss = self.DistantShootSound
|
||||
|
||||
if self:GetBuff_Override("Silencer") then
|
||||
dss = nil
|
||||
end
|
||||
|
||||
dss = self:GetBuff_Hook("Hook_GetDistantShootSound", dss)
|
||||
|
||||
local svol = self:GetBuff("ShootVol")
|
||||
local spitch = self.ShootPitch * math.Rand(0.95, 1.05) * self:GetBuff_Mult("Mult_ShootPitch")
|
||||
|
||||
svol = svol * 0.75
|
||||
|
||||
svol = math.Clamp(svol, 51, 149)
|
||||
spitch = math.Clamp(spitch, 51, 149)
|
||||
|
||||
if dss then
|
||||
-- sound.Play(self.DistantShootSound, self:GetPos(), 149, self.ShootPitch * math.Rand(0.95, 1.05), 1)
|
||||
self:MyEmitSound(dss, 130, spitch, 0.5, CHAN_BODY)
|
||||
end
|
||||
|
||||
if ss then
|
||||
self:MyEmitSound(ss, svol, spitch, 1, CHAN_WEAPON)
|
||||
end
|
||||
]]
|
||||
|
||||
self:DoShootSound()
|
||||
|
||||
self:SetClip1(self:Clip1() - 1)
|
||||
|
||||
self:SetNextPrimaryFire(CurTime() + delay)
|
||||
if delay < 0.1 then
|
||||
self:GetOwner():NextThink(CurTime() + delay)
|
||||
end
|
||||
|
||||
if self:GetBuff_Override("UBGL_NPCFire") and self:GetNextSecondaryFire() < CurTime() then
|
||||
if math.random(0, 100) < (self:GetOwner():GetCurrentWeaponProficiency() + 1) then
|
||||
self:SetNextSecondaryFire(CurTime() + math.random(3, 5))
|
||||
else
|
||||
local func = self:GetBuff_Override("UBGL_NPCFire")
|
||||
if func then
|
||||
func(self)
|
||||
end
|
||||
if self:Clip2() == 0 then
|
||||
self:SetClip2(self.Secondary.ClipSize)
|
||||
self:SetNextSecondaryFire(CurTime() + math.random(300, 600) / (self:GetOwner():GetCurrentWeaponProficiency() + 1))
|
||||
else
|
||||
self:SetNextSecondaryFire(CurTime() + 1 / ((self:GetBuff_Override("UBGL_RPM") or 300) / 60))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:GetNPCBulletSpread(prof)
|
||||
local mode = self:GetCurrentFiremode()
|
||||
mode = mode.Mode
|
||||
|
||||
if mode < 0 then
|
||||
return 15 / (prof + 1)
|
||||
elseif mode == 1 then
|
||||
if math.Rand(0, 100) < (prof + 5) * 5 then
|
||||
return 5 / (prof + 1)
|
||||
else
|
||||
return 30 / (prof + 1)
|
||||
end
|
||||
elseif mode > 1 then
|
||||
if math.Rand(0, 100) < (prof + 5) * 2 then
|
||||
return 15 / (prof + 1)
|
||||
else
|
||||
return (20 + self:GetBuff("Recoil") * 10) / (prof + 1)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return 15
|
||||
end
|
||||
|
||||
function SWEP:GetNPCBurstSettings()
|
||||
local mode = self:GetCurrentFiremode()
|
||||
mode = mode.Mode
|
||||
|
||||
local delay = self:GetFiringDelay()
|
||||
|
||||
if !mode then return 1, 1, delay end
|
||||
|
||||
if self.ManualAction or self:GetBuff_Override("Override_ManualAction") then
|
||||
return 1, 1, self:GetAnimKeyTime("cycle") * self:GetBuff("CycleTime")
|
||||
end
|
||||
|
||||
if mode < 0 then
|
||||
return -mode, -mode, delay
|
||||
elseif mode == 0 then
|
||||
return 0, 0, delay
|
||||
elseif mode == 1 then
|
||||
local c = self:GetCapacity()
|
||||
return math.ceil(c * 0.075), math.floor(c * math.Rand(0.15, 0.3)), delay + math.Rand(0.2, 0.4)
|
||||
elseif mode >= 2 then
|
||||
if self:GetCurrentFiremode().RunawayBurst then
|
||||
return self:Clip1(), self:Clip1(), delay
|
||||
else
|
||||
return 2, math.floor(2.5 / delay), delay
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:GetNPCRestTimes()
|
||||
local mode = self:GetCurrentFiremode()
|
||||
mode = mode.Mode
|
||||
local postburst = self:GetCurrentFiremode().PostBurstDelay or 0
|
||||
local m = self:GetBuff("Recoil")
|
||||
local rs = self:GetBuff("RecoilSide")
|
||||
|
||||
if !mode then return 0.3, 0.6 end
|
||||
|
||||
local o = m * 0.3 + rs * 0.15
|
||||
if self.ManualAction or self:GetBuff_Override("Override_ManualAction") then
|
||||
local cycle = self:GetAnimKeyTime("cycle") * self:GetBuff("CycleTime")
|
||||
return cycle + 0.1 * o, cycle + 0.2 * o
|
||||
elseif mode < 0 then
|
||||
o = o * 0.5 + postburst * self:GetBuff("PostBurstDelay")
|
||||
end
|
||||
|
||||
return 0.4 * o, 0.6 * o
|
||||
end
|
||||
|
||||
function SWEP:CanBePickedUpByNPCs()
|
||||
return !self.NotForNPCs
|
||||
end
|
||||
|
||||
function SWEP:OnDrop()
|
||||
self.Primary.DefaultClip = 0
|
||||
|
||||
if self.Singleton or self.Primary.ClipSize == -1 then
|
||||
self.Primary.DefaultClip = 1
|
||||
end
|
||||
|
||||
self.UnReady = false
|
||||
-- if engine.ActiveGamemode() == "terrortown" then
|
||||
-- self.UnReady = true
|
||||
-- else
|
||||
-- self.UnReady = false
|
||||
-- end
|
||||
end
|
||||
145
lua/weapons/arccw_base/sv_shield.lua
Normal file
145
lua/weapons/arccw_base/sv_shield.lua
Normal file
@@ -0,0 +1,145 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
SWEP.Shields = {}
|
||||
|
||||
function SWEP:SetupShields()
|
||||
self:KillShields()
|
||||
|
||||
for i, k in pairs(self.Attachments) do
|
||||
if !k then continue end
|
||||
if !k.Installed then continue end
|
||||
|
||||
local atttbl = ArcCW.AttachmentTable[k.Installed]
|
||||
|
||||
if atttbl.ModelIsShield then
|
||||
|
||||
for _, e in pairs(self:GetActiveElements()) do
|
||||
local ele = self.AttachmentElements[e]
|
||||
|
||||
if !ele then continue end
|
||||
|
||||
if ((ele.AttPosMods or {})[i] or {}).wpos then
|
||||
wmelemod = ele.AttPosMods[i].wpos
|
||||
end
|
||||
|
||||
if ((ele.AttPosMods or {})[i] or {}).slide then
|
||||
slidemod = ele.AttPosMods[i].slide
|
||||
end
|
||||
|
||||
-- Refer to sh_model Line 837
|
||||
if ((ele.AttPosMods or {})[i] or {}).SlideAmount then
|
||||
slidemod = ele.AttPosMods[i].SlideAmount
|
||||
end
|
||||
end
|
||||
|
||||
local bonename = atttbl.ShieldBone or "ValveBiped.Bip01_R_Hand"
|
||||
|
||||
local boneindex = self:GetOwner():LookupBone(bonename)
|
||||
|
||||
local bpos, bang = self:GetOwner():GetBonePosition(boneindex)
|
||||
|
||||
local delta = k.SlidePos or 0.5
|
||||
|
||||
local offset = wmelemod or k.Offset.wpos or Vector(0, 0, 0)
|
||||
|
||||
if k.SlideAmount then
|
||||
offset = LerpVector(delta, (slidemod or k.SlideAmount).wmin, (slidemod or k.SlideAmount).wmax)
|
||||
end
|
||||
|
||||
local pos = offset + (atttbl.ShieldCorrectPos or Vector(0, 0, 0))
|
||||
local ang = k.Offset.wang or Angle(0, 0, 0)
|
||||
|
||||
local apos = LocalToWorld(pos, ang, bpos, bang)
|
||||
|
||||
local shield = ents.Create("physics_prop")
|
||||
if !shield then
|
||||
print("!!! Unable to spawn shield!")
|
||||
continue
|
||||
end
|
||||
|
||||
shield.mmRHAe = atttbl.ShieldResistance
|
||||
|
||||
shield:SetModel( atttbl.Model )
|
||||
shield:FollowBone( self:GetOwner(), boneindex )
|
||||
shield:SetPos( apos )
|
||||
shield:SetAngles( self:GetOwner():GetAngles() + ang + (atttbl.ShieldCorrectAng or Angle(0, 0, 0)) )
|
||||
shield:SetCollisionGroup( COLLISION_GROUP_WORLD )
|
||||
shield.Weapon = self
|
||||
if GetConVar("developer"):GetBool() then
|
||||
shield:SetColor( Color(0, 0, 0, 255) )
|
||||
else
|
||||
shield:SetColor( Color(0, 0, 0, 0) )
|
||||
shield:SetRenderMode(RENDERMODE_NONE)
|
||||
end
|
||||
table.insert(self.Shields, shield)
|
||||
shield:Spawn()
|
||||
shield:Activate()
|
||||
|
||||
table.insert(ArcCW.ShieldPropPile, {Weapon = self, Model = shield})
|
||||
|
||||
local phys = shield:GetPhysicsObject()
|
||||
|
||||
phys:SetMass(1000)
|
||||
end
|
||||
end
|
||||
|
||||
for i, k in pairs(self.ShieldProps or {}) do
|
||||
if !k then continue end
|
||||
if !k.Model then continue end
|
||||
|
||||
local bonename = k.Bone or "ValveBiped.Bip01_R_Hand"
|
||||
|
||||
local boneindex = self:GetOwner():LookupBone(bonename)
|
||||
|
||||
local bpos, bang = self:GetOwner():GetBonePosition(boneindex)
|
||||
|
||||
local pos = k.Pos or Vector(0, 0, 0)
|
||||
local ang = k.Ang or Angle(0, 0, 0)
|
||||
|
||||
local apos = LocalToWorld(pos, ang, bpos, bang)
|
||||
|
||||
local shield = ents.Create("physics_prop")
|
||||
if !shield then
|
||||
print("!!! Unable to spawn shield!")
|
||||
continue
|
||||
end
|
||||
|
||||
shield.mmRHAe = k.Resistance
|
||||
|
||||
shield:SetModel( k.Model )
|
||||
shield:FollowBone( self:GetOwner(), boneindex )
|
||||
shield:SetPos( apos )
|
||||
shield:SetAngles( self:GetOwner():GetAngles() + ang )
|
||||
shield:SetCollisionGroup( COLLISION_GROUP_WORLD )
|
||||
shield.Weapon = self
|
||||
if GetConVar("developer"):GetBool() then
|
||||
shield:SetColor( Color(0, 0, 0, 255) )
|
||||
else
|
||||
shield:SetColor( Color(0, 0, 0, 0) )
|
||||
shield:SetRenderMode(RENDERMODE_NONE)
|
||||
end
|
||||
table.insert(self.Shields, shield)
|
||||
shield:Spawn()
|
||||
shield:Activate()
|
||||
|
||||
table.insert(ArcCW.ShieldPropPile, {Weapon = self, Model = shield})
|
||||
|
||||
local phys = shield:GetPhysicsObject()
|
||||
|
||||
phys:SetMass(1000)
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:KillShields()
|
||||
for i, k in pairs(self.Shields) do
|
||||
SafeRemoveEntity(k)
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user