new formula: worst case scenario, picks worst

also lots of refactoring for more dynamic MCM
This commit is contained in:
Lilian Jónsdóttir 2021-08-11 00:31:02 -07:00
parent a40d07df18
commit 977cf12b6f
4 changed files with 149 additions and 52 deletions

View file

@ -2,12 +2,62 @@ local this = {}
this.modName = "A Sinking Feeling"
this.author = "Celediel"
this.modInfo = "No longer can you swim in heavy plate; now your armour, equipment, or carried items drag you down while swimming.\n" ..
this.modInfo = "No longer can you swim in heavy plate; now your armour, equipment, or carried items drag you down while swimming.\n\n" ..
"Options exist for formulas based on equipped armour weight class, total equipment weight or encumbrance percentage.\n\n" ..
"What is dead may never die."
this.version = "1.0.4"
this.configString = string.gsub(this.modName, "%s+", "")
this.modes = {equippedArmour = 0, allEquipment = 1, encumbrancePercentage = 2, allEquipmentNecroEdit = 3}
this.modes = {
equippedArmour = {
value = 0,
description = "Actors are pulled down by their combined armour class (Light = 1, Medium = 2, Heavy = 3) multiplied by a tenth of " ..
"the down-pull multiplier. Default of 100 makes it impossible to surface in all heavy armour for all but the most Athletic.",
},
allEquipment = {
value = 1,
description = "Actors are pulled down by double the weight of all equipped gear multiplied by a hundredth of the down-pull multiplier.",
},
encumbrancePercentage = {
value = 2,
description = "Actors are pulled down by their encumbrance percentage multiplied by triple the down-pull multiplier.",
},
allEquipmentNecroEdit = {
value = 3,
description = "Actors are pulled down by their encumbrance percentage multiplied by triple the down-pull multiplier, " ..
"except any weight above 135 only counts 10%. Lessens the gap between the lightest and heaviest heavy armours.",
},
worstCaseScenario = {
value = 4,
description = "Calculates results from all formulas, and uses the highest value.",
}
}
this.log = function(...) mwse.log("[%s] %s", this.modName, string.format(...)) end
this.camelCaseToWords = function(str)
local function spaceBefore(word)
return " " .. word
end
local function titleCase(first, rest)
return first:upper() .. rest:lower()
end
local words = str:gsub("%u", spaceBefore)
return words:gsub("(%a)([%w_']*)", titleCase)
end
-- picks the key of the largest value out of a key:whatever, value:number table
this.keyOfLargestValue = function(t)
local picked
local largest = 0
for key, value in pairs(t) do
if value > largest then
largest = value
picked = key
end
end
return picked
end
return this

View file

@ -1,6 +1,6 @@
local common = require("celediel.ASinkingFeeling.common")
local defaultConfig = {enabled = true, debug = false, playerOnly = false, downPullMultiplier = 100, mode = common.modes.equippedArmour}
local defaultConfig = {enabled = true, debug = false, playerOnly = false, downPullMultiplier = 100, mode = common.modes.equippedArmour.value}
local config = mwse.loadConfig(common.configString, defaultConfig)
return config

View file

@ -32,6 +32,66 @@ local function getTotalEquipmentWeight(actor)
return weight
end
-- Formula functions
local formulas = {}
formulas.equippedArmour = function(actor, ref)
local armourClass = getTotalArmourClass(actor)
local downPull = (config.downPullMultiplier / 10) * armourClass
local debugStr = string.format("Pulling %s down by %s using equipped armour mode (%s total armour class)",
ref.id, downPull, armourClass)
return downPull, debugStr
end
formulas.allEquipment = function(actor, ref)
local totalWeight = getTotalEquipmentWeight(actor)
-- doubling this keeps this formula somewhat uniform with armour class @ multiplier 100
local downPull = ((config.downPullMultiplier / 100) * totalWeight) * 2
local debugStr = string.format("Pulling %s down by %s using equipment weight mode (%s total equipment weight)",
ref.id, downPull, totalWeight)
return downPull, debugStr
end
formulas.allEquipmentNecroEdit = function(actor, ref)
local totalWeight = getTotalEquipmentWeight(actor)
-- Thanks Necrolesian for this formula
-- https://forums.nexusmods.com/index.php?/topic/10349253-a-sinking-feeling/page-2#entry97870268
local term1 = ((config.downPullMultiplier / 100) * totalWeight) * 2
local term2 = ((config.downPullMultiplier / 100) * (totalWeight - 135) * 0.2) + 270
local downPull = math.min(term1, term2)
local debugStr = string.format("Pulling %s down by %s (instead of %s) using equipment weight mode (necro edit) (%s total equipment weight)",
ref.id, downPull, math.max(term1, term2), totalWeight)
return downPull, debugStr
end
formulas.encumbrancePercentage = function(mobile, ref)
local encumbrance = mobile.encumbrance
-- tripling this keeps this formula somewhat uniform with armour class @ multiplier 100
local downPull = (config.downPullMultiplier * encumbrance.normalized) * 3
local debugStr = string.format("Pulling %s down by %s using encumbrance mode (%s/%s = %s encumbrance)",
ref.id, downPull, encumbrance.current, encumbrance.base, encumbrance.normalized)
return downPull, debugStr
end
formulas.worstCaseScenario = function(actor, mobile, ref)
local downPull = 0
local results = {}
-- todo: maybe loop over formulas to calculate each instead of this
-- different formulas needing different actor/mobile might make it too unwieldy though
results.equippedArmour = formulas.equippedArmour(actor, ref)
results.allEquipment = formulas.allEquipment(actor, ref)
results.allEquipmentNecroEdit = formulas.allEquipmentNecroEdit(actor, ref)
results.encumbrancePercentage = formulas.encumbrancePercentage(mobile, ref)
local largest = common.keyOfLargestValue(results)
downPull = results[largest]
local debugStr = string.format("Pulling %s down by %s using worst mode:%s", ref.id, downPull, common.camelCaseToWords(largest))
return downPull, debugStr
end
-- Event functions
local function sinkInWater(e)
-- shortcut refs
@ -54,35 +114,16 @@ local function sinkInWater(e)
if not config.enabled then
downPull = 0
-- calculate the down-pull with the configured formula
elseif config.mode == common.modes.equippedArmour then
local armourClass = getTotalArmourClass(actor)
downPull = (config.downPullMultiplier / 10) * armourClass
debugStr = string.format("Pulling %s down by %s using equipped armour mode (%s total armour class)",
ref.id, downPull, armourClass)
elseif config.mode == common.modes.allEquipment then
local totalWeight = getTotalEquipmentWeight(actor)
-- doubling this keeps this formula somewhat uniform with armour class @ multiplier 100
downPull = ((config.downPullMultiplier / 100) * totalWeight) * 2
debugStr = string.format("Pulling %s down by %s using equipment weight mode (%s total equipment weight)",
ref.id, downPull, totalWeight)
elseif config.mode == common.modes.allEquipmentNecroEdit then
local totalWeight = getTotalEquipmentWeight(actor)
-- Thanks Necrolesian for this formula
-- https://forums.nexusmods.com/index.php?/topic/10349253-a-sinking-feeling/page-2#entry97870268
local term1 = ((config.downPullMultiplier / 100) * totalWeight) * 2
local term2 = ((config.downPullMultiplier / 100) * (totalWeight - 135) * 0.2) + 270
downPull = math.min(term1, term2)
debugStr = string.format("Pulling %s down by %s (instead of %s) using equipment weight mode (necro edit) (%s total equipment weight)",
ref.id, downPull, math.max(term1, term2), totalWeight)
elseif config.mode == common.modes.encumbrancePercentage then
local encumbrance = mobile.encumbrance
-- tripling this keeps this formula somewhat uniform with armour class @ multiplier 100
downPull = (config.downPullMultiplier * encumbrance.normalized) * 3
debugStr = string.format("Pulling %s down by %s using encumbrance mode (%s/%s = %s encumbrance)",
ref.id, downPull, encumbrance.current, encumbrance.base, encumbrance.normalized)
elseif config.mode == common.modes.equippedArmour.value then
downPull, debugStr = formulas.equippedArmour(actor, ref)
elseif config.mode == common.modes.allEquipment.value then
downPull, debugStr = formulas.allEquipment(actor, ref)
elseif config.mode == common.modes.allEquipmentNecroEdit.value then
downPull, debugStr = formulas.allEquipmentNecroEdit(actor, ref)
elseif config.mode == common.modes.encumbrancePercentage.value then
downPull, debugStr = formulas.encumbrancePercentage(mobile, ref)
elseif config.mode == common.modes.worstCaseScenario.value then
downPull, debugStr = formulas.worstCaseScenario(actor, mobile, ref)
end
-- reset if levitating

View file

@ -1,26 +1,36 @@
local common = require("celediel.ASinkingFeeling.common")
local config = require("celediel.ASinkingFeeling.config")
local function camelCaseToWords(str)
local function spaceBefore(word)
return " " .. word
end
local function titleCase(first, rest)
return first:upper() .. rest:lower()
end
local words = str:gsub("%u", spaceBefore)
return words:gsub("(%a)([%w_']*)", titleCase)
end
local function createTableVar(id) return mwse.mcm.createTableVariable {id = id, table = config} end
local function createDescriptions()
local description = "Formula used to calculate down-pull amount.\n\nOptions are: "
local options = ""
-- list all current modes
for mode, _ in pairs(common.modes) do
options = options .. common.camelCaseToWords(mode) .. ", "
end
-- strip off ending ", "
options = options:sub(1, string.len(options) - 2)
-- add modes to description
description = description .. options
-- add descriptions to description
for mode, t in pairs(common.modes) do
description = description .. "\n\n" .. common.camelCaseToWords(mode) .. ": " .. t.description
end
return description
end
local function createOptions()
local options = {}
for mode, i in pairs(common.modes) do
options[#options+1] = {label = camelCaseToWords(mode), value = i}
for mode, t in pairs(common.modes) do
options[#options+1] = {label = common.camelCaseToWords(mode), value = t.value}
end
return options
@ -50,11 +60,7 @@ category:createYesNoButton({
category:createDropdown({
label = "Down-pull formula",
description = "Formula used to calculate down-pull amount.\n\nOptions are: Equipped Armour, Equipment Weight, Encumbrance\n\n" ..
"Equipped Armour: Actors are pulled down by their combined armour class (Light = 1, Medium = 2, Heavy = 3), " ..
"multiplied by a tenth of the down-pull multiplier. Default of 100 makes it impossible to surface in all heavy armour for all but the most Athletic.\n\n" ..
"Equipment weight: Actors are pulled down by double the weight of all equipped gear multiplied by a hundredth of the down-pull multiplier.\n\n" ..
"Encumbrance: Actors are pulled down by their encumbrance percentage multiplied by triple the down-pull multiplier.\n\n",
description = createDescriptions(),
options = createOptions(),
variable = createTableVar("mode")
})