mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-16 21:33:46 +03:00
728 lines
18 KiB
Lua
728 lines
18 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/
|
|
--]]
|
|
|
|
|
|
-- Copyright (c) 2018-2020 TFA Base Devs
|
|
|
|
-- Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
-- of this software and associated documentation files (the "Software"), to deal
|
|
-- in the Software without restriction, including without limitation the rights
|
|
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
-- copies of the Software, and to permit persons to whom the Software is
|
|
-- furnished to do so, subject to the following conditions:
|
|
|
|
-- The above copyright notice and this permission notice shall be included in all
|
|
-- copies or substantial portions of the Software.
|
|
|
|
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
-- SOFTWARE.
|
|
|
|
local ATT_DIMENSION
|
|
local ATT_MAX_SCREEN_RATIO = 1 / 3
|
|
local tableCopy = table.Copy
|
|
|
|
SWEP.Attachments = {} --[MDL_ATTACHMENT] = = { offset = { 0, 0 }, atts = { "sample_attachment_1", "sample_attachment_2" }, sel = 1, order = 1 } --offset will move the offset the display from the weapon attachment when using CW2.0 style attachment display --atts is a table containing the visible attachments --sel allows you to have an attachment pre-selected, and is used internally by the base to show which attachment is selected in each category. --order is the order it will appear in the TFA style attachment menu
|
|
SWEP.AttachmentCache = {} --["att_name"] = true
|
|
SWEP.AttachmentTableCache = {}
|
|
SWEP.AttachmentCount = 0
|
|
SWEP.AttachmentDependencies = {} --{["si_acog"] = {"bg_rail"}}
|
|
SWEP.AttachmentExclusions = {} --{ ["si_iron"] = {"bg_heatshield"} }
|
|
SWEP.AttachmentTableOverride = {}
|
|
|
|
local pairs, type, tonumber = pairs, type, tonumber
|
|
local string, IsValid = string, IsValid
|
|
local table = table
|
|
|
|
function SWEP:RemoveUnusedAttachments()
|
|
for k, v in pairs(self.Attachments) do
|
|
if v.atts then
|
|
local t = {}
|
|
local i = 1
|
|
|
|
for _, b in pairs(v.atts) do
|
|
if TFA.Attachments.Atts[b] then
|
|
t[i] = b
|
|
i = i + 1
|
|
end
|
|
end
|
|
|
|
v.atts = tableCopy(t)
|
|
end
|
|
|
|
if #v.atts <= 0 then
|
|
self.Attachments[k] = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
local function select_function_table(target)
|
|
-- idk
|
|
local found_table
|
|
|
|
for i_index, base_value in pairs(target) do
|
|
if istable(base_value) then
|
|
found_table = base_value
|
|
end
|
|
end
|
|
|
|
if not found_table then
|
|
found_table = {}
|
|
table.insert(target, found_table)
|
|
end
|
|
|
|
return found_table
|
|
end
|
|
|
|
local function get(path, target)
|
|
if #path == 1 then
|
|
return target[path[1]]
|
|
end
|
|
|
|
local _target = target[path[1]]
|
|
|
|
if _target == nil then
|
|
target[path[1]] = {}
|
|
_target = target[path[1]]
|
|
end
|
|
|
|
for i = 2, #path do
|
|
if not istable(_target) then
|
|
return
|
|
end
|
|
|
|
if _target[path[i]] == nil then _target[path[i]] = {} end
|
|
|
|
if istable(_target[path[i]]) and _target[path[i]].functionTable and i ~= #path then
|
|
_target = select_function_table(_target[path[i]])
|
|
else
|
|
_target = _target[path[i]]
|
|
end
|
|
end
|
|
|
|
return _target
|
|
end
|
|
|
|
local function set(path, target, value)
|
|
if #path == 1 then
|
|
target[path[1]] = value
|
|
return value
|
|
end
|
|
|
|
local _target = target[path[1]]
|
|
|
|
if _target == nil then
|
|
target[path[1]] = {}
|
|
_target = target[path[1]]
|
|
end
|
|
|
|
for i = 2, #path - 1 do
|
|
if not istable(_target) then
|
|
return value
|
|
end
|
|
|
|
if _target[path[i]] == nil then _target[path[i]] = {} end
|
|
|
|
if _target[path[i]].functionTable then
|
|
_target = select_function_table(_target[path[i]])
|
|
else
|
|
_target = _target[path[i]]
|
|
end
|
|
end
|
|
|
|
if istable(_target) then
|
|
if istable(_target[path[#path]]) and _target[path[#path]].functionTable then
|
|
table.insert(select_function_table(_target[path[#path]]), value)
|
|
else
|
|
_target[path[#path]] = value
|
|
end
|
|
end
|
|
|
|
return value
|
|
end
|
|
|
|
local function CloneTableRecursive(source, target, root, source_version, target_version)
|
|
for index, value in pairs(source) do
|
|
local _root = root == "" and index or (root .. "." .. index)
|
|
|
|
-- merge two tables
|
|
if istable(value) then
|
|
local baseTable = get(TFA.GetStatPath(_root, source_version, target_version), target)
|
|
|
|
-- target is a function table
|
|
if istable(baseTable) and baseTable.functionTable then
|
|
local found_table
|
|
|
|
for i_index, base_value in pairs(baseTable) do
|
|
if istable(base_value) then
|
|
found_table = base_value
|
|
end
|
|
end
|
|
|
|
if not found_table then
|
|
found_table = {}
|
|
table.insert(baseTable, 1, found_table)
|
|
end
|
|
|
|
CloneTableRecursive(value, target, _root, source_version, target_version)
|
|
-- target is a regular table
|
|
else
|
|
if not istable(baseTable) then
|
|
set(TFA.GetStatPath(_root, source_version, target_version), target, {})
|
|
end
|
|
|
|
CloneTableRecursive(value, target, _root, source_version, target_version)
|
|
end
|
|
-- final value is determined by function
|
|
elseif isfunction(value) then
|
|
local temp
|
|
local get_path = TFA.GetStatPath(_root, source_version, target_version)
|
|
local get_table = get(get_path, target)
|
|
|
|
if get_table ~= nil and not istable(get_table) then
|
|
temp = get_table
|
|
end
|
|
|
|
local get_value = not istable(get_table) and set(get_path, target, {}) or get_table
|
|
|
|
-- mark this table as function based
|
|
get_value.functionTable = true
|
|
|
|
if temp ~= nil then
|
|
-- insert variable that was there before
|
|
table.insert(get_value, temp)
|
|
end
|
|
|
|
-- insert function
|
|
table.insert(get_value, value)
|
|
-- final value is a scalar
|
|
else
|
|
local get_table = get(TFA.GetStatPath(_root, source_version, target_version), target)
|
|
|
|
if istable(get_table) and get_table.functionTable then
|
|
table.insert(get_table, 1, value)
|
|
else
|
|
set(TFA.GetStatPath(_root, source_version, target_version), target, value)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function SWEP:BuildAttachmentCache()
|
|
self.AttachmentCount = 0
|
|
|
|
for k, v in pairs(self.Attachments) do
|
|
if v.atts then
|
|
for l, b in pairs(v.atts) do
|
|
self.AttachmentCount = self.AttachmentCount + 1
|
|
self.AttachmentCache[b] = (v.sel == l) and k or false
|
|
end
|
|
end
|
|
end
|
|
|
|
table.Empty(self.AttachmentTableCache)
|
|
|
|
for attName, sel in pairs(self.AttachmentCache) do
|
|
if not sel then goto CONTINUE end
|
|
if not TFA.Attachments.Atts[attName] then goto CONTINUE end
|
|
|
|
local srctbl = TFA.Attachments.Atts[attName].WeaponTable
|
|
|
|
if istable(srctbl) then
|
|
CloneTableRecursive(srctbl, self.AttachmentTableCache, "", TFA.Attachments.Atts[attName].TFADataVersion or 0, self.TFADataVersion or 0)
|
|
end
|
|
|
|
if istable(self.AttachmentTableOverride[attName]) then
|
|
CloneTableRecursive(self.AttachmentTableOverride[attName], self.AttachmentTableCache, "", self.TFADataVersion or 0, self.TFADataVersion or 0)
|
|
end
|
|
|
|
::CONTINUE::
|
|
end
|
|
|
|
self:ClearStatCache()
|
|
self:ClearMaterialCache()
|
|
end
|
|
|
|
function SWEP:IsAttached(attn)
|
|
return isnumber(self.AttachmentCache[attn])
|
|
end
|
|
|
|
local tc
|
|
|
|
function SWEP:CanAttach(attn)
|
|
local retVal = hook.Run("TFA_PreCanAttach", self, attn)
|
|
if retVal ~= nil then return retVal end
|
|
local self2 = self:GetTable()
|
|
|
|
if not self2.HasBuiltMutualExclusions then
|
|
tc = tableCopy(self2.AttachmentExclusions)
|
|
|
|
for k, v in pairs(tc) do
|
|
if k ~= "BaseClass" then
|
|
for _, b in pairs(v) do
|
|
self2.AttachmentExclusions[b] = self2.AttachmentExclusions[b] or {}
|
|
|
|
if not table.HasValue(self2.AttachmentExclusions[b]) then
|
|
self2.AttachmentExclusions[b][#self2.AttachmentExclusions[b] + 1] = k
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
self2.HasBuiltMutualExclusions = true
|
|
end
|
|
|
|
if self.AttachmentExclusions[attn] then
|
|
for _, v in pairs(self.AttachmentExclusions[attn]) do
|
|
if self:IsAttached(v) then return false end
|
|
end
|
|
end
|
|
|
|
if self2.AttachmentDependencies[attn] then
|
|
local t = self2.AttachmentDependencies[attn]
|
|
|
|
if isstring(t) then
|
|
if t ~= "BaseClass" and not self2.IsAttached(self, t) then return false end
|
|
elseif istable(t) then
|
|
t.type = t.type or "OR"
|
|
|
|
if t.type == "AND" then
|
|
for k, v in pairs(self.AttachmentDependencies[attn]) do
|
|
if k ~= "BaseClass" and k ~= "type" and not self2.IsAttached(self, v) then return false end
|
|
end
|
|
else
|
|
local cnt = 0
|
|
|
|
for k, v in pairs(self.AttachmentDependencies[attn]) do
|
|
if k ~= "BaseClass" and k ~= "type" and self2.IsAttached(self, v) then
|
|
cnt = cnt + 1
|
|
end
|
|
end
|
|
|
|
if cnt == 0 then return false end
|
|
end
|
|
end
|
|
end
|
|
|
|
local atTable = TFA.Attachments.Atts[attn]
|
|
if not atTable or not atTable:CanAttach(self) then return false end
|
|
|
|
local retVal2 = hook.Run("TFA_CanAttach", self, attn)
|
|
if retVal2 ~= nil then return retVal2 end
|
|
|
|
return true
|
|
end
|
|
|
|
local ATTACHMENT_SORTING_DEPENDENCIES = false
|
|
function SWEP:ForceAttachmentReqs(attn)
|
|
if not ATTACHMENT_SORTING_DEPENDENCIES then
|
|
ATTACHMENT_SORTING_DEPENDENCIES = true
|
|
local related = {}
|
|
|
|
for k, v in pairs(self.AttachmentDependencies) do
|
|
if istable(v) then
|
|
for _, b in pairs(v) do
|
|
if k == attn then
|
|
related[b] = true
|
|
elseif b == attn then
|
|
related[k] = true
|
|
end
|
|
end
|
|
elseif isstring(v) then
|
|
if k == attn then
|
|
related[v] = true
|
|
elseif v == attn then
|
|
related[k] = true
|
|
end
|
|
end
|
|
end
|
|
|
|
for k, v in pairs(self.AttachmentExclusions) do
|
|
if istable(v) then
|
|
for _, b in pairs(v) do
|
|
if k == attn then
|
|
related[b] = true
|
|
elseif b == attn then
|
|
related[k] = true
|
|
end
|
|
end
|
|
elseif isstring(v) then
|
|
if k == attn then
|
|
related[v] = true
|
|
elseif v == attn then
|
|
related[k] = true
|
|
end
|
|
end
|
|
end
|
|
|
|
for k, v in pairs(self.AttachmentCache) do
|
|
if v and related[k] and not self:CanAttach(k) then
|
|
self:SetTFAAttachment(v, 0, true, true)
|
|
end
|
|
end
|
|
|
|
ATTACHMENT_SORTING_DEPENDENCIES = false
|
|
end
|
|
end
|
|
|
|
do
|
|
local self3, att_neue, att_old
|
|
|
|
local function attach()
|
|
att_neue:Attach(self3)
|
|
end
|
|
|
|
local function detach()
|
|
att_old:Detach(self3)
|
|
end
|
|
|
|
function SWEP:SetTFAAttachment(cat, id, nw, force)
|
|
self3 = self
|
|
local self2 = self:GetTable()
|
|
|
|
if not self2.Attachments[cat] then return false end
|
|
|
|
if isstring(id) then
|
|
if id == "" then
|
|
id = -1
|
|
else
|
|
id = table.KeyFromValue(self2.Attachments[cat].atts, id)
|
|
if not id then return false end
|
|
end
|
|
end
|
|
|
|
if id <= 0 and self2.Attachments[cat].default and type(self2.Attachments[cat].default) == "string" and self2.Attachments[cat].default ~= "" then
|
|
return self2.SetTFAAttachment(self, cat, self2.Attachments[cat].default, nw, force)
|
|
end
|
|
|
|
local attn = self2.Attachments[cat].atts[id] or ""
|
|
local attn_old = self2.Attachments[cat].atts[self2.Attachments[cat].sel or -1] or ""
|
|
if SERVER and id > 0 and not (force or self2.CanAttach(self, attn)) then return false end
|
|
|
|
if id ~= self2.Attachments[cat].sel then
|
|
att_old = TFA.Attachments.Atts[self2.Attachments[cat].atts[self2.Attachments[cat].sel] or -1]
|
|
local detach_status = att_old == nil
|
|
|
|
if att_old then
|
|
detach_status = ProtectedCall(detach)
|
|
|
|
if detach_status then
|
|
hook.Run("TFA_Attachment_Detached", self, attn_old, att_old, cat, id, force)
|
|
end
|
|
end
|
|
|
|
att_neue = TFA.Attachments.Atts[self2.Attachments[cat].atts[id] or -1]
|
|
local attach_status = att_neue == nil
|
|
|
|
if detach_status then
|
|
if att_neue then
|
|
attach_status = ProtectedCall(attach)
|
|
|
|
if attach_status then
|
|
hook.Run("TFA_Attachment_Attached", self, attn, att_neue, cat, id, force)
|
|
end
|
|
end
|
|
end
|
|
|
|
if detach_status and attach_status then
|
|
if id > 0 then
|
|
self2.Attachments[cat].sel = id
|
|
else
|
|
self2.Attachments[cat].sel = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
self2.BuildAttachmentCache(self)
|
|
self2.ForceAttachmentReqs(self, (id > 0) and attn or attn_old)
|
|
|
|
if nw and (not isentity(nw) or SERVER) then
|
|
net.Start("TFA_Attachment_Set")
|
|
net.WriteUInt(cat, 8)
|
|
net.WriteString(attn)
|
|
|
|
if SERVER then
|
|
net.WriteEntity(self)
|
|
|
|
if isentity(nw) then
|
|
local filter = RecipientFilter()
|
|
filter:AddPVS(self:GetPos())
|
|
filter:RemovePlayer(nw)
|
|
net.Send(filter)
|
|
else
|
|
net.SendPVS(self:GetPos())
|
|
end
|
|
elseif CLIENT then
|
|
net.SendToServer()
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
end
|
|
|
|
function SWEP:Attach(attname, force)
|
|
if not attname or not IsValid(self) then return false end
|
|
if self.AttachmentCache[attname] == nil then return false end
|
|
|
|
for cat, tbl in pairs(self.Attachments) do
|
|
local atts = tbl.atts
|
|
|
|
for id, att in ipairs(atts) do
|
|
if att == attname then return self:SetTFAAttachment(cat, id, true, force) end
|
|
end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
function SWEP:Detach(attname, force)
|
|
if not attname or not IsValid(self) then return false end
|
|
local cat = self.AttachmentCache[attname]
|
|
if not cat then return false end
|
|
|
|
return self:SetTFAAttachment(cat, 0, true, force)
|
|
end
|
|
|
|
function SWEP:RandomizeAttachments(force)
|
|
for key, slot in pairs(self.AttachmentCache) do
|
|
if slot then
|
|
self:Detach(key)
|
|
end
|
|
end
|
|
|
|
for category, def in pairs(self.Attachments) do
|
|
if istable(def) and istable(def.atts) and #def.atts > 0 then
|
|
if math.random() > 0.3 then
|
|
local randkey = math.random(1, #def.atts)
|
|
self:SetTFAAttachment(category, randkey, true, force)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local attachments_sorted_alphabetically = GetConVar("sv_tfa_attachments_alphabetical")
|
|
|
|
function SWEP:InitAttachments()
|
|
if self.HasInitAttachments then return end
|
|
hook.Run("TFA_PreInitAttachments", self)
|
|
self.HasInitAttachments = true
|
|
|
|
for k, v in pairs(self.Attachments) do
|
|
if type(k) == "string" then
|
|
local tatt = self:VMIV() and self.OwnerViewModel:LookupAttachment(k) or self:LookupAttachment(k)
|
|
|
|
if tatt > 0 then
|
|
self.Attachments[tatt] = v
|
|
end
|
|
|
|
self.Attachments[k] = nil
|
|
elseif (not attachments_sorted_alphabetically) and attachments_sorted_alphabetically:GetBool() then
|
|
local sval = v.atts[v.sel]
|
|
|
|
table.sort(v.atts, function(a, b)
|
|
local aname = ""
|
|
local bname = ""
|
|
local att_a = TFA.Attachments.Atts[a]
|
|
|
|
if att_a then
|
|
aname = att_a.Name or a
|
|
end
|
|
|
|
local att_b = TFA.Attachments.Atts[b]
|
|
|
|
if att_b then
|
|
bname = att_b.Name or b
|
|
end
|
|
|
|
return aname < bname
|
|
end)
|
|
|
|
if sval then
|
|
v.sel = table.KeyFromValue(v.atts, sval) or v.sel
|
|
end
|
|
end
|
|
end
|
|
|
|
for k, v in pairs(self.Attachments) do
|
|
if v.sel then
|
|
local vsel = v.sel
|
|
v.sel = nil
|
|
|
|
if type(vsel) == "string" then
|
|
vsel = table.KeyFromValue(v.atts, vsel) or tonumber(vsel)
|
|
|
|
if not vsel then goto CONTINUE end
|
|
end
|
|
|
|
timer.Simple(0, function()
|
|
if IsValid(self) and self.SetTFAAttachment then
|
|
self:SetTFAAttachment(k, vsel, false)
|
|
end
|
|
end)
|
|
|
|
if SERVER and game.SinglePlayer() then
|
|
timer.Simple(0.05, function()
|
|
if IsValid(self) and self.SetTFAAttachment then
|
|
self:SetTFAAttachment(k, vsel, true)
|
|
end
|
|
end)
|
|
end
|
|
end
|
|
|
|
::CONTINUE::
|
|
end
|
|
|
|
hook.Run("TFA_PostInitAttachments", self)
|
|
self:RemoveUnusedAttachments()
|
|
self:BuildAttachmentCache()
|
|
hook.Run("TFA_FinalInitAttachments", self)
|
|
end
|
|
|
|
function SWEP:GenerateVGUIAttachmentTable()
|
|
self.VGUIAttachments = {}
|
|
local keyz = table.GetKeys(self.Attachments)
|
|
table.RemoveByValue(keyz, "BaseClass")
|
|
|
|
table.sort(keyz, function(a, b)
|
|
--A and B are keys
|
|
local v1 = self.Attachments[a]
|
|
local v2 = self.Attachments[b]
|
|
|
|
if v1 and v2 and (v1.order or v2.order) then
|
|
return (v1.order or a) < (v2.order or b)
|
|
else
|
|
return a < b
|
|
end
|
|
end)
|
|
|
|
for _, k in ipairs(keyz) do
|
|
local v = self.Attachments[k]
|
|
|
|
if not v.hidden then
|
|
local aTbl = tableCopy(v)
|
|
|
|
aTbl.cat = k
|
|
aTbl.offset = nil
|
|
aTbl.order = nil
|
|
|
|
table.insert(self.VGUIAttachments, aTbl)
|
|
end
|
|
end
|
|
|
|
ATT_DIMENSION = math.Round(TFA.ScaleH(TFA.Attachments.IconSize))
|
|
local max_row_atts = math.floor(ScrW() * ATT_MAX_SCREEN_RATIO / ATT_DIMENSION)
|
|
local i = 1
|
|
|
|
while true do
|
|
local v = self.VGUIAttachments[i]
|
|
if not v then break end
|
|
i = i + 1
|
|
|
|
for l, b in pairs(v.atts) do
|
|
if not istable(b) then
|
|
v.atts[l] = {b, l} --name, ID
|
|
end
|
|
end
|
|
|
|
if (#v.atts > max_row_atts) then
|
|
while (#v.atts > max_row_atts) do
|
|
local t = tableCopy(v)
|
|
|
|
for _ = 1, max_row_atts do
|
|
table.remove(t.atts, 1)
|
|
end
|
|
|
|
for _ = 1, #v.atts - max_row_atts do
|
|
table.remove(v.atts)
|
|
end
|
|
|
|
table.insert(self.VGUIAttachments, i, t)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local bgt = {}
|
|
SWEP.ViewModelBodygroups = {}
|
|
SWEP.WorldModelBodygroups = {}
|
|
|
|
function SWEP:IterateBodygroups(entity, tablename, version)
|
|
local self2 = self:GetTable()
|
|
|
|
bgt = self2.GetStatVersioned(self, tablename, version or 0, self2[tablename])
|
|
|
|
for k, v in pairs(bgt) do
|
|
if isnumber(k) then
|
|
local bgn = entity:GetBodygroupName(k)
|
|
|
|
if bgt[bgn] then
|
|
v = bgt[bgn]
|
|
end
|
|
|
|
if entity:GetBodygroup(k) ~= v then
|
|
entity:SetBodygroup(k, v)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function SWEP:ProcessBodygroups()
|
|
local self2 = self:GetTable()
|
|
local ViewModelBodygroups = self:GetStatRawL("ViewModelBodygroups")
|
|
local WorldModelBodygroups = self:GetStatRawL("WorldModelBodygroups")
|
|
|
|
if not self2.HasFilledBodygroupTables then
|
|
if self2.VMIV(self) then
|
|
for i = 0, #(self2.OwnerViewModel:GetBodyGroups() or ViewModelBodygroups) do
|
|
ViewModelBodygroups[i] = ViewModelBodygroups[i] or 0
|
|
end
|
|
end
|
|
|
|
for i = 0, #(self:GetBodyGroups() or WorldModelBodygroups) do
|
|
WorldModelBodygroups[i] = WorldModelBodygroups[i] or 0
|
|
end
|
|
|
|
self2.HasFilledBodygroupTables = true
|
|
end
|
|
|
|
if self2.VMIV(self) then
|
|
self2.IterateBodygroups(self, self2.OwnerViewModel, "ViewModelBodygroups", TFA.LatestDataVersion)
|
|
end
|
|
|
|
self2.IterateBodygroups(self, self, "WorldModelBodygroups", TFA.LatestDataVersion)
|
|
end
|
|
|
|
function SWEP:CallAttFunc(funcName, ...)
|
|
for attName, sel in pairs(self.AttachmentCache or {}) do
|
|
if not sel then goto CONTINUE end
|
|
|
|
local att = TFA.Attachments.Atts[attName]
|
|
if not att then goto CONTINUE end
|
|
|
|
local attFunc = att[funcName]
|
|
if attFunc and type(attFunc) == "function" then
|
|
local _ret1, _ret2, _ret3, _ret4, _ret5, _ret6, _ret7, _ret8, _ret9, _ret10 = attFunc(att, self, ...)
|
|
|
|
if _ret1 ~= nil then
|
|
return _ret1, _ret2, _ret3, _ret4, _ret5, _ret6, _ret7, _ret8, _ret9, _ret10
|
|
end
|
|
end
|
|
|
|
::CONTINUE::
|
|
end
|
|
|
|
return nil
|
|
end
|