mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 05:43:46 +03:00
1777 lines
49 KiB
Lua
1777 lines
49 KiB
Lua
|
|
--[[
|
||
|
|
| This file was obtained through the combined efforts
|
||
|
|
| of Madbluntz & Plymouth Antiquarian Society.
|
||
|
|
|
|
||
|
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||
|
|
| Maloy, DrPepper10 @ RIP, Atle!
|
||
|
|
|
|
||
|
|
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||
|
|
--]]
|
||
|
|
|
||
|
|
-- Used to prevent stack overflow. Set false here so luarefresh clears it
|
||
|
|
ArcCW.BuffStack = false
|
||
|
|
|
||
|
|
ArcCW.ConVar_BuffMults = {
|
||
|
|
["Mult_Damage"] = "arccw_mult_damage",
|
||
|
|
["Mult_DamageMin"] = "arccw_mult_damage",
|
||
|
|
["Mult_DamageNPC"] = "arccw_mult_npcdamage",
|
||
|
|
["Mult_HipDispersion"] = "arccw_mult_hipfire",
|
||
|
|
["Mult_ReloadTime"] = "arccw_mult_reloadtime",
|
||
|
|
["Mult_SightTime"] = "arccw_mult_sighttime",
|
||
|
|
["Mult_RPM"] = "arccw_mult_rpm",
|
||
|
|
["Mult_CycleTime"] = "arccw_mult_rpm",
|
||
|
|
["Mult_Range"] = "arccw_mult_range",
|
||
|
|
["Mult_Recoil"] = "arccw_mult_recoil",
|
||
|
|
["Mult_MoveDispersion"] = "arccw_mult_movedisp",
|
||
|
|
["Mult_AccuracyMOA"] = "arccw_mult_accuracy",
|
||
|
|
["Mult_Penetration"] = "arccw_mult_penetration",
|
||
|
|
["Mult_Sway"] = "arccw_mult_sway",
|
||
|
|
["Mult_MeleeDamage"] = "arccw_mult_meleedamage",
|
||
|
|
["Mult_MeleeTime"] = "arccw_mult_meleetime",
|
||
|
|
}
|
||
|
|
|
||
|
|
ArcCW.ConVar_BuffAdds = {
|
||
|
|
["Add_Sway"] = "arccw_add_sway",
|
||
|
|
}
|
||
|
|
|
||
|
|
ArcCW.ConVar_BuffOverrides = {
|
||
|
|
["Override_ShootWhileSprint"] = "arccw_mult_shootwhilesprinting"
|
||
|
|
}
|
||
|
|
|
||
|
|
SWEP.TickCache_Overrides = {}
|
||
|
|
SWEP.TickCache_Adds = {}
|
||
|
|
SWEP.TickCache_Mults = {}
|
||
|
|
SWEP.TickCache_Hooks = {}
|
||
|
|
SWEP.TickCache_IsShotgun = nil
|
||
|
|
|
||
|
|
SWEP.TickCache_Tick_Overrides = {}
|
||
|
|
SWEP.TickCache_Tick_Adds = {}
|
||
|
|
SWEP.TickCache_Tick_Mults = {}
|
||
|
|
|
||
|
|
SWEP.AttCache_Hooks = {}
|
||
|
|
|
||
|
|
-- debug: enable/disable modified caching
|
||
|
|
local MODIFIED_CACHE = true
|
||
|
|
-- print if a variable presumed to never change actually changes (this also happens right after attaching/detaching)
|
||
|
|
-- only works if MODIFIED_CACHE is false
|
||
|
|
local VERIFY_MODIFIED_CACHE = false
|
||
|
|
|
||
|
|
-- Conditions not listed are are presumed to never change; this is done for optimization purposes
|
||
|
|
SWEP.ModifiedCache = {}
|
||
|
|
|
||
|
|
function SWEP:RecalcAllBuffs()
|
||
|
|
self.TickCache_Overrides = {}
|
||
|
|
self.TickCache_Adds = {}
|
||
|
|
self.TickCache_Mults = {}
|
||
|
|
self.TickCache_Hooks = {}
|
||
|
|
self.TickCache_IsShotgun = nil
|
||
|
|
|
||
|
|
self.TickCache_Tick_Overrides = {}
|
||
|
|
self.TickCache_Tick_Adds = {}
|
||
|
|
self.TickCache_Tick_Mults = {}
|
||
|
|
|
||
|
|
self.ReferencePosCache = {}
|
||
|
|
|
||
|
|
self.AttCache_Hooks = {}
|
||
|
|
|
||
|
|
self.NextMalfunction = nil
|
||
|
|
|
||
|
|
-- for the customization page
|
||
|
|
if CLIENT then
|
||
|
|
self.Infos_Stats = nil
|
||
|
|
self.Infos_Ballistics = nil
|
||
|
|
self.Infos_Breakpoints = nil
|
||
|
|
end
|
||
|
|
|
||
|
|
-- this function is not always called right before AdjustAtts
|
||
|
|
--self.ModifiedCache = {}
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:GetIsShotgun()
|
||
|
|
if self.TickCache_IsShotgun == nil then
|
||
|
|
local shotgun = self:GetBuff_Override("Override_IsShotgun")
|
||
|
|
if shotgun != nil then
|
||
|
|
self.TickCache_IsShotgun = shotgun
|
||
|
|
end
|
||
|
|
|
||
|
|
local num = self.Num
|
||
|
|
if self.TickCache_IsShotgun == nil and num > 1 then self.TickCache_IsShotgun = true end
|
||
|
|
end
|
||
|
|
|
||
|
|
return self.TickCache_IsShotgun
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:GetIsManualAction()
|
||
|
|
local manual = self:GetBuff_Override("Override_ManualAction")
|
||
|
|
|
||
|
|
if manual != false then
|
||
|
|
manual = manual or self.ManualAction
|
||
|
|
end
|
||
|
|
|
||
|
|
-- A manual action gun CAN have automatic firemode, this is intended behavior!!!
|
||
|
|
-- It's used for slamfiring
|
||
|
|
--[[]
|
||
|
|
local mode = self:GetCurrentFiremode().Mode
|
||
|
|
|
||
|
|
if mode != 0 and mode != 1 then
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
]]
|
||
|
|
|
||
|
|
return manual
|
||
|
|
end
|
||
|
|
|
||
|
|
-- ONE FUNCTION TO RULE THEM ALL
|
||
|
|
function SWEP:GetBuff(buff, defaultnil, defaultvar)
|
||
|
|
local stable = self:GetTable()
|
||
|
|
|
||
|
|
local result = stable[buff] or defaultvar
|
||
|
|
if !result and defaultnil then
|
||
|
|
result = nil
|
||
|
|
elseif !result then
|
||
|
|
result = 1
|
||
|
|
end
|
||
|
|
|
||
|
|
result = self:GetBuff_Override("Override_" .. buff, result)
|
||
|
|
|
||
|
|
if isnumber(result) then
|
||
|
|
result = self:GetBuff_Add("Add_" .. buff) + result
|
||
|
|
result = self:GetBuff_Mult("Mult_" .. buff) * result
|
||
|
|
end
|
||
|
|
|
||
|
|
return result
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:GetBuff_Stat(buff, slot)
|
||
|
|
local slottbl = self.Attachments[slot]
|
||
|
|
if !slottbl then return end
|
||
|
|
local atttbl = ArcCW.AttachmentTable[slottbl.Installed]
|
||
|
|
if !atttbl then return end
|
||
|
|
local num = slottbl.ToggleNum or 1
|
||
|
|
|
||
|
|
if atttbl.ToggleStats and atttbl.ToggleStats[num] and (atttbl.ToggleStats[num][buff] != nil) then
|
||
|
|
return atttbl.ToggleStats[num][buff]
|
||
|
|
else
|
||
|
|
return atttbl[buff]
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:GetBuff_Hook(buff, data, defaultnil)
|
||
|
|
-- call through hook function, args = data. return nil to do nothing. return false to prevent thing from happening.
|
||
|
|
|
||
|
|
if !self.AttCache_Hooks[buff] then
|
||
|
|
self.AttCache_Hooks[buff] = {}
|
||
|
|
|
||
|
|
for i, k in pairs(self.Attachments) do
|
||
|
|
if !k.Installed then continue end
|
||
|
|
|
||
|
|
local atttbl = ArcCW.AttachmentTable[k.Installed]
|
||
|
|
|
||
|
|
if !atttbl then continue end
|
||
|
|
|
||
|
|
if isfunction(atttbl[buff]) then
|
||
|
|
table.insert(self.AttCache_Hooks[buff], {atttbl[buff], atttbl[buff .. "_Priority"] or 0})
|
||
|
|
elseif atttbl.ToggleStats and k.ToggleNum and atttbl.ToggleStats[k.ToggleNum] and isfunction(atttbl.ToggleStats[k.ToggleNum][buff]) then
|
||
|
|
table.insert(self.AttCache_Hooks[buff], {atttbl.ToggleStats[k.ToggleNum][buff], atttbl.ToggleStats[k.ToggleNum][buff .. "_Priority"] or 0})
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local cfm = self:GetCurrentFiremode()
|
||
|
|
|
||
|
|
if cfm and isfunction(cfm[buff]) then
|
||
|
|
table.insert(self.AttCache_Hooks[buff], {cfm[buff], cfm[buff .. "_Priority"] or 0})
|
||
|
|
end
|
||
|
|
|
||
|
|
for i, e in pairs(self:GetActiveElements()) do
|
||
|
|
local ele = self.AttachmentElements[e]
|
||
|
|
|
||
|
|
if ele and ele[buff] then
|
||
|
|
table.insert(self.AttCache_Hooks[buff], {ele[buff], ele[buff .. "_Priority"] or 0})
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if isfunction(self:GetTable()[buff]) then
|
||
|
|
table.insert(self.AttCache_Hooks[buff], {self:GetTable()[buff], self:GetTable()[buff .. "_Priority"] or 0})
|
||
|
|
end
|
||
|
|
|
||
|
|
table.sort(self.AttCache_Hooks[buff], function(a, b) return a[2] >= b[2] end)shouldsort = true
|
||
|
|
end
|
||
|
|
|
||
|
|
local retvalue = nil
|
||
|
|
for i, k in ipairs(self.AttCache_Hooks[buff]) do
|
||
|
|
local ret = k[1](self, data)
|
||
|
|
if ret == false then
|
||
|
|
return
|
||
|
|
elseif ret != nil then
|
||
|
|
retvalue = ret
|
||
|
|
break
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if retvalue then data = retvalue
|
||
|
|
elseif defaultnil then data = nil end
|
||
|
|
|
||
|
|
data = hook.Call(buff, nil, self, data) or data
|
||
|
|
|
||
|
|
return data
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:GetBuff_Override(buff, default)
|
||
|
|
|
||
|
|
local level = 0
|
||
|
|
local current = nil
|
||
|
|
local winningslot = nil
|
||
|
|
|
||
|
|
if MODIFIED_CACHE and !self.ModifiedCache[buff] then
|
||
|
|
-- ArcCW.ConVar_BuffOverrides[buff] isn't actually implemented??
|
||
|
|
|
||
|
|
if !ArcCW.BuffStack then
|
||
|
|
ArcCW.BuffStack = true
|
||
|
|
local out = (self:GetBuff_Hook("O_Hook_" .. buff, {buff = buff}) or {})
|
||
|
|
current = out.current or current
|
||
|
|
winningslot = out.winningslot or winningslot
|
||
|
|
ArcCW.BuffStack = false
|
||
|
|
end
|
||
|
|
|
||
|
|
return current or default, winningslot
|
||
|
|
end
|
||
|
|
|
||
|
|
if self.TickCache_Overrides[buff] then
|
||
|
|
current = self.TickCache_Overrides[buff][1]
|
||
|
|
winningslot = self.TickCache_Overrides[buff][2]
|
||
|
|
|
||
|
|
local data = {
|
||
|
|
buff = buff,
|
||
|
|
current = current,
|
||
|
|
winningslot = winningslot
|
||
|
|
}
|
||
|
|
|
||
|
|
if !ArcCW.BuffStack then
|
||
|
|
|
||
|
|
ArcCW.BuffStack = true
|
||
|
|
|
||
|
|
local out = (self:GetBuff_Hook("O_Hook_" .. buff, data) or {})
|
||
|
|
|
||
|
|
current = out.current or current
|
||
|
|
winningslot = out.winningslot or winningslot
|
||
|
|
|
||
|
|
ArcCW.BuffStack = false
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
if current == nil then
|
||
|
|
return default
|
||
|
|
else
|
||
|
|
return current, winningslot
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
for i, k in pairs(self.Attachments) do
|
||
|
|
if !k.Installed then continue end
|
||
|
|
|
||
|
|
local atttbl = ArcCW.AttachmentTable[k.Installed]
|
||
|
|
|
||
|
|
if !atttbl then continue end
|
||
|
|
|
||
|
|
if atttbl[buff] != nil then
|
||
|
|
local pri = atttbl[buff .. "_Priority"] or 1
|
||
|
|
if level == 0 or (pri > level) then
|
||
|
|
current = atttbl[buff]
|
||
|
|
level = pri
|
||
|
|
winningslot = i
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if atttbl.ToggleStats and k.ToggleNum and atttbl.ToggleStats[k.ToggleNum] and atttbl.ToggleStats[k.ToggleNum][buff] then
|
||
|
|
local pri = atttbl.ToggleStats[k.ToggleNum][buff .. "_Priority"] or 1
|
||
|
|
if level == 0 or (pri > level) then
|
||
|
|
current = atttbl.ToggleStats[k.ToggleNum][buff]
|
||
|
|
level = pri
|
||
|
|
winningslot = i
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if !ArcCW.BuffStack then
|
||
|
|
|
||
|
|
ArcCW.BuffStack = true
|
||
|
|
|
||
|
|
local cfm = self:GetCurrentFiremode()
|
||
|
|
|
||
|
|
if cfm and cfm[buff] != nil then
|
||
|
|
local pri = cfm[buff .. "_Priority"] or 1
|
||
|
|
if level == 0 or (pri > level) then
|
||
|
|
current = cfm[buff]
|
||
|
|
level = pri
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
ArcCW.BuffStack = false
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
if !ArcCW.BuffStack then
|
||
|
|
|
||
|
|
ArcCW.BuffStack = true
|
||
|
|
|
||
|
|
for i, e in pairs(self:GetActiveElements()) do
|
||
|
|
local ele = self.AttachmentElements[e]
|
||
|
|
|
||
|
|
if ele and ele[buff] != nil then
|
||
|
|
local pri = ele[buff .. "_Priority"] or 1
|
||
|
|
if level == 0 or (pri > level) then
|
||
|
|
current = ele[buff]
|
||
|
|
level = pri
|
||
|
|
winningslot = i
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
ArcCW.BuffStack = false
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
if self:GetTable()[buff] != nil then
|
||
|
|
local pri = self:GetTable()[buff .. "_Priority"] or 1
|
||
|
|
if level == 0 or (pri > level) then
|
||
|
|
current = self:GetTable()[buff]
|
||
|
|
level = pri
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
self.TickCache_Overrides[buff] = {current, winningslot}
|
||
|
|
|
||
|
|
if VERIFY_MODIFIED_CACHE and !self.ModifiedCache[buff] and current != nil then
|
||
|
|
print("ArcCW: Presumed non-changing buff '" .. buff .. "' is modified (" .. tostring(current) .. ")!")
|
||
|
|
end
|
||
|
|
|
||
|
|
local data = {
|
||
|
|
buff = buff,
|
||
|
|
current = current,
|
||
|
|
winningslot = winningslot
|
||
|
|
}
|
||
|
|
|
||
|
|
if !ArcCW.BuffStack then
|
||
|
|
|
||
|
|
ArcCW.BuffStack = true
|
||
|
|
|
||
|
|
current = (self:GetBuff_Hook("O_Hook_" .. buff, data) or {}).current or current
|
||
|
|
|
||
|
|
ArcCW.BuffStack = false
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
if current == nil then
|
||
|
|
current = default
|
||
|
|
end
|
||
|
|
|
||
|
|
return current, winningslot
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:GetBuff_Mult(buff)
|
||
|
|
|
||
|
|
local mult = 1
|
||
|
|
|
||
|
|
if MODIFIED_CACHE and !self.ModifiedCache[buff] then
|
||
|
|
if !ArcCW.BuffStack then
|
||
|
|
ArcCW.BuffStack = true
|
||
|
|
mult = (self:GetBuff_Hook("M_Hook_" .. buff, {buff = buff, mult = 1}) or {}).mult or mult
|
||
|
|
ArcCW.BuffStack = false
|
||
|
|
end
|
||
|
|
if ArcCW.ConVar_BuffMults[buff] then
|
||
|
|
if buff == "Mult_CycleTime" then
|
||
|
|
mult = mult / GetConVar(ArcCW.ConVar_BuffMults[buff]):GetFloat()
|
||
|
|
else
|
||
|
|
mult = mult * GetConVar(ArcCW.ConVar_BuffMults[buff]):GetFloat()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
return mult
|
||
|
|
end
|
||
|
|
|
||
|
|
if self.TickCache_Mults[buff] then
|
||
|
|
mult = self.TickCache_Mults[buff]
|
||
|
|
local data = {
|
||
|
|
buff = buff,
|
||
|
|
mult = mult
|
||
|
|
}
|
||
|
|
|
||
|
|
if !ArcCW.BuffStack then
|
||
|
|
|
||
|
|
ArcCW.BuffStack = true
|
||
|
|
|
||
|
|
mult = (self:GetBuff_Hook("M_Hook_" .. buff, data) or {}).mult or mult
|
||
|
|
|
||
|
|
ArcCW.BuffStack = false
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
if ArcCW.ConVar_BuffMults[buff] then
|
||
|
|
if buff == "Mult_CycleTime" then
|
||
|
|
mult = mult / GetConVar(ArcCW.ConVar_BuffMults[buff]):GetFloat()
|
||
|
|
else
|
||
|
|
mult = mult * GetConVar(ArcCW.ConVar_BuffMults[buff]):GetFloat()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
return mult
|
||
|
|
end
|
||
|
|
|
||
|
|
for i, k in pairs(self.Attachments) do
|
||
|
|
if !k.Installed then continue end
|
||
|
|
|
||
|
|
local atttbl = ArcCW.AttachmentTable[k.Installed]
|
||
|
|
|
||
|
|
if atttbl[buff] then
|
||
|
|
mult = mult * atttbl[buff]
|
||
|
|
end
|
||
|
|
|
||
|
|
if atttbl.ToggleStats and k.ToggleNum and atttbl.ToggleStats[k.ToggleNum] and atttbl.ToggleStats[k.ToggleNum][buff] then
|
||
|
|
mult = mult * atttbl.ToggleStats[k.ToggleNum][buff]
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local cfm = self:GetCurrentFiremode()
|
||
|
|
|
||
|
|
if cfm and cfm[buff] then
|
||
|
|
mult = mult * cfm[buff]
|
||
|
|
end
|
||
|
|
|
||
|
|
if self:GetTable()[buff] then
|
||
|
|
mult = mult * self:GetTable()[buff]
|
||
|
|
end
|
||
|
|
|
||
|
|
for i, e in pairs(self:GetActiveElements()) do
|
||
|
|
local ele = self.AttachmentElements[e]
|
||
|
|
|
||
|
|
if ele and ele[buff] then
|
||
|
|
mult = mult * ele[buff]
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
self.TickCache_Mults[buff] = mult
|
||
|
|
|
||
|
|
if VERIFY_MODIFIED_CACHE and !self.ModifiedCache[buff] and mult != 1 then
|
||
|
|
print("ArcCW: Presumed non-changing buff '" .. buff .. "' is modified (" .. tostring(mult) .. ")!")
|
||
|
|
end
|
||
|
|
|
||
|
|
if ArcCW.ConVar_BuffMults[buff] then
|
||
|
|
if buff == "Mult_CycleTime" then
|
||
|
|
mult = mult / GetConVar(ArcCW.ConVar_BuffMults[buff]):GetFloat()
|
||
|
|
else
|
||
|
|
mult = mult * GetConVar(ArcCW.ConVar_BuffMults[buff]):GetFloat()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local data = {
|
||
|
|
buff = buff,
|
||
|
|
mult = mult
|
||
|
|
}
|
||
|
|
|
||
|
|
if !ArcCW.BuffStack then
|
||
|
|
|
||
|
|
ArcCW.BuffStack = true
|
||
|
|
|
||
|
|
mult = (self:GetBuff_Hook("M_Hook_" .. buff, data) or {}).mult or mult
|
||
|
|
|
||
|
|
ArcCW.BuffStack = false
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
return mult
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:GetBuff_Add(buff)
|
||
|
|
local add = 0
|
||
|
|
|
||
|
|
if MODIFIED_CACHE and !self.ModifiedCache[buff] then
|
||
|
|
if !ArcCW.BuffStack then
|
||
|
|
ArcCW.BuffStack = true
|
||
|
|
add = (self:GetBuff_Hook("A_Hook_" .. buff, {buff = buff, add = 0}) or {}).add or add
|
||
|
|
ArcCW.BuffStack = false
|
||
|
|
end
|
||
|
|
if ArcCW.ConVar_BuffAdds[buff] then
|
||
|
|
add = add + GetConVar(ArcCW.ConVar_BuffAdds[buff]):GetFloat()
|
||
|
|
end
|
||
|
|
return add
|
||
|
|
end
|
||
|
|
|
||
|
|
if self.TickCache_Adds[buff] then
|
||
|
|
add = self.TickCache_Adds[buff]
|
||
|
|
|
||
|
|
local data = {
|
||
|
|
buff = buff,
|
||
|
|
add = add
|
||
|
|
}
|
||
|
|
|
||
|
|
if !ArcCW.BuffStack then
|
||
|
|
|
||
|
|
ArcCW.BuffStack = true
|
||
|
|
|
||
|
|
add = (self:GetBuff_Hook("A_Hook_" .. buff, data) or {}).add or add
|
||
|
|
|
||
|
|
ArcCW.BuffStack = false
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
if ArcCW.ConVar_BuffAdds[buff] then
|
||
|
|
add = add + GetConVar(ArcCW.ConVar_BuffAdds[buff]):GetFloat()
|
||
|
|
end
|
||
|
|
|
||
|
|
return add
|
||
|
|
end
|
||
|
|
|
||
|
|
for i, k in pairs(self.Attachments) do
|
||
|
|
if !k.Installed then continue end
|
||
|
|
|
||
|
|
local atttbl = ArcCW.AttachmentTable[k.Installed]
|
||
|
|
|
||
|
|
if atttbl[buff] then
|
||
|
|
add = add + atttbl[buff]
|
||
|
|
end
|
||
|
|
|
||
|
|
if atttbl.ToggleStats and k.ToggleNum and atttbl.ToggleStats[k.ToggleNum] and atttbl.ToggleStats[k.ToggleNum][buff] then
|
||
|
|
add = add + atttbl.ToggleStats[k.ToggleNum][buff]
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local cfm = self:GetCurrentFiremode()
|
||
|
|
|
||
|
|
if cfm and cfm[buff] then
|
||
|
|
add = add + cfm[buff]
|
||
|
|
end
|
||
|
|
|
||
|
|
for i, e in pairs(self:GetActiveElements()) do
|
||
|
|
local ele = self.AttachmentElements[e]
|
||
|
|
|
||
|
|
if ele and ele[buff] then
|
||
|
|
add = add + ele[buff]
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
self.TickCache_Adds[buff] = add
|
||
|
|
|
||
|
|
if VERIFY_MODIFIED_CACHE and !self.ModifiedCache[buff] and add != 0 then
|
||
|
|
print("ArcCW: Presumed non-changing buff '" .. buff .. "' is modified (" .. tostring(add) .. ")!")
|
||
|
|
end
|
||
|
|
|
||
|
|
if ArcCW.ConVar_BuffAdds[buff] then
|
||
|
|
add = add + GetConVar(ArcCW.ConVar_BuffAdds[buff]):GetFloat()
|
||
|
|
end
|
||
|
|
|
||
|
|
local data = {
|
||
|
|
buff = buff,
|
||
|
|
add = add
|
||
|
|
}
|
||
|
|
|
||
|
|
if !ArcCW.BuffStack then
|
||
|
|
|
||
|
|
ArcCW.BuffStack = true
|
||
|
|
|
||
|
|
add = (self:GetBuff_Hook("A_Hook_" .. buff, data) or {}).add or add
|
||
|
|
|
||
|
|
ArcCW.BuffStack = false
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
return add
|
||
|
|
end
|
||
|
|
|
||
|
|
SWEP.ActiveElementCache = nil
|
||
|
|
|
||
|
|
function SWEP:GetActiveElements(recache)
|
||
|
|
if self.ActiveElementCache and !recache then return self.ActiveElementCache end
|
||
|
|
if ArcCW.Overflow and self.ActiveElementCache then return self.ActiveElementCache end
|
||
|
|
|
||
|
|
local eles = {}
|
||
|
|
|
||
|
|
for _, i in pairs(self.Attachments) do
|
||
|
|
if !i.Installed then
|
||
|
|
if i.DefaultEles then
|
||
|
|
table.Add(eles, i.DefaultEles)
|
||
|
|
end
|
||
|
|
continue
|
||
|
|
end
|
||
|
|
|
||
|
|
if i.InstalledEles and i.Installed != i.EmptyFallback then
|
||
|
|
table.Add(eles, i.InstalledEles)
|
||
|
|
end
|
||
|
|
|
||
|
|
local atttbl = ArcCW.AttachmentTable[i.Installed]
|
||
|
|
|
||
|
|
if atttbl.ActivateElements then
|
||
|
|
table.Add(eles, atttbl.ActivateElements)
|
||
|
|
end
|
||
|
|
|
||
|
|
local num = i.ToggleNum or 1
|
||
|
|
if atttbl.ToggleStats and atttbl.ToggleStats[num] and (atttbl.ToggleStats[num]["ActivateElements"] != nil) then
|
||
|
|
table.Add(eles, atttbl.ToggleStats[num]["ActivateElements"])
|
||
|
|
--atttbl.ToggleStats[num][buff]
|
||
|
|
end
|
||
|
|
|
||
|
|
local slots = atttbl.Slot
|
||
|
|
|
||
|
|
if isstring(slots) then
|
||
|
|
slots = {slots}
|
||
|
|
end
|
||
|
|
|
||
|
|
table.Add(eles, slots or {})
|
||
|
|
|
||
|
|
table.insert(eles, i.Installed)
|
||
|
|
end
|
||
|
|
|
||
|
|
table.Add(eles, self.DefaultElements)
|
||
|
|
|
||
|
|
local mode = self:GetCurrentFiremode()
|
||
|
|
table.Add(eles, (mode or {}).ActivateElements or {})
|
||
|
|
|
||
|
|
local eles2 = {}
|
||
|
|
|
||
|
|
ArcCW.Overflow = true
|
||
|
|
|
||
|
|
for f, i in pairs(eles) do
|
||
|
|
local e = self.AttachmentElements[i]
|
||
|
|
|
||
|
|
if !e then continue end
|
||
|
|
|
||
|
|
if !self:CheckFlags(e.ExcludeFlags, e.RequireFlags) then continue end
|
||
|
|
|
||
|
|
local a = false
|
||
|
|
local c = 0
|
||
|
|
|
||
|
|
for g = f, table.Count(eles) do
|
||
|
|
if eles[g] == i then c = c + 1 end
|
||
|
|
if a then continue end
|
||
|
|
|
||
|
|
if c > 1 then a = true end
|
||
|
|
end
|
||
|
|
|
||
|
|
if a then continue end
|
||
|
|
|
||
|
|
table.insert(eles2, i)
|
||
|
|
end
|
||
|
|
|
||
|
|
table.Add(eles2, self:GetWeaponFlags())
|
||
|
|
|
||
|
|
ArcCW.Overflow = false
|
||
|
|
|
||
|
|
self.ActiveElementCache = eles2
|
||
|
|
|
||
|
|
return eles2
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:GetMuzzleDevice(wm)
|
||
|
|
local model = self.WM
|
||
|
|
local muzz = self.WMModel or self
|
||
|
|
|
||
|
|
if !wm then
|
||
|
|
model = self.VM
|
||
|
|
muzz = self:GetOwner():GetViewModel()
|
||
|
|
end
|
||
|
|
|
||
|
|
if model then
|
||
|
|
for _, ele in pairs(model) do
|
||
|
|
if ele.IsMuzzleDevice then
|
||
|
|
muzz = ele.Model or muzz
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if self:GetInUBGL() then
|
||
|
|
local _, slot = self:GetBuff_Override("UBGL")
|
||
|
|
|
||
|
|
if wm then
|
||
|
|
muzz = (self.Attachments[slot].WMuzzleDeviceElement or {}).Model or muzz
|
||
|
|
else
|
||
|
|
muzz = (self.Attachments[slot].VMuzzleDeviceElement or {}).Model or muzz
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
return muzz
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:GetTracerOrigin()
|
||
|
|
local ow = self:GetOwner()
|
||
|
|
local wm = nil
|
||
|
|
local muzz = nil
|
||
|
|
|
||
|
|
if !ow:IsNPC() and !ow:IsNextBot() and ow:IsValid() then
|
||
|
|
wm = !ow:GetViewModel():IsValid() or ow:ShouldDrawLocalPlayer()
|
||
|
|
muzz = self:GetMuzzleDevice(wm)
|
||
|
|
end
|
||
|
|
|
||
|
|
if muzz and muzz:IsValid() then
|
||
|
|
local posang = muzz:GetAttachment(self:GetBuff_Override("Override_MuzzleEffectAttachment", self.MuzzleEffectAttachment) or 1)
|
||
|
|
if !posang then return muzz:GetPos() end
|
||
|
|
local pos = posang.Pos
|
||
|
|
|
||
|
|
return pos
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:CheckFlags(reject, need)
|
||
|
|
local flags
|
||
|
|
if ArcCW.Overflow then
|
||
|
|
flags = self:GetWeaponFlags()
|
||
|
|
else
|
||
|
|
flags = self:GetActiveElements()
|
||
|
|
end
|
||
|
|
|
||
|
|
reject = reject or {}
|
||
|
|
need = need or {}
|
||
|
|
|
||
|
|
if !istable(reject) then reject = {reject} end
|
||
|
|
if !istable(need) then need = {need} end
|
||
|
|
|
||
|
|
for _, i in pairs(reject) do
|
||
|
|
if table.HasValue(flags, i) then
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
for _, i in pairs(need) do
|
||
|
|
if !table.HasValue(flags, i) then
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
return true
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:GetWeaponFlags()
|
||
|
|
local flags = {}
|
||
|
|
|
||
|
|
if self.DefaultFlags then table.Add(flags, self.DefaultFlags) end
|
||
|
|
|
||
|
|
for id, i in pairs(self.Attachments) do
|
||
|
|
if !i.Installed then
|
||
|
|
if i.DefaultFlags then
|
||
|
|
table.Add(flags, i.DefaultFlags)
|
||
|
|
end
|
||
|
|
continue
|
||
|
|
end
|
||
|
|
|
||
|
|
local buff = self:GetBuff_Stat("GivesFlags", id)
|
||
|
|
if buff then
|
||
|
|
table.Add(flags, buff)
|
||
|
|
end
|
||
|
|
|
||
|
|
if i.GivesFlags then
|
||
|
|
table.Add(flags, i.GivesFlags)
|
||
|
|
end
|
||
|
|
|
||
|
|
local extras = {}
|
||
|
|
self:GetBuff_Hook("Hook_ExtraFlags", extras)
|
||
|
|
table.Add(flags, extras)
|
||
|
|
|
||
|
|
table.Add(flags, {i.Installed})
|
||
|
|
end
|
||
|
|
|
||
|
|
return flags
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:PlayerOwnsAtt(att)
|
||
|
|
local qty = ArcCW:PlayerGetAtts(self:GetOwner(), att)
|
||
|
|
|
||
|
|
return qty > 0
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:NetworkWeapon(sendto)
|
||
|
|
net.Start("arccw_networkatts")
|
||
|
|
net.WriteEntity(self) -- self entity
|
||
|
|
|
||
|
|
net.WriteUInt(table.Count(self.Attachments), 8)
|
||
|
|
|
||
|
|
for _, i in pairs(self.Attachments) do
|
||
|
|
if !i.Installed then net.WriteUInt(0, ArcCW.GetBitNecessity()) continue end
|
||
|
|
|
||
|
|
local atttbl = ArcCW.AttachmentTable[i.Installed]
|
||
|
|
local id = atttbl.ID
|
||
|
|
|
||
|
|
net.WriteUInt(id, ArcCW.GetBitNecessity())
|
||
|
|
|
||
|
|
if i.SlideAmount then
|
||
|
|
net.WriteFloat(i.SlidePos or 0.5)
|
||
|
|
end
|
||
|
|
|
||
|
|
if atttbl.ToggleStats then
|
||
|
|
net.WriteUInt(i.ToggleNum or 1, 8) -- look if you want more than 255 fucking toggle options you're insane and stupid just don't ok
|
||
|
|
end
|
||
|
|
|
||
|
|
-- if atttbl.ColorOptionsTable then
|
||
|
|
-- net.WriteUInt(i.ColorOptionIndex or 1, 8) -- look if you want more than 256 fucking color options you're insane and stupid and just don't ok
|
||
|
|
-- end
|
||
|
|
end
|
||
|
|
|
||
|
|
if sendto then
|
||
|
|
net.Send(sendto)
|
||
|
|
else
|
||
|
|
-- net.SendPVS(self:GetPos())
|
||
|
|
net.Broadcast()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:SendDetail_ColorIndex(slot)
|
||
|
|
net.Start("arccw_colorindex")
|
||
|
|
net.WriteUInt(slot, 8)
|
||
|
|
net.WriteUInt(self.Attachments[slot].ColorOptionIndex)
|
||
|
|
net.SendToServer()
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:SendDetail_SlidePos(slot, hmm)
|
||
|
|
if !self.Attachments then return end
|
||
|
|
if !self.Attachments[slot].SlidePos then return end
|
||
|
|
|
||
|
|
net.Start("arccw_slidepos")
|
||
|
|
net.WriteUInt(slot, 8)
|
||
|
|
net.WriteFloat(self.Attachments[slot].SlidePos or 0.5)
|
||
|
|
net.SendToServer()
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:SendDetail_ToggleNum(slot, hmm)
|
||
|
|
if !self.Attachments or !self.Attachments[slot] then return end
|
||
|
|
if !self.Attachments[slot].ToggleNum then return end
|
||
|
|
|
||
|
|
net.Start("arccw_togglenum")
|
||
|
|
net.WriteUInt(slot, 8)
|
||
|
|
net.WriteUInt(self.Attachments[slot].ToggleNum or 1, 8)
|
||
|
|
net.SendToServer()
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
function SWEP:SendAllDetails()
|
||
|
|
for i, k in pairs(self.Attachments) do
|
||
|
|
self:SendDetail_SlidePos(i, true)
|
||
|
|
self:SendDetail_ToggleNum(i, true)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:CountAttachments()
|
||
|
|
local total = 0
|
||
|
|
|
||
|
|
for _, i in pairs(self.Attachments) do
|
||
|
|
if i.Installed and !i.FreeSlot then
|
||
|
|
local ins = ArcCW.AttachmentTable[i.Installed]
|
||
|
|
if ins and !ins.IgnorePickX then
|
||
|
|
total = total + 1
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
return total
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:SetBodygroupTr(ind, bg)
|
||
|
|
self.Bodygroups[ind] = bg
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:RefreshBGs()
|
||
|
|
local vm
|
||
|
|
|
||
|
|
local vmm = self:GetBuff_Override("Override_VMMaterial") or self.VMMaterial or ""
|
||
|
|
local wmm = self:GetBuff_Override("Override_WMMaterial") or self.WMMaterial or ""
|
||
|
|
|
||
|
|
local vmc = self:GetBuff_Override("Override_VMColor") or self.VMColor or Color(255, 255, 255)
|
||
|
|
local wmc = self:GetBuff_Override("Override_WMColor") or self.WMColor or Color(255, 255, 255)
|
||
|
|
|
||
|
|
local vms = self:GetBuff_Override("Override_VMSkin") or self.DefaultSkin
|
||
|
|
local wms = self:GetBuff_Override("Override_WMSkin") or self.DefaultWMSkin
|
||
|
|
|
||
|
|
local vmp = self.DefaultPoseParams
|
||
|
|
local wmp = self.DefaultWMPoseParams
|
||
|
|
|
||
|
|
if self.MirrorVMWM then
|
||
|
|
wmm = vmm
|
||
|
|
wmc = vmc
|
||
|
|
wms = vms
|
||
|
|
wmp = vmp
|
||
|
|
end
|
||
|
|
|
||
|
|
if self:GetOwner():IsPlayer() then
|
||
|
|
vm = self:GetOwner():GetViewModel()
|
||
|
|
end
|
||
|
|
|
||
|
|
if vm and vm:IsValid() then
|
||
|
|
ArcCW.SetBodyGroups(vm, self.DefaultBodygroups)
|
||
|
|
vm:SetMaterial(vmm)
|
||
|
|
vm:SetColor(vmc)
|
||
|
|
vm:SetSkin(vms)
|
||
|
|
|
||
|
|
vmp["BaseClass"] = nil
|
||
|
|
|
||
|
|
for i, k in pairs(vmp) do
|
||
|
|
vm:SetPoseParameter(i, k)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
self:SetMaterial(wmm)
|
||
|
|
self:SetColor(wmc)
|
||
|
|
self:SetSkin(wms)
|
||
|
|
|
||
|
|
if self.WMModel and self.WMModel:IsValid() then
|
||
|
|
ArcCW.SetBodyGroups(self.WMModel, self.MirrorVMWM and self.DefaultBodygroups or self.DefaultWMBodygroups)
|
||
|
|
|
||
|
|
self.WMModel:SetMaterial(wmm)
|
||
|
|
self.WMModel:SetColor(wmc)
|
||
|
|
self.WMModel:SetSkin(wms)
|
||
|
|
|
||
|
|
wmp["BaseClass"] = nil
|
||
|
|
|
||
|
|
for i, k in pairs(wmp) do
|
||
|
|
self.WMModel:SetPoseParameter(i, k)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local ae = self:GetActiveElements()
|
||
|
|
|
||
|
|
for _, e in pairs(ae) do
|
||
|
|
local ele = self.AttachmentElements[e]
|
||
|
|
|
||
|
|
if !ele then continue end
|
||
|
|
|
||
|
|
if ele.VMPoseParams and vm and IsValid(vm) then
|
||
|
|
ele.VMPoseParams["BaseClass"] = nil
|
||
|
|
for i, k in pairs(ele.VMPoseParams) do
|
||
|
|
vm:SetPoseParameter(i, k)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if self.WMModel and self.WMModel:IsValid() then
|
||
|
|
if self.MirrorVMWM and ele.VMPoseParams then
|
||
|
|
ele.VMPoseParams["BaseClass"] = nil
|
||
|
|
for i, k in pairs(ele.VMPoseParams) do
|
||
|
|
self.WMModel:SetPoseParameter(i, k)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
if ele.WMPoseParams then
|
||
|
|
ele.WMPoseParams["BaseClass"] = nil
|
||
|
|
for i, k in pairs(ele.WMPoseParams) do
|
||
|
|
self.WMModel:SetPoseParameter(i, k)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if ele.VMSkin and vm and IsValid(vm) then
|
||
|
|
vm:SetSkin(ele.VMSkin)
|
||
|
|
end
|
||
|
|
|
||
|
|
if self.WMModel and self.WMModel:IsValid() then
|
||
|
|
if self.MirrorVMWM and ele.VMSkin then
|
||
|
|
self.WMModel:SetSkin(ele.VMSkin)
|
||
|
|
self:SetSkin(ele.VMSkin)
|
||
|
|
end
|
||
|
|
if ele.WMSkin then
|
||
|
|
self.WMModel:SetSkin(ele.WMSkin)
|
||
|
|
self:SetSkin(ele.WMSkin)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if ele.VMColor and vm and IsValid(vm) then
|
||
|
|
vm:SetColor(ele.VMColor)
|
||
|
|
end
|
||
|
|
|
||
|
|
if self.WMModel and self.WMModel:IsValid() then
|
||
|
|
if self.MirrorVMWM and ele.VMSkin then
|
||
|
|
self.WMModel:SetColor(ele.VMColor or color_white)
|
||
|
|
self:SetColor(ele.VMColor or color_white)
|
||
|
|
end
|
||
|
|
if ele.WMSkin then
|
||
|
|
self.WMModel:SetColor(ele.WMColor or color_white)
|
||
|
|
self:SetColor(ele.WMColor or color_white)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if ele.VMMaterial and vm and IsValid(vm) then
|
||
|
|
vm:SetMaterial(ele.VMMaterial)
|
||
|
|
end
|
||
|
|
|
||
|
|
if self.WMModel and self.WMModel:IsValid() then
|
||
|
|
if self.MirrorVMWM and ele.VMMaterial then
|
||
|
|
self.WMModel:SetMaterial(ele.VMMaterial)
|
||
|
|
self:SetMaterial(ele.VMMaterial)
|
||
|
|
end
|
||
|
|
if ele.WMMaterial then
|
||
|
|
self.WMModel:SetMaterial(ele.WMMaterial)
|
||
|
|
self:SetMaterial(ele.WMMaterial)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if ele.VMBodygroups then
|
||
|
|
for _, i in pairs(ele.VMBodygroups) do
|
||
|
|
if !i.ind or !i.bg then continue end
|
||
|
|
|
||
|
|
if vm and IsValid(vm) and vm:GetBodygroup(i.ind) != i.bg then
|
||
|
|
vm:SetBodygroup(i.ind, i.bg)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if self.MirrorVMWM then
|
||
|
|
for _, i in pairs(ele.VMBodygroups) do
|
||
|
|
if !i.ind or !i.bg then continue end
|
||
|
|
|
||
|
|
if self.WMModel and IsValid(self.WMModel) and self.WMModel:GetBodygroup(i.ind) != i.bg then
|
||
|
|
self.WMModel:SetBodygroup(i.ind, i.bg)
|
||
|
|
end
|
||
|
|
|
||
|
|
if self:GetBodygroup(i.ind) != i.bg then
|
||
|
|
self:SetBodygroup(i.ind, i.bg)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if ele.WMBodygroups then
|
||
|
|
for _, i in pairs(ele.WMBodygroups) do
|
||
|
|
if !i.ind or !i.bg then continue end
|
||
|
|
|
||
|
|
if self.WMModel and IsValid(self.WMModel) and self.WMModel:GetBodygroup(i.ind) != i.bg then
|
||
|
|
self.WMModel:SetBodygroup(i.ind, i.bg)
|
||
|
|
end
|
||
|
|
|
||
|
|
if self:GetBodygroup(i.ind) != i.bg then
|
||
|
|
self:SetBodygroup(i.ind, i.bg)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if ele.VMBoneMods then
|
||
|
|
for bone, i in pairs(ele.VMBoneMods) do
|
||
|
|
local boneind = vm:LookupBone(bone)
|
||
|
|
|
||
|
|
if !boneind then continue end
|
||
|
|
|
||
|
|
vm:ManipulateBonePosition(boneind, i)
|
||
|
|
end
|
||
|
|
|
||
|
|
if self.MirrorVMWM then
|
||
|
|
for bone, i in pairs(ele.VMBoneMods) do
|
||
|
|
if !(self.WMModel and self.WMModel:IsValid()) then break end
|
||
|
|
local boneind = self:LookupBone(bone)
|
||
|
|
|
||
|
|
if !boneind then continue end
|
||
|
|
|
||
|
|
self:ManipulateBonePosition(boneind, i)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if ele.WMBoneMods then
|
||
|
|
for bone, i in pairs(ele.WMBoneMods) do
|
||
|
|
if !(self.WMModel and self.WMModel:IsValid()) then break end
|
||
|
|
local boneind = self:LookupBone(bone)
|
||
|
|
|
||
|
|
if !boneind then continue end
|
||
|
|
|
||
|
|
self:ManipulateBonePosition(boneind, i)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if SERVER then
|
||
|
|
self:SetupShields()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local tpmdl = IsValid(self.WMModel) and self.WMModel or self
|
||
|
|
|
||
|
|
if IsValid(vm) then
|
||
|
|
for i = 0, (vm:GetNumBodyGroups()) do
|
||
|
|
if self.Bodygroups[i] then
|
||
|
|
vm:SetBodygroup(i, self.Bodygroups[i])
|
||
|
|
end
|
||
|
|
end
|
||
|
|
self:GetBuff_Hook("Hook_ModifyBodygroups", {vm = vm, eles = ae, wm = false})
|
||
|
|
end
|
||
|
|
|
||
|
|
for i = 0, (tpmdl:GetNumBodyGroups()) do
|
||
|
|
if self.Bodygroups[i] then
|
||
|
|
tpmdl:SetBodygroup(i, self.Bodygroups[i])
|
||
|
|
end
|
||
|
|
end
|
||
|
|
self:GetBuff_Hook("Hook_ModifyBodygroups", {vm = tpmdl, eles = ae, wm = true})
|
||
|
|
|
||
|
|
for slot, v in pairs(self.Attachments) do
|
||
|
|
if !v.Installed then continue end
|
||
|
|
|
||
|
|
local func = self:GetBuff_Stat("Hook_ModifyAttBodygroups", slot)
|
||
|
|
if func and v.VElement and IsValid(v.VElement.Model) and IsValid(vm) then
|
||
|
|
func(self, {vm = vm, element = v.VElement, slottbl = v, wm = false})
|
||
|
|
end
|
||
|
|
if func and v.WElement and IsValid(v.WElement.Model) then
|
||
|
|
func(self, {vm = tpmdl, element = v.WElement, slottbl = v, wm = true})
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:GetPickX()
|
||
|
|
return ArcCW.ConVars["atts_pickx"]:GetInt()
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:Attach(slot, attname, silent, noadjust)
|
||
|
|
silent = silent or false
|
||
|
|
local attslot = self.Attachments[slot]
|
||
|
|
if !attslot then return end
|
||
|
|
if attslot.Installed == attname then return end
|
||
|
|
if attslot.Internal then return end
|
||
|
|
|
||
|
|
-- Make an additional check to see if we can detach the current attachment
|
||
|
|
if attslot.Installed and !ArcCW:PlayerCanAttach(self:GetOwner(), self, attslot.Installed, slot, attname) then
|
||
|
|
if CLIENT and !silent then
|
||
|
|
surface.PlaySound("items/medshotno1.wav")
|
||
|
|
end
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
if !ArcCW:PlayerCanAttach(self:GetOwner(), self, attname, slot, false) then
|
||
|
|
if CLIENT and !silent then
|
||
|
|
surface.PlaySound("items/medshotno1.wav")
|
||
|
|
end
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
local pick = self:GetPickX()
|
||
|
|
|
||
|
|
if pick > 0 and self:CountAttachments() >= pick and !attslot.FreeSlot
|
||
|
|
and !attslot.Installed then
|
||
|
|
if CLIENT and !silent then
|
||
|
|
surface.PlaySound("items/medshotno1.wav")
|
||
|
|
end
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
local atttbl = ArcCW.AttachmentTable[attname]
|
||
|
|
|
||
|
|
if !atttbl then return end
|
||
|
|
if !ArcCW:SlotAcceptsAtt(attslot.Slot, self, attname) then return end
|
||
|
|
if !self:CheckFlags(atttbl.ExcludeFlags, atttbl.RequireFlags) then return end
|
||
|
|
if !self:PlayerOwnsAtt(attname) then return end
|
||
|
|
|
||
|
|
local max = atttbl.Max
|
||
|
|
|
||
|
|
if max then
|
||
|
|
local amt = 0
|
||
|
|
|
||
|
|
for i, k in pairs(self.Attachments) do
|
||
|
|
if k.Installed == attname then amt = amt + 1 end
|
||
|
|
end
|
||
|
|
|
||
|
|
if amt >= max then return end
|
||
|
|
end
|
||
|
|
|
||
|
|
if attslot.SlideAmount then
|
||
|
|
attslot.SlidePos = 0.5
|
||
|
|
end
|
||
|
|
|
||
|
|
if atttbl.MountPositionOverride then
|
||
|
|
attslot.SlidePos = atttbl.MountPositionOverride
|
||
|
|
end
|
||
|
|
|
||
|
|
if atttbl.AdditionalSights then
|
||
|
|
self.SightMagnifications = {}
|
||
|
|
end
|
||
|
|
|
||
|
|
if atttbl.ToggleStats then
|
||
|
|
attslot.ToggleNum = 1
|
||
|
|
end
|
||
|
|
|
||
|
|
attslot.ToggleLock = atttbl.ToggleLockDefault or false
|
||
|
|
|
||
|
|
if CLIENT then
|
||
|
|
-- we are asking to attach something
|
||
|
|
|
||
|
|
self:SendAllDetails()
|
||
|
|
|
||
|
|
net.Start("arccw_asktoattach")
|
||
|
|
net.WriteUInt(slot, 8)
|
||
|
|
net.WriteUInt(atttbl.ID, 24)
|
||
|
|
net.SendToServer()
|
||
|
|
|
||
|
|
if !silent then
|
||
|
|
surface.PlaySound(atttbl.AttachSound or "weapons/arccw/install.wav")
|
||
|
|
end
|
||
|
|
else
|
||
|
|
self:DetachAllMergeSlots(slot)
|
||
|
|
|
||
|
|
for i, k in pairs(self.Attachments) do
|
||
|
|
if table.HasValue(k.MergeSlots or {}, slot) then
|
||
|
|
self:DetachAllMergeSlots(i)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
attslot.Installed = attname
|
||
|
|
|
||
|
|
if atttbl.Health then
|
||
|
|
attslot.HP = self:GetAttachmentMaxHP(slot)
|
||
|
|
end
|
||
|
|
|
||
|
|
if atttbl.ColorOptionsTable then
|
||
|
|
attslot.ColorOptionIndex = 1
|
||
|
|
end
|
||
|
|
|
||
|
|
ArcCW:PlayerTakeAtt(self:GetOwner(), attname)
|
||
|
|
|
||
|
|
--[[]
|
||
|
|
local fmt = self:GetBuff_Override("Override_Firemodes") or self.Firemodes
|
||
|
|
local fmi = self:GetFireMode()
|
||
|
|
|
||
|
|
if fmi > table.Count(fmt) then
|
||
|
|
self:SetFireMode(1)
|
||
|
|
end
|
||
|
|
]]
|
||
|
|
|
||
|
|
--self.UnReady = false
|
||
|
|
|
||
|
|
if SERVER then
|
||
|
|
self:NetworkWeapon()
|
||
|
|
self:SetupModel(false)
|
||
|
|
self:SetupModel(true)
|
||
|
|
ArcCW:PlayerSendAttInv(self:GetOwner())
|
||
|
|
|
||
|
|
if engine.ActiveGamemode() == "terrortown" then
|
||
|
|
self:TTT_PostAttachments()
|
||
|
|
end
|
||
|
|
else
|
||
|
|
self:SetupActiveSights()
|
||
|
|
|
||
|
|
self.LHIKAnimation = 0
|
||
|
|
self.LHIKAnimationStart = 0
|
||
|
|
self.LHIKAnimationTime = 0
|
||
|
|
|
||
|
|
self.LHIKDelta = {}
|
||
|
|
self.LHIKDeltaAng = {}
|
||
|
|
|
||
|
|
self.ViewModel_Hit = Vector(0, 0, 0)
|
||
|
|
|
||
|
|
if !silent then
|
||
|
|
self:SavePreset("autosave")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
for s, i in pairs(self.Attachments) do
|
||
|
|
if !self:CheckFlags(i.ExcludeFlags, i.RequireFlags) then
|
||
|
|
self:Detach(s, true, true)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if !noadjust then
|
||
|
|
self:AdjustAtts()
|
||
|
|
end
|
||
|
|
|
||
|
|
if atttbl.UBGL then
|
||
|
|
local ubgl_ammo = self:GetBuff_Override("UBGL_Ammo")
|
||
|
|
local ubgl_clip = self:GetBuff_Override("UBGL_Capacity")
|
||
|
|
if self:GetOwner():IsPlayer() and ArcCW.ConVars["atts_ubglautoload"]:GetBool() and ubgl_ammo then
|
||
|
|
local amt = math.min(ubgl_clip - self:Clip2(), self:GetOwner():GetAmmoCount(ubgl_ammo))
|
||
|
|
self:SetClip2(self:Clip2() + amt)
|
||
|
|
self:GetOwner():RemoveAmmo(amt, ubgl_ammo)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
self:RefreshBGs()
|
||
|
|
return true
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:DetachAllMergeSlots(slot, silent)
|
||
|
|
local slots = {slot}
|
||
|
|
|
||
|
|
table.Add(slots, (self.Attachments[slot] or {}).MergeSlots or {})
|
||
|
|
|
||
|
|
for _, i in pairs(slots) do
|
||
|
|
self:Detach(i, silent, nil, true)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:Detach(slot, silent, noadjust, nocheck)
|
||
|
|
if !slot then return end
|
||
|
|
if !self.Attachments[slot] then return end
|
||
|
|
|
||
|
|
if !self.Attachments[slot].Installed then return end
|
||
|
|
|
||
|
|
if self.Attachments[slot].Internal then return end
|
||
|
|
|
||
|
|
if !nocheck and !ArcCW:PlayerCanAttach(self:GetOwner(), self, self.Attachments[slot].Installed, slot, true) then
|
||
|
|
if CLIENT and !silent then
|
||
|
|
surface.PlaySound("items/medshotno1.wav")
|
||
|
|
end
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
if self.Attachments[slot].Installed == self.Attachments[slot].EmptyFallback then
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
local previnstall = self.Attachments[slot].Installed
|
||
|
|
|
||
|
|
local atttbl = ArcCW.AttachmentTable[previnstall]
|
||
|
|
|
||
|
|
if atttbl.UBGL then
|
||
|
|
local clip = self:Clip2()
|
||
|
|
|
||
|
|
local ammo = atttbl.UBGL_Ammo or "smg1_grenade"
|
||
|
|
|
||
|
|
if SERVER and IsValid(self:GetOwner()) then
|
||
|
|
self:GetOwner():GiveAmmo(clip, ammo, true)
|
||
|
|
end
|
||
|
|
|
||
|
|
self:SetClip2(0)
|
||
|
|
self:DeselectUBGL()
|
||
|
|
end
|
||
|
|
|
||
|
|
if self.Attachments[slot].EmptyFallback then -- is this a good name
|
||
|
|
self.Attachments[slot].Installed = self.Attachments[slot].EmptyFallback
|
||
|
|
else
|
||
|
|
self.Attachments[slot].Installed = nil
|
||
|
|
end
|
||
|
|
|
||
|
|
if self.Attachments[slot].SubAtts then
|
||
|
|
for i, k in pairs(self.Attachments[slot].SubAtts) do
|
||
|
|
self:Detach(k, true, true)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if self:GetAttachmentHP(slot) >= self:GetAttachmentMaxHP(slot) then
|
||
|
|
ArcCW:PlayerGiveAtt(self:GetOwner(), previnstall)
|
||
|
|
end
|
||
|
|
|
||
|
|
if CLIENT then
|
||
|
|
self:SendAllDetails()
|
||
|
|
|
||
|
|
-- we are asking to detach something
|
||
|
|
net.Start("arccw_asktodetach")
|
||
|
|
net.WriteUInt(slot, 8)
|
||
|
|
net.SendToServer()
|
||
|
|
|
||
|
|
if !silent then
|
||
|
|
surface.PlaySound(atttbl.DetachSound or "weapons/arccw/uninstall.wav")
|
||
|
|
end
|
||
|
|
|
||
|
|
self:SetupActiveSights()
|
||
|
|
|
||
|
|
self.LHIKAnimation = 0
|
||
|
|
self.LHIKAnimationStart = 0
|
||
|
|
self.LHIKAnimationTime = 0
|
||
|
|
|
||
|
|
if !silent then
|
||
|
|
self:SavePreset("autosave")
|
||
|
|
end
|
||
|
|
else
|
||
|
|
self:NetworkWeapon()
|
||
|
|
self:SetupModel(false)
|
||
|
|
self:SetupModel(true)
|
||
|
|
ArcCW:PlayerSendAttInv(self:GetOwner())
|
||
|
|
|
||
|
|
if engine.ActiveGamemode() == "terrortown" then
|
||
|
|
self:TTT_PostAttachments()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
self:RefreshBGs()
|
||
|
|
|
||
|
|
if !noadjust then
|
||
|
|
self:AdjustAtts()
|
||
|
|
end
|
||
|
|
return true
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:ToggleSlot(slot, num, silent, back)
|
||
|
|
local atttbl = ArcCW.AttachmentTable[self.Attachments[slot].Installed]
|
||
|
|
if !atttbl.ToggleStats then return end
|
||
|
|
|
||
|
|
local amt = 1
|
||
|
|
|
||
|
|
if back then amt = -1 end
|
||
|
|
|
||
|
|
if !num then
|
||
|
|
self.Attachments[slot].ToggleNum = (self.Attachments[slot].ToggleNum or 1) + amt
|
||
|
|
if self.Attachments[slot].ToggleNum > #atttbl.ToggleStats then
|
||
|
|
self.Attachments[slot].ToggleNum = 1
|
||
|
|
elseif self.Attachments[slot].ToggleNum < 1 then
|
||
|
|
self.Attachments[slot].ToggleNum = #atttbl.ToggleStats
|
||
|
|
end
|
||
|
|
else
|
||
|
|
self.Attachments[slot].ToggleNum = math.Clamp(num, 1, #catttbl.ToggleStats)
|
||
|
|
end
|
||
|
|
|
||
|
|
if CLIENT then
|
||
|
|
self:SendDetail_ToggleNum(slot)
|
||
|
|
self:SetupActiveSights()
|
||
|
|
elseif SERVER then
|
||
|
|
self:NetworkWeapon()
|
||
|
|
self:SetupModel(false)
|
||
|
|
self:SetupModel(true)
|
||
|
|
end
|
||
|
|
|
||
|
|
self:AdjustAtts()
|
||
|
|
|
||
|
|
for s, i in pairs(self.Attachments) do
|
||
|
|
if !self:CheckFlags(i.ExcludeFlags, i.RequireFlags) then
|
||
|
|
self:Detach(s, true)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
self:RefreshBGs()
|
||
|
|
|
||
|
|
if CLIENT and !silent and self:GetBuff_Stat("ToggleSound", slot) != false then
|
||
|
|
surface.PlaySound(self:GetBuff_Stat("ToggleSound", slot) or (atttbl.ToggleStats[slot] or {}).ToggleSound or "weapons/arccw/firemode.wav")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:AdjustAmmo(old_inf)
|
||
|
|
|
||
|
|
local new_inf = self:HasInfiniteAmmo()
|
||
|
|
|
||
|
|
local wpn = weapons.Get(self:GetClass())
|
||
|
|
local ammo = self:GetBuff_Override("Override_Ammo", wpn.Primary.Ammo)
|
||
|
|
local oldammo = self.OldAmmo or self.Primary.Ammo
|
||
|
|
|
||
|
|
if old_inf and (!new_inf or ammo != oldammo) then
|
||
|
|
self:SetClip1(0)
|
||
|
|
elseif (!old_inf and new_inf) or ammo != oldammo then
|
||
|
|
self:Unload()
|
||
|
|
end
|
||
|
|
|
||
|
|
self.Primary.Ammo = ammo
|
||
|
|
self.OldAmmo = self.Primary.Ammo
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:AdjustAtts()
|
||
|
|
local old_inf = self:HasInfiniteAmmo()
|
||
|
|
|
||
|
|
self:RecalcAllBuffs()
|
||
|
|
|
||
|
|
-- Recalculate active elements so dependencies aren't fucked
|
||
|
|
self.ActiveElementCache = nil
|
||
|
|
self:GetActiveElements(true)
|
||
|
|
self.ModifiedCache = {}
|
||
|
|
|
||
|
|
-- Tempoarily disable modified cache, since we're building it right now
|
||
|
|
MODIFIED_CACHE = false
|
||
|
|
|
||
|
|
for i, k in pairs(self.Attachments) do
|
||
|
|
if !k.Installed then continue end
|
||
|
|
local ok = true
|
||
|
|
|
||
|
|
if !ArcCW:SlotAcceptsAtt(k.Slot, self, k.Installed) then ok = false end
|
||
|
|
if ok and !self:CheckFlags(k.ExcludeFlags, k.RequireFlags) then ok = false end
|
||
|
|
|
||
|
|
local atttbl = ArcCW.AttachmentTable[k.Installed]
|
||
|
|
|
||
|
|
if !atttbl then continue end
|
||
|
|
if ok and !self:CheckFlags(atttbl.ExcludeFlags, atttbl.RequireFlags) then ok = false end
|
||
|
|
|
||
|
|
if !ok then
|
||
|
|
self:Detach(i, true)
|
||
|
|
continue
|
||
|
|
end
|
||
|
|
|
||
|
|
-- Cache all possible value modifiers
|
||
|
|
for var, v in pairs(atttbl) do
|
||
|
|
self.ModifiedCache[var] = true
|
||
|
|
if var == "ToggleStats" or var == "Override_Firemodes" then
|
||
|
|
for _, v2 in pairs(v) do
|
||
|
|
for var2, _ in pairs(v2) do
|
||
|
|
self.ModifiedCache[var2] = true
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
for _, e in pairs(self.AttachmentElements) do
|
||
|
|
if !istable(e) then continue end
|
||
|
|
for var, v in pairs(e) do
|
||
|
|
self.ModifiedCache[var] = true
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
for _, e in pairs(self.Firemodes) do
|
||
|
|
if !istable(e) then continue end
|
||
|
|
for var, v in pairs(e) do
|
||
|
|
self.ModifiedCache[var] = true
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
MODIFIED_CACHE = true
|
||
|
|
|
||
|
|
if SERVER then
|
||
|
|
local cs = self:GetCapacity() + self:GetChamberSize()
|
||
|
|
|
||
|
|
if self:Clip1() > cs and self:Clip1() != ArcCW.BottomlessMagicNumber then
|
||
|
|
local diff = self:Clip1() - cs
|
||
|
|
self:SetClip1(cs)
|
||
|
|
|
||
|
|
if self:GetOwner():IsValid() and !self:GetOwner():IsNPC() then
|
||
|
|
self:GetOwner():GiveAmmo(diff, self.Primary.Ammo, true)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
else
|
||
|
|
local se = self:GetBuff_Override("Override_ShootEntity") or self.ShootEntity
|
||
|
|
if se then
|
||
|
|
local path = "arccw/weaponicons/" .. self:GetClass()
|
||
|
|
local mat = Material(path)
|
||
|
|
|
||
|
|
if !mat:IsError() then
|
||
|
|
local tex = mat:GetTexture("$basetexture")
|
||
|
|
local texpath = tex:GetName()
|
||
|
|
|
||
|
|
killicon.Add(se, texpath, Color(255, 255, 255))
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local ubgl_ammo = self:GetBuff_Override("UBGL_Ammo")
|
||
|
|
local ubgl_clip = self:GetBuff_Override("UBGL_Capacity")
|
||
|
|
|
||
|
|
self.Secondary.ClipSize = ubgl_clip or -1
|
||
|
|
self.Secondary.Ammo = ubgl_ammo or "none"
|
||
|
|
|
||
|
|
--[[]
|
||
|
|
if ubgl_clip then
|
||
|
|
self.Secondary.ClipSize = ubgl_clip
|
||
|
|
if self:GetOwner():IsPlayer() and ArcCW.ConVars["atts_ubglautoload"]:GetBool() and ubgl_ammo then
|
||
|
|
local amt = math.min(ubgl_clip - self:Clip2(), self:GetOwner():GetAmmoCount(ubgl_ammo))
|
||
|
|
self:SetClip2(self:Clip2() + amt)
|
||
|
|
self:GetOwner():RemoveAmmo(amt, ubgl_ammo)
|
||
|
|
end
|
||
|
|
else
|
||
|
|
self.Secondary.ClipSize = -1
|
||
|
|
end
|
||
|
|
]]
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
self:RebuildSubSlots()
|
||
|
|
|
||
|
|
local fmt = self:GetBuff_Override("Override_Firemodes", self.Firemodes)
|
||
|
|
fmt["BaseClass"] = nil
|
||
|
|
|
||
|
|
local fmi = self:GetFireMode()
|
||
|
|
if !fmt[fmi] then self:SetFireMode(1) end
|
||
|
|
|
||
|
|
self:AdjustAmmo(old_inf)
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:GetAttachmentMaxHP(slot)
|
||
|
|
if !self.Attachments[slot] then return 100 end
|
||
|
|
if !self.Attachments[slot].Installed then return 100 end
|
||
|
|
local maxhp = 100
|
||
|
|
local atttbl = ArcCW.AttachmentTable[self.Attachments[slot].Installed]
|
||
|
|
|
||
|
|
if atttbl.Health then
|
||
|
|
maxhp = atttbl.Health
|
||
|
|
end
|
||
|
|
|
||
|
|
return maxhp
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:GetAttachmentHP(slot)
|
||
|
|
if !self.Attachments[slot] then return 100 end
|
||
|
|
if !self.Attachments[slot].Installed then return 100 end
|
||
|
|
|
||
|
|
if self.Attachments[slot].HP then return self.Attachments[slot].HP end
|
||
|
|
|
||
|
|
self.Attachments[slot].HP = self:GetAttachmentMaxHP(slot)
|
||
|
|
|
||
|
|
return self.Attachments[slot].HP
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:ApplyAttachmentShootDamage()
|
||
|
|
local any = false
|
||
|
|
for j, i in pairs(self.Attachments) do
|
||
|
|
if !i.Installed then continue end
|
||
|
|
local atttbl = ArcCW.AttachmentTable[i.Installed]
|
||
|
|
|
||
|
|
if !atttbl.Health then continue end
|
||
|
|
|
||
|
|
if atttbl.DamageOnShoot then
|
||
|
|
self:DamageAttachment(j, atttbl.DamageOnShoot)
|
||
|
|
any = true
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if any then
|
||
|
|
self:SendAttHP()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:DamageAttachment(slot, dmg)
|
||
|
|
if !self.Attachments[slot] then return end
|
||
|
|
if !self.Attachments[slot].Installed then return end
|
||
|
|
|
||
|
|
self.Attachments[slot].HP = self:GetAttachmentHP(slot) - dmg
|
||
|
|
|
||
|
|
if self:GetAttachmentHP(slot) <= 0 then
|
||
|
|
local atttbl = ArcCW.AttachmentTable[self.Attachments[slot].Installed]
|
||
|
|
|
||
|
|
if atttbl.Hook_AttDestroyed then
|
||
|
|
atttbl.Hook_AttDestroyed(self, {slot = slot, dmg = dmg})
|
||
|
|
end
|
||
|
|
|
||
|
|
self:Detach(slot, true)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:SendAttHP()
|
||
|
|
net.Start("arccw_sendatthp")
|
||
|
|
for i, k in pairs(self.Attachments) do
|
||
|
|
if !k.Installed then continue end
|
||
|
|
local atttbl = ArcCW.AttachmentTable[k.Installed]
|
||
|
|
|
||
|
|
if atttbl.Health then
|
||
|
|
net.WriteBool(true)
|
||
|
|
net.WriteUInt(i, 8)
|
||
|
|
net.WriteFloat(self:GetAttachmentHP(i))
|
||
|
|
end
|
||
|
|
end
|
||
|
|
net.WriteBool(false)
|
||
|
|
net.Send(self:GetOwner())
|
||
|
|
end
|
||
|
|
|
||
|
|
-- local node = {b = {}, i = "" t = 0}
|
||
|
|
-- b: branches
|
||
|
|
-- i: installed
|
||
|
|
-- t: toggle
|
||
|
|
-- s: slide
|
||
|
|
-- h: hp
|
||
|
|
|
||
|
|
-- recursive function
|
||
|
|
-- gets a tree of all the attachments installed in subslots subordinate to a particular slot
|
||
|
|
function SWEP:GetSubSlotTree(i)
|
||
|
|
if !self.Attachments[i] then return nil end
|
||
|
|
if !self.Attachments[i].Installed then return nil end
|
||
|
|
if !self.Attachments[i].SubAtts then return
|
||
|
|
{
|
||
|
|
b = {},
|
||
|
|
i = self.Attachments[i].Installed,
|
||
|
|
t = self.Attachments[i].ToggleNum,
|
||
|
|
s = self.Attachments[i].SlidePos,
|
||
|
|
h = self.Attachments[i].Health}
|
||
|
|
end
|
||
|
|
|
||
|
|
local ss = {}
|
||
|
|
for j, k in pairs(self.Attachments[i].SubAtts) do
|
||
|
|
if k == i then continue end
|
||
|
|
local sst = self:GetSubSlotTree(k)
|
||
|
|
if sst then
|
||
|
|
ss[j] = sst
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
return {b = ss, i = self.Attachments[i].Installed}
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:SubSlotTreeReinstall(slot, subslottree)
|
||
|
|
for i, k in pairs(self.Attachments[slot].SubAtts or {}) do
|
||
|
|
-- i = index
|
||
|
|
-- k = slot
|
||
|
|
self.Attachments[k].Installed = subslottree[i].i
|
||
|
|
self.Attachments[k].ToggleNum = subslottree[i].t
|
||
|
|
self.Attachments[k].SlidePos = subslottree[i].s
|
||
|
|
self.Attachments[k].Health = subslottree[i].h
|
||
|
|
|
||
|
|
if subslottree.b[i] then
|
||
|
|
self:SubSlotTreeReinstall(i, subslottree.b[i])
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:RebuildSubSlots()
|
||
|
|
-- this function rebuilds the subslots while preserving installed attachment data
|
||
|
|
local subslottrees = {}
|
||
|
|
|
||
|
|
local baseatts = table.Count(weapons.Get(self:GetClass()).Attachments)
|
||
|
|
|
||
|
|
self.Attachments.BaseClass = nil
|
||
|
|
|
||
|
|
for i = 1, baseatts do
|
||
|
|
subslottrees[baseatts] = self:GetSubSlotTree(i)
|
||
|
|
end
|
||
|
|
|
||
|
|
-- remove all sub slots
|
||
|
|
for i, k in pairs(self.Attachments) do
|
||
|
|
if !isnumber(i) then continue end
|
||
|
|
if !istable(k) then continue end
|
||
|
|
if i > baseatts then
|
||
|
|
self.Attachments[i] = nil
|
||
|
|
else
|
||
|
|
self.Attachments[i].SubAtts = nil
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
self.SubSlotCount = 0
|
||
|
|
-- add the sub slots back
|
||
|
|
for i, k in pairs(self.Attachments) do
|
||
|
|
if !k.Installed then continue end
|
||
|
|
local att = ArcCW.AttachmentTable[k.Installed]
|
||
|
|
if !att then continue end
|
||
|
|
if !istable(k) then continue end
|
||
|
|
|
||
|
|
if att.SubSlots then
|
||
|
|
self:AddSubSlot(i, k.Installed)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
-- add the sub slot data back
|
||
|
|
|
||
|
|
for i, k in pairs(subslottrees) do
|
||
|
|
self:SubSlotTreeReinstall(i, k)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:AddSubSlot(i, attname)
|
||
|
|
local baseatts = table.Count(weapons.Get(self:GetClass()).Attachments)
|
||
|
|
local att = ArcCW.AttachmentTable[attname]
|
||
|
|
if att.SubSlots then
|
||
|
|
self.Attachments[i].SubAtts = {}
|
||
|
|
local og_slot = self.Attachments[i]
|
||
|
|
for ind, slot in pairs(att.SubSlots) do
|
||
|
|
if !istable(slot) then continue end
|
||
|
|
self.SubSlotCount = self.SubSlotCount + 1
|
||
|
|
local index = baseatts + self.SubSlotCount
|
||
|
|
self.Attachments[index] = slot
|
||
|
|
self.Attachments[index].Bone = og_slot.Bone
|
||
|
|
self.Attachments[index].WMBone = og_slot.WMBone
|
||
|
|
self.Attachments[index].ExtraSightDist = 0--self.Attachments[index].ExtraSightDist or og_slot.ExtraSightDist
|
||
|
|
self.Attachments[index].CorrectivePos = og_slot.CorrectivePos
|
||
|
|
self.Attachments[index].CorrectiveAng = og_slot.CorrectiveAng
|
||
|
|
og_slot.SubAtts[ind] = index
|
||
|
|
|
||
|
|
if slot.MergeSlots then
|
||
|
|
self.Attachments[index].MergeSlots = {}
|
||
|
|
for _, k2 in pairs(slot.MergeSlots) do
|
||
|
|
table.insert(self.Attachments[index].MergeSlots, k2 + index)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if slot.Offset then
|
||
|
|
self.Attachments[index].Offset = {
|
||
|
|
vpos = Vector(0, 0, 0),
|
||
|
|
vang = Angle(0, 0, 0),
|
||
|
|
wpos = Vector(0, 0, 0),
|
||
|
|
wang = Angle(0, 0, 0)
|
||
|
|
}
|
||
|
|
|
||
|
|
if slot.Offset.vang then
|
||
|
|
self.Attachments[index].Offset.vang = slot.Offset.vang + (og_slot.Offset.vang or Angle(0, 0, 0))
|
||
|
|
end
|
||
|
|
|
||
|
|
if slot.Offset.wang then
|
||
|
|
self.Attachments[index].Offset.wang = slot.Offset.wang + (og_slot.Offset.wang or Angle(0, 0, 0))
|
||
|
|
end
|
||
|
|
|
||
|
|
if slot.Offset.vpos then
|
||
|
|
self.Attachments[index].Offset.vpos = LocalToWorld(slot.Offset.vpos, self.Attachments[index].Offset.vang, og_slot.Offset.vpos, og_slot.Offset.vang or Angle(0, 0, 0))
|
||
|
|
end
|
||
|
|
|
||
|
|
if slot.Offset.wpos then
|
||
|
|
self.Attachments[index].Offset.wpos = LocalToWorld(slot.Offset.wpos, self.Attachments[index].Offset.wang, og_slot.Offset.wpos, og_slot.Offset.wang or Angle(0, 0, 0))
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
self.Attachments[index].SubAtts = {}
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function SWEP:OnReloaded()
|
||
|
|
self:RecalcAllBuffs()
|
||
|
|
self:SetupActiveSights()
|
||
|
|
end
|