200 lines
5.2 KiB
Lua
200 lines
5.2 KiB
Lua
-- Path of Building
|
|
--
|
|
-- Module: Mod Tools
|
|
-- Various functions for dealing with modifier lists and databases
|
|
--
|
|
|
|
local t_insert = table.insert
|
|
local m_floor = math.floor
|
|
|
|
modLib = { }
|
|
|
|
modLib.parseMod = LoadModule("Modules/ModParser")
|
|
|
|
-- Break modifier name into namespace and mod name
|
|
local spaceLookup = { }
|
|
function modLib.getSpaceName(modName)
|
|
if not spaceLookup[modName] then
|
|
local space, mod = modName:match("^([^_]+)_(.+)$")
|
|
if not space then
|
|
space = "global"
|
|
mod = modName
|
|
end
|
|
spaceLookup[modName] = { space, mod }
|
|
return space, mod
|
|
end
|
|
return unpack(spaceLookup[modName])
|
|
end
|
|
|
|
-- Extract condition name from modifier name
|
|
local condLookup = { }
|
|
function modLib.getCondName(modName)
|
|
if not condLookup[modName] then
|
|
local isNot, condName, mod = modName:match("^(n?o?t?)(%w+)_(.+)$")
|
|
isNot = (isNot == "not")
|
|
condLookup[modName] = { isNot, condName, mod }
|
|
return isNot, condName, mod
|
|
end
|
|
return unpack(condLookup[modName])
|
|
end
|
|
|
|
-- Magic table to check modifier type:
|
|
-- "MORE" = multiplicative (contains 'More' in the modifier name)
|
|
-- "INC" = additive (contains 'Inc' in the modifier name)
|
|
modLib.getModType = { }
|
|
modLib.getModType.__index = function(t, modName)
|
|
local val
|
|
if modName:match("More$") then
|
|
val = "MORE"
|
|
elseif modName:match("Inc$") then
|
|
val = "INC"
|
|
else
|
|
val = "BASE"
|
|
end
|
|
t[modName] = val
|
|
return val
|
|
end
|
|
setmetatable(modLib.getModType, modLib.getModType)
|
|
|
|
-- Merge modifier with existing mod list, respecting additivity/multiplicativity
|
|
function modLib.listMerge(modList, modName, modVal)
|
|
if modList[modName] then
|
|
if type(modVal) == "boolean" then
|
|
modList[modName] = modList[modName] or modVal
|
|
elseif type(modVal) == "function" then
|
|
local orig = modList[modName]
|
|
modList[modName] = function(...) orig(...) modVal(...) end
|
|
elseif modLib.getModType[modName] == "MORE" then
|
|
modList[modName] = modList[modName] * modVal
|
|
else
|
|
modList[modName] = modList[modName] + modVal
|
|
end
|
|
else
|
|
modList[modName] = modVal
|
|
end
|
|
end
|
|
|
|
-- Scale and merge modifier with existing mod list
|
|
function modLib.listScaleMerge(modList, k, v, scale)
|
|
local type = modLib.getModType[k]
|
|
if type == "MORE" then
|
|
modLib.listMerge(modList, k, 1 + m_floor((v - 1) * scale * 100) / 100)
|
|
elseif type == "INC" then
|
|
modLib.listMerge(modList, k, m_floor(v * scale))
|
|
else
|
|
modLib.listMerge(modList, k, v * scale)
|
|
end
|
|
end
|
|
|
|
|
|
-- Unmerge modifier from existing mod list, respecting additivity/multiplicativity
|
|
function modLib.listUnmerge(modList, modName, modVal)
|
|
if type(modVal) == "boolean" then
|
|
if modVal == true then
|
|
modList[modName] = false
|
|
end
|
|
elseif type(modVal) == "string" then
|
|
modList[modName] = nil
|
|
elseif modLib.getModType[modName] == "MORE" then
|
|
if modVal == 0 then
|
|
modList[modName] = 1
|
|
else
|
|
modList[modName] = (modList[modName] or 1) / modVal
|
|
end
|
|
else
|
|
modList[modName] = (modList[modName] or 0) - modVal
|
|
end
|
|
end
|
|
|
|
-- Merge modifier with mod database
|
|
function modLib.dbMerge(modDB, spaceName, modName, modVal)
|
|
if not spaceName then
|
|
spaceName, modName = modLib.getSpaceName(modName)
|
|
elseif spaceName == "" then
|
|
spaceName = "global"
|
|
end
|
|
if not modDB[spaceName] then
|
|
modDB[spaceName] = { }
|
|
end
|
|
modLib.listMerge(modDB[spaceName], modName, modVal)
|
|
end
|
|
|
|
-- Scale and merge modifier with mod database
|
|
function modLib.dbScaleMerge(modDB, spaceName, modName, modVal, scale)
|
|
if not spaceName then
|
|
spaceName, modName = modLib.getSpaceName(modName)
|
|
elseif spaceName == "" then
|
|
spaceName = "global"
|
|
end
|
|
if not modDB[spaceName] then
|
|
modDB[spaceName] = { }
|
|
end
|
|
modLib.listScaleMerge(modDB[spaceName], modName, modVal, scale)
|
|
end
|
|
|
|
-- Unmerge modifier from mod database
|
|
function modLib.dbUnmerge(modDB, spaceName, modName, modVal)
|
|
if not spaceName then
|
|
spaceName, modName = modLib.getSpaceName(modName)
|
|
elseif spaceName == "" then
|
|
spaceName = "global"
|
|
end
|
|
if not modDB[spaceName] then
|
|
modDB[spaceName] = { }
|
|
end
|
|
modLib.listUnmerge(modDB[spaceName], modName, modVal)
|
|
end
|
|
|
|
-- Merge modifier list with mod database
|
|
function modLib.dbMergeList(modDB, modList)
|
|
for k, modVal in pairs(modList) do
|
|
local spaceName, modName = modLib.getSpaceName(k)
|
|
if not modDB[spaceName] then
|
|
modDB[spaceName] = { }
|
|
end
|
|
modLib.listMerge(modDB[spaceName], modName, modVal)
|
|
end
|
|
end
|
|
|
|
-- Unmerge modifier list from mod database
|
|
function modLib.dbUnmergeList(modDB, modList)
|
|
for k, modVal in pairs(modList) do
|
|
local spaceName, modName = modLib.getSpaceName(k)
|
|
if not modDB[spaceName] then
|
|
modDB[spaceName] = { }
|
|
end
|
|
modLib.listUnmerge(modDB[spaceName], modName, modVal)
|
|
end
|
|
end
|
|
|
|
-- Print modifier list to the console
|
|
function modLib.listPrint(modList, tab)
|
|
local names = { }
|
|
for k in pairs(modList) do
|
|
if type(k) == "string" then
|
|
t_insert(names, k)
|
|
end
|
|
end
|
|
table.sort(names)
|
|
for _, name in pairs(names) do
|
|
ConPrintf("%s%s = %s", string.rep("\t", tab or 0), name, modList[name])
|
|
end
|
|
end
|
|
|
|
-- Print modifier database to the console
|
|
function modLib.dbPrint(modDB)
|
|
local spaceNames = { }
|
|
for k in pairs(modDB) do
|
|
t_insert(spaceNames, k)
|
|
end
|
|
table.sort(spaceNames)
|
|
for _, spaceName in pairs(spaceNames) do
|
|
if next(modDB[spaceName]) then
|
|
ConPrintf("%s = {", spaceName)
|
|
modLib.listPrint(modDB[spaceName], 1)
|
|
ConPrintf("},")
|
|
else
|
|
ConPrintf("%s = { },", spaceName)
|
|
end
|
|
end
|
|
end |