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.modName = "A Sinking Feeling"
this.author = "Celediel" 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" .. "Options exist for formulas based on equipped armour weight class, total equipment weight or encumbrance percentage.\n\n" ..
"What is dead may never die." "What is dead may never die."
this.version = "1.0.4" this.version = "1.0.4"
this.configString = string.gsub(this.modName, "%s+", "") 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.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 return this

View file

@ -1,6 +1,6 @@
local common = require("celediel.ASinkingFeeling.common") 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) local config = mwse.loadConfig(common.configString, defaultConfig)
return config return config

View file

@ -32,6 +32,66 @@ local function getTotalEquipmentWeight(actor)
return weight return weight
end 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 -- Event functions
local function sinkInWater(e) local function sinkInWater(e)
-- shortcut refs -- shortcut refs
@ -54,35 +114,16 @@ local function sinkInWater(e)
if not config.enabled then if not config.enabled then
downPull = 0 downPull = 0
-- calculate the down-pull with the configured formula -- calculate the down-pull with the configured formula
elseif config.mode == common.modes.equippedArmour then elseif config.mode == common.modes.equippedArmour.value then
local armourClass = getTotalArmourClass(actor) downPull, debugStr = formulas.equippedArmour(actor, ref)
downPull = (config.downPullMultiplier / 10) * armourClass elseif config.mode == common.modes.allEquipment.value then
debugStr = string.format("Pulling %s down by %s using equipped armour mode (%s total armour class)", downPull, debugStr = formulas.allEquipment(actor, ref)
ref.id, downPull, armourClass) elseif config.mode == common.modes.allEquipmentNecroEdit.value then
downPull, debugStr = formulas.allEquipmentNecroEdit(actor, ref)
elseif config.mode == common.modes.allEquipment then elseif config.mode == common.modes.encumbrancePercentage.value then
local totalWeight = getTotalEquipmentWeight(actor) downPull, debugStr = formulas.encumbrancePercentage(mobile, ref)
-- doubling this keeps this formula somewhat uniform with armour class @ multiplier 100 elseif config.mode == common.modes.worstCaseScenario.value then
downPull = ((config.downPullMultiplier / 100) * totalWeight) * 2 downPull, debugStr = formulas.worstCaseScenario(actor, mobile, ref)
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)
end end
-- reset if levitating -- reset if levitating

View file

@ -1,26 +1,36 @@
local common = require("celediel.ASinkingFeeling.common") local common = require("celediel.ASinkingFeeling.common")
local config = require("celediel.ASinkingFeeling.config") 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 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 function createOptions()
local options = {} local options = {}
for mode, i in pairs(common.modes) do for mode, t in pairs(common.modes) do
options[#options+1] = {label = camelCaseToWords(mode), value = i} options[#options+1] = {label = common.camelCaseToWords(mode), value = t.value}
end end
return options return options
@ -50,11 +60,7 @@ category:createYesNoButton({
category:createDropdown({ category:createDropdown({
label = "Down-pull formula", label = "Down-pull formula",
description = "Formula used to calculate down-pull amount.\n\nOptions are: Equipped Armour, Equipment Weight, Encumbrance\n\n" .. description = createDescriptions(),
"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",
options = createOptions(), options = createOptions(),
variable = createTableVar("mode") variable = createTableVar("mode")
}) })