Files
wnsrc/lua/tfa/modules/tfa_data.lua
lifestorm 94063e4369 Upload
2024-08-04 22:55:00 +03:00

580 lines
12 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.
-- This file is holding seamless translation of older versions of data to newer
-- versions of data
TFA.LatestDataVersion = 1
TFA.DataVersionMapping = {
[0] = {
{
old_path = "DrawCrosshairIS",
new_path = "DrawCrosshairIronSights",
},
{
old_path = "FiresUnderwater",
new_path = "Primary.FiresUnderwater",
},
{
old_path = "PenetrationMaterials",
new_path = "Primary.PenetrationMaterials",
},
{
old_path = "MaxPenetrationCounter",
new_path = "Primary.MaxSurfacePenetrationCount",
},
{
old_path = "MaxPenetration",
new_path = "Primary.MaxSurfacePenetrationCount",
},
{
old_path = "IronRecoilMultiplier",
new_path = "Primary.IronRecoilMultiplier",
},
{
old_path = "MoveSpeed",
new_path = "RegularMoveSpeedMultiplier",
},
{
old_path = "IronSightsMoveSpeed",
new_path = "AimingDownSightsSpeedMultiplier",
},
{
old_path = "Shotgun",
new_path = "LoopedReload",
},
{
old_path = "ShellTime",
new_path = "LoopedReloadInsertTime",
},
{
old_path = "CrouchPos",
new_path = "CrouchViewModelPosition",
},
{
old_path = "CrouchAng",
new_path = "CrouchViewModelAngle",
},
{
old_path = "data.ironsights",
new_path = "Secondary.IronSightsEnabled",
upgrade = function(value) return value == 1 end,
downgrade = function(value) return value and 1 or 0 end,
},
{
old_path = "Secondary.IronFOV",
new_path = "Secondary.OwnerFOV",
},
{
old_path = "IronViewModelFOV",
new_path = "Secondary.ViewModelFOV",
},
{
old_path = "DoProceduralReload",
new_path = "IsProceduralReloadBased",
},
{
old_path = "ProceduralReloadEnabled",
new_path = "IsProceduralReloadBased",
},
{
old_path = "Akimbo",
new_path = "IsAkimbo",
},
{
old_path = "AkimboHUD",
new_path = "EnableAkimboHUD",
},
{
old_path = "IronInSound",
new_path = "Secondary.IronSightsInSound",
},
{
old_path = "IronOutSound",
new_path = "Secondary.IronSightsOutSound",
},
{
old_path = "DisableChambering",
new_path = "Primary.DisableChambering",
},
{
old_path = "DisplayFalloff",
new_path = "Primary.DisplayFalloff",
},
{
old_path = "SpreadPattern",
new_path = "Primary.SpreadPattern",
},
{
old_path = "SpreadBiasYaw",
new_path = "Primary.SpreadBiasYaw",
},
{
old_path = "SpreadBiasPitch",
new_path = "Primary.SpreadBiasPitch",
},
{
old_path = "VMPos",
new_path = "ViewModelPosition",
},
{
old_path = "VMAng",
new_path = "ViewModelAngle",
},
{
old_path = "VMPos_Additive",
new_path = "AdditiveViewModelPosition",
},
{
old_path = "RunSightsPos",
new_path = "SprintViewModelPosition",
},
{
old_path = "RunSightsAng",
new_path = "SprintViewModelAngle",
},
{
old_path = "IronSightsPos",
new_path = "IronSightsPosition",
},
{
old_path = "IronSightsAng",
new_path = "IronSightsAngle",
},
{
old_path = "Bodygroups_V",
new_path = "ViewModelBodygroups",
},
{
old_path = "Bodygroups_W",
new_path = "WorldModelBodygroups",
},
{
old_path = "CenteredPos",
new_path = "CenteredViewModelPosition",
},
{
old_path = "CenteredAng",
new_path = "CenteredViewModelAngle",
},
{
old_path = "Offset",
new_path = "WorldModelOffset",
},
{
old_path = "ProceduralHolsterPos",
new_path = "ProceduralHolsterPosition",
},
{
old_path = "ProceduralHolsterAng",
new_path = "ProceduralHolsterAngle",
},
{
old_path = "VElements",
new_path = "ViewModelElements",
},
{
old_path = "WElements",
new_path = "WorldModelElements",
},
}
}
local function identity(...) return ... end
for version = 0, #TFA.DataVersionMapping do
for i, data in ipairs(TFA.DataVersionMapping[version]) do
if not isfunction(data.upgrade) then data.upgrade = identity end
if not isfunction(data.downgrade) then data.downgrade = identity end
end
end
TFA.PathParseCache = {}
TFA.PathParseCacheTR = {}
TFA.StatPathRemapCache = {}
TFA.PathParseCacheDirect = {}
TFA.PathParseChildren = {}
local PathParseCache = TFA.PathParseCache
local PathParseCacheTR = TFA.PathParseCacheTR
local PathParseCacheDirect = TFA.PathParseCacheDirect
local StatPathRemapCache = TFA.StatPathRemapCache
local PathParseChildren = TFA.PathParseChildren
local string_Explode = string.Explode
local ipairs = ipairs
local pairs = pairs
local string_sub = string.sub
local tonumber = tonumber
local table_Copy = table.Copy
local table_concat = table.concat
local istable = istable
local string_format = string.format
local function doDowngrade(path, migrations)
for i, data in ipairs(migrations) do
if data.new_path == path then
return data.old_path, data.upgrade
elseif path:StartWith(data.new_path) and path[#data.new_path + 1] == '.' then
return data.old_path .. path:sub(#data.new_path + 1), data.upgrade
end
end
return path
end
local function doUpgrade(path, migrations)
for i, data in ipairs(migrations) do
if data.old_path == path then
return data.new_path, data.downgrade
elseif path:StartWith(data.old_path) and path[#data.old_path + 1] == '.' then
return data.new_path .. path:sub(#data.old_path + 1), data.downgrade
end
end
return path
end
function TFA.RemapStatPath(path, path_version, structure_version)
local cache_path = path
if path_version == nil then path_version = 0 end
if structure_version == nil then structure_version = 0 end
-- version do not match
if path_version ~= structure_version then
cache_path = string_format("%d_%d_%s", path_version, structure_version, path)
end
local get_cache = StatPathRemapCache[cache_path]
if get_cache ~= nil then return get_cache end
if cache_path ~= path then
-- downgrade path
if path_version > structure_version then
for version = path_version, structure_version, -1 do
local mapping = TFA.DataVersionMapping[version]
if istable(mapping) then
path = doDowngrade(path, mapping)
end
end
else -- upgrade path
for version = path_version, structure_version do
local mapping = TFA.DataVersionMapping[version]
if istable(mapping) then
path = doUpgrade(path, mapping)
end
end
end
end
StatPathRemapCache[cache_path] = path
return StatPathRemapCache[cache_path]
end
function TFA.GetStatPathChildren(path, path_version, structure_version)
-- version do not match
if path_version ~= structure_version then
path = TFA.RemapStatPath(path, path_version, structure_version)
end
if not PathParseChildren[path] then
TFA.GetStatPath(path, path_version, structure_version)
end
return PathParseChildren[path].list
end
local function concat_to(tab, to)
local str = tab[1]
for i = 2, to do
str = str .. '.' .. tab[i]
end
return str
end
local function concat_from(tab, from)
local str = tab[from]
for i = from + 1, #tab do
str = str .. '.' .. tab[i]
end
return str
end
function TFA.GetStatPath(path, path_version, structure_version, no_translate)
local cache_path = path
if path_version == nil then path_version = 0 end
if structure_version == nil then structure_version = 0 end
-- version do not match
if path_version ~= structure_version then
cache_path = string_format("%d_%d_%s", path_version, structure_version, path)
end
local _PathParseCache = no_translate and PathParseCacheTR or PathParseCache
local get_cache = _PathParseCache[cache_path]
if get_cache ~= nil then return get_cache[1], get_cache[2], get_cache[3] end
local fn, fnGet
if cache_path ~= path then
-- downgrade
if path_version > structure_version then
for version = path_version, structure_version, -1 do
local mapping = TFA.DataVersionMapping[version]
if istable(mapping) then
path, fnGet = doDowngrade(path, mapping)
if fnGet and fnGet ~= identity then
if not fn then
fn = fnGet
else
local _fn = fn
function fn(...) return fnGet(_fn(...)) end
end
end
end
end
else -- upgrade
for version = path_version, structure_version do
local mapping = TFA.DataVersionMapping[version]
if istable(mapping) then
path, fnGet = doUpgrade(path, mapping)
if fnGet and fnGet ~= identity then
if not fn then
fn = fnGet
else
local _fn = fn
function fn(...) return fnGet(_fn(...)) end
end
end
end
end
end
end
get_cache = string_Explode(".", path, false)
do
local children = PathParseChildren[get_cache[1]]
if not children then
children = {
list = {get_cache[1]},
children = {}
}
PathParseChildren[get_cache[1]] = children
end
local childrens = {children}
for i = 2, #get_cache do
local obj = get_cache[i]
local path2 = concat_to(get_cache, i)
for i3 = 1, #childrens do
local list = childrens[i3].list
local hit = false
for i2 = 1, #list do
if list[i2] == path2 then
hit = true
break
end
end
if not hit then
table.insert(list, path2)
end
end
if not children.children[obj] then
children.children[obj] = {
list = {path2},
children = {}
}
end
if not PathParseChildren[path2] then
PathParseChildren[path2] = {
list = {path2},
children = {}
}
end
children = children.children[obj]
table.insert(childrens, children)
table.insert(childrens, PathParseChildren[path2])
end
end
if not no_translate then
if get_cache[1] == "Primary" then
get_cache[1] = "Primary_TFA"
elseif get_cache[1] == "Secondary" then
get_cache[1] = "Secondary_TFA"
end
end
for k, v in ipairs(get_cache) do
get_cache[k] = tonumber(v) or v
end
_PathParseCache[cache_path] = {get_cache, path, fn or identity}
return get_cache, path, fn or identity
end
function TFA.GetStatPathRaw(path)
local get_cache = PathParseCacheDirect[path]
if get_cache ~= nil then return get_cache end
local t_stbl = string_Explode(".", path, false)
for k, v in ipairs(t_stbl) do
t_stbl[k] = tonumber(v) or v
end
PathParseCacheDirect[path] = t_stbl
return t_stbl
end
local GetStatPathRaw = TFA.GetStatPathRaw
do
local function get(self, path)
local value = self[path[1]]
for i = 2, #path do
if not istable(value) then return end
value = value[path[i]]
end
return value
end
local function set(self, path, val)
if #path == 1 then
if self[path[1]] == nil then
self[path[1]] = val
end
return
end
local value = self[path[1]]
if value == nil then
self[path[1]] = {}
value = self[path[1]]
end
for i = 2, #path - 1 do
if not istable(value) then return end
if value[path[i]] == nil then value[path[i]] = {} end
value = value[path[i]]
end
if istable(value) and value[path[#path]] == nil then
value[path[#path]] = val
elseif not istable(value) then
print('[TFA Base] unable to fill gap for older version in meta structure of ' .. table_concat(path, '.'))
end
end
function TFA.FillMissingMetaValues(SWEP)
for version = TFA.LatestDataVersion, 0, -1 do
local mapping = TFA.DataVersionMapping[version]
if istable(mapping) then
for i, data in ipairs(mapping) do
local getVal = get(SWEP, GetStatPathRaw(data.new_path))
if getVal ~= nil then
set(SWEP, GetStatPathRaw(data.old_path), data.downgrade(getVal))
end
end
end
end
end
end