Module:Constants: Difference between revisions
From Melvor Idle
Falterfire (talk | contribs) (Tweaked modifier text for a few things to include multipliers properly) |
No edit summary |
||
(146 intermediate revisions by 7 users not shown) | |||
Line 1: | Line 1: | ||
local p = {} | local p = {} | ||
local | local Shared = require('Module:Shared') | ||
local | local GameData = require('Module:GameData') | ||
local Modifiers = require('Module:Modifiers') | |||
function p.getTriangleAttribute(attribute, attackerStyle, targetStyle, modeName) | |||
if type(attribute) ~= 'string' then | |||
error("Parameter 'attribute' must be a string", 2) | |||
elseif type(attackerStyle) ~= 'string' then | |||
error("Parameter 'attackerStyle' must be a string", 2) | |||
elseif type(targetStyle) ~= 'string' then | |||
error("Parameter 'targetStyle' must be a string", 2) | |||
elseif type(modeName) ~= 'string' then | |||
error("Parameter 'modeName' must be a string", 2) | |||
end | |||
local mode = GameData.getEntityByName('gamemodes', modeName) | |||
if mode == nil then | |||
error("Invalid gamemode '" .. modeName .. "'", 2) | |||
end | |||
local attStyle, targStyle = string.lower(attackerStyle), string.lower(targetStyle) | |||
local validStyles = { 'magic', 'melee', 'ranged' } | |||
if not Shared.contains(validStyles, string.lower(attStyle)) then | |||
error("Invalid value for parameter 'attackerStyle'", 2) | |||
elseif not Shared.contains(validStyles, string.lower(targStyle)) then | |||
error("Invalid value for parameter 'targetStyle'", 2) | |||
end | |||
local combatTriangle = GameData.getEntityByID('combatTriangles', mode.combatTriangle) | |||
if combatTriangle == nil then | |||
error("No such combat triangle: " .. mode.combatTriangle) | |||
end | |||
local attrData = combatTriangle[attribute] | |||
if attrData == nil then | |||
error("No such attribute: " .. attribute) | |||
else | |||
return attrData[attStyle][targStyle] | |||
end | |||
end | |||
function p.getTriangleDamageModifier(attackerStyle, targetStyle, mode) | |||
return p.getTriangleAttribute('damageModifier', attackerStyle, targetStyle, mode) | |||
end | |||
--Syntax is like p.getTriangleDRModifier('Melee', 'Ranged', 'Normal') | |||
--Returns a multiplier that can be multiplied with base DR to get the post-Triangle result | |||
function p.getTriangleDRModifier(attackerStyle, targetStyle, mode) | |||
return p.getTriangleAttribute('reductionModifier', attackerStyle, targetStyle, mode) | |||
end | |||
function p.getDifficultyString(difficulty) | |||
return GameData.rawData.combatAreaDifficulties[difficulty + 1] | |||
end | |||
function p.getSkillName(skillID) | function p.getSkillName(skillID) | ||
local skill = GameData.getSkillData(skillID) | |||
if skill ~= nil then | |||
return skill.name | |||
end | |||
end | |||
function p.getSkillID(skillName) | |||
for i, skillData in ipairs(GameData.rawData.skillData) do | |||
if skillData.data.name == skillName then | |||
return skillData.skillID | |||
end | |||
end | |||
end | |||
function p.getSkillIDText(frame) | |||
local skillName = frame.args ~= nil and frame.args[1] or frame[1] | |||
local id = p.getSkillID(skillName) | |||
if id == nil or id == '' then | |||
return "Unknown" | |||
else | |||
return id | |||
end | |||
end | end | ||
function p.getEquipmentSlotName(id) | function p.getEquipmentSlotName(id) | ||
local slotData = GameData.getEntityByID('equipmentSlots', id) | |||
if slotData ~= nil then | |||
return slotData.emptyName | |||
end | |||
end | |||
function p.getEquipmentSlotID(name) | |||
local slotData = GameData.getEntityByProperty('equipmentSlots', 'emptyName', name) | |||
if slotData ~= nil then | |||
return slotData.id | |||
end | |||
end | |||
function p.getCombatStyleName(styleNum) | |||
if type(styleNum) == 'number' then | |||
local styleName = GameData.rawData.attackTypes[styleNum] | |||
if styleName ~= nil then | |||
return Shared.titleCase(styleName) | |||
end | |||
elseif type(styleNum) == 'string' and type(GameData.rawData.attackTypes[string.lower(styleNum)]) == 'number' then | |||
return Shared.titleCase(styleNum) | |||
end | |||
return Shared.printError('Invalid combat style') | |||
end | |||
--- Slayer functions | |||
-- | |||
function p.getSlayerTierByID(tierID) | |||
if type(tierID) ~= 'number' then | |||
return nil | |||
else | |||
return GameData.rawData.slayerTaskCategories[tierID + 1] | |||
end | |||
end | |||
function p.getSlayerTier(name) | |||
return GameData.getEntityByProperty('slayerTiers', 'display', name) | |||
end | |||
function p.getSlayerTierByLevel(level) | |||
if type(level) ~= 'number' or level < 1 then | |||
return Shared.printError('Invalid Slayer level') | |||
end | |||
for i, tier in ipairs(GameData.rawData.slayerTaskCategories) do | |||
if tier.type == 'CombatLevel' and tier.minLevel <= level and (tier.maxLevel == nil or tier.maxLevel >= level) then | |||
return tier | |||
end | |||
end | |||
end | |||
-- | |||
-- the following functions just return subsets of the slayer functions above | |||
-- | |||
function p.getSlayerTierName(tierID) | |||
if type(tierID) == 'number' then | |||
local tier = p.getSlayerTierByID(tierID) | |||
if tier ~= nil then | |||
return tier.display | |||
end | |||
end | |||
return Shared.printError('Invalid Slayer tier') | |||
end | |||
function p.getSlayerTierNameByLevel(lvl) | |||
local tier = p.getSlayerTierByLevel(lvl) | |||
if type(tier) == 'table' then | |||
return tier.display | |||
else | |||
return Shared.printError('Invalid Slayer tier') | |||
end | |||
end | end | ||
-- | |||
--- End of slayer functions | |||
--Turns a modifier name like 'increasedHPRegenFlat' into several pieces of data: | |||
--Base Name, Description, IsNegative, and modifyValue | |||
--ex. "HPRegenFlat", "+${value} Flat Hitpoints Regeneration", false, "multiplyByNumberMultiplier" | |||
function p.getModifierDetails(modifierName) | |||
-- Unsupported | |||
error('Function is no longer supported', 2) | |||
--[==[ | |||
local baseName = modifierName | |||
local modifier = GameData.rawData.modifierData[modifierName] | |||
if modifier == nil then | |||
return nil | |||
end | |||
if Shared.startsWith(modifierName, "increased") or Shared.startsWith(modifierName, "decreased") then | |||
baseName = string.sub(modifierName, 10) | |||
end | |||
return baseName, modifier.description, modifier.isNegative, modifier.modifyValue | |||
--]==] | |||
end | |||
function p._getModifierText(modifier, value, doColor) | |||
return Modifiers.getModifierText(modifier, value, doColor) | |||
end | |||
function p.getModifierText(frame) | |||
local modifier = frame.args ~= nil and frame.args[1] or frame[1] | |||
local value = frame.args ~= nil and frame.args[2] or frame[2] | |||
local skill = frame.args ~= nil and frame.args.skill or frame.skill | |||
local doColor = frame.args ~= nil and frame.args[3] or frame[3] | |||
if doColor ~= nil then | |||
doColor = string.upper(doColor) ~= 'FALSE' | |||
end | |||
if skill ~= nil and skill ~= '' then | |||
value = { { ["skillID"] = p.getSkillID(skill), ["value"] = value } } | |||
end | |||
return p._getModifierText(modifier, value, doColor) | |||
end | |||
function p.getModifiersText(modifiers, doColor, inline, maxVisible) | |||
return Modifiers.getModifiersText(modifiers, doColor, inline, maxVisible) | |||
end | |||
function p.getModifierSkills(modifiers) | |||
return Modifiers.getModifierSkills(modifiers) | |||
end | |||
-- Returns a modifiers table indicating modifiersNew less modifiersOld | |||
-- The returned table can be passed to getModifiersText to obtain the | |||
-- result in a human readable format | |||
function p.getModifiersDifference(modifiersOld, modifiersNew) | |||
local modHasPrefix = {} | |||
local modDiff, modDiffBase = {}, {} | |||
local allMods = { | |||
{ ["mods"] = (modifiersNew or {}), ["mult"] = 1 }, | |||
{ ["mods"] = (modifiersOld or {}), ["mult"] = -1 } | |||
} | |||
-- Generate modifiers table containing only variances | |||
-- Create modDiffBase with mod base names (less 'increased'/'decreased' prefixes), | |||
for i, modDef in ipairs(allMods) do | |||
for modName, value in pairs(modDef.mods) do | |||
local modBaseName, modIsIncrease = modName, true | |||
if Shared.startsWith(modName, "increased") or Shared.startsWith(modName, "decreased") then | |||
modBaseName = string.sub(modName, 10) | |||
modIsIncrease = Shared.startsWith(modName, "increased") | |||
modHasPrefix[modBaseName] = true | |||
end | |||
local modMult = (modIsIncrease and 1 or -1) * modDef.mult | |||
if type(value) == 'table' then | |||
-- Skill specific modifier | |||
if modDiffBase[modBaseName] == nil then | |||
modDiffBase[modBaseName] = {} | |||
end | |||
for j, subVal in ipairs(value) do | |||
if type(subVal) == 'table' and subVal.skillID ~= nil then | |||
modDiffBase[modBaseName][subVal.skillID] = (modDiffBase[modBaseName][subVal.skillID] or 0) + subVal.value * modMult | |||
end | |||
end | |||
else | |||
modDiffBase[modBaseName] = (modDiffBase[modBaseName] or 0) + value * modMult | |||
end | |||
end | |||
end | |||
-- Transform modDiffBase into modDiff with the appropriate mod name within the return value | |||
for modBaseName, value in pairs(modDiffBase) do | |||
if type(value) == 'table' then | |||
-- Skill specific modifier | |||
for skillID, subVal in pairs(value) do | |||
if subVal ~= 0 then | |||
local modName = nil | |||
if modHasPrefix[modBaseName] then | |||
modName = (subVal < 0 and 'decreased' or 'increased') .. modBaseName | |||
else | |||
modName = modBaseName | |||
end | |||
if modDiff[modName] == nil then | |||
modDiff[modName] = {} | |||
end | |||
table.insert(modDiff[modName], { ["skillID"] = skillID, ["value"] = math.abs(subVal) }) | |||
end | |||
end | |||
elseif value ~= 0 then | |||
local modName = nil | |||
if modHasPrefix[modBaseName] then | |||
modName = (value < 0 and 'decreased' or 'increased') .. modBaseName | |||
else | |||
modName = modBaseName | |||
end | |||
modDiff[modName] = (modDiff[modName] or 0) + math.abs(value) | |||
if GameData.rawData.modifierData[modName] == nil then | |||
modDiff[modName] = nil | |||
end | |||
end | |||
end | |||
return modDiff | |||
end | |||
-- From game version 1.1 onwards, some entities have custom descriptions, while | |||
-- many are generated based on the modifiers associated to that entity. This | |||
-- function handles that logic given a custom description (may be nil) and | |||
-- a modifiers object | |||
function p.getDescription(customDescription, modifiers) | |||
if customDescription ~= nil then | |||
return customDescription | |||
else | |||
return p.getModifiersText(modifiers, false) | |||
end | |||
end | end | ||
return p | return p |
Latest revision as of 22:37, 22 June 2024
Documentation for this module may be created at Module:Constants/doc
local p = {}
local Shared = require('Module:Shared')
local GameData = require('Module:GameData')
local Modifiers = require('Module:Modifiers')
function p.getTriangleAttribute(attribute, attackerStyle, targetStyle, modeName)
if type(attribute) ~= 'string' then
error("Parameter 'attribute' must be a string", 2)
elseif type(attackerStyle) ~= 'string' then
error("Parameter 'attackerStyle' must be a string", 2)
elseif type(targetStyle) ~= 'string' then
error("Parameter 'targetStyle' must be a string", 2)
elseif type(modeName) ~= 'string' then
error("Parameter 'modeName' must be a string", 2)
end
local mode = GameData.getEntityByName('gamemodes', modeName)
if mode == nil then
error("Invalid gamemode '" .. modeName .. "'", 2)
end
local attStyle, targStyle = string.lower(attackerStyle), string.lower(targetStyle)
local validStyles = { 'magic', 'melee', 'ranged' }
if not Shared.contains(validStyles, string.lower(attStyle)) then
error("Invalid value for parameter 'attackerStyle'", 2)
elseif not Shared.contains(validStyles, string.lower(targStyle)) then
error("Invalid value for parameter 'targetStyle'", 2)
end
local combatTriangle = GameData.getEntityByID('combatTriangles', mode.combatTriangle)
if combatTriangle == nil then
error("No such combat triangle: " .. mode.combatTriangle)
end
local attrData = combatTriangle[attribute]
if attrData == nil then
error("No such attribute: " .. attribute)
else
return attrData[attStyle][targStyle]
end
end
function p.getTriangleDamageModifier(attackerStyle, targetStyle, mode)
return p.getTriangleAttribute('damageModifier', attackerStyle, targetStyle, mode)
end
--Syntax is like p.getTriangleDRModifier('Melee', 'Ranged', 'Normal')
--Returns a multiplier that can be multiplied with base DR to get the post-Triangle result
function p.getTriangleDRModifier(attackerStyle, targetStyle, mode)
return p.getTriangleAttribute('reductionModifier', attackerStyle, targetStyle, mode)
end
function p.getDifficultyString(difficulty)
return GameData.rawData.combatAreaDifficulties[difficulty + 1]
end
function p.getSkillName(skillID)
local skill = GameData.getSkillData(skillID)
if skill ~= nil then
return skill.name
end
end
function p.getSkillID(skillName)
for i, skillData in ipairs(GameData.rawData.skillData) do
if skillData.data.name == skillName then
return skillData.skillID
end
end
end
function p.getSkillIDText(frame)
local skillName = frame.args ~= nil and frame.args[1] or frame[1]
local id = p.getSkillID(skillName)
if id == nil or id == '' then
return "Unknown"
else
return id
end
end
function p.getEquipmentSlotName(id)
local slotData = GameData.getEntityByID('equipmentSlots', id)
if slotData ~= nil then
return slotData.emptyName
end
end
function p.getEquipmentSlotID(name)
local slotData = GameData.getEntityByProperty('equipmentSlots', 'emptyName', name)
if slotData ~= nil then
return slotData.id
end
end
function p.getCombatStyleName(styleNum)
if type(styleNum) == 'number' then
local styleName = GameData.rawData.attackTypes[styleNum]
if styleName ~= nil then
return Shared.titleCase(styleName)
end
elseif type(styleNum) == 'string' and type(GameData.rawData.attackTypes[string.lower(styleNum)]) == 'number' then
return Shared.titleCase(styleNum)
end
return Shared.printError('Invalid combat style')
end
--- Slayer functions
--
function p.getSlayerTierByID(tierID)
if type(tierID) ~= 'number' then
return nil
else
return GameData.rawData.slayerTaskCategories[tierID + 1]
end
end
function p.getSlayerTier(name)
return GameData.getEntityByProperty('slayerTiers', 'display', name)
end
function p.getSlayerTierByLevel(level)
if type(level) ~= 'number' or level < 1 then
return Shared.printError('Invalid Slayer level')
end
for i, tier in ipairs(GameData.rawData.slayerTaskCategories) do
if tier.type == 'CombatLevel' and tier.minLevel <= level and (tier.maxLevel == nil or tier.maxLevel >= level) then
return tier
end
end
end
--
-- the following functions just return subsets of the slayer functions above
--
function p.getSlayerTierName(tierID)
if type(tierID) == 'number' then
local tier = p.getSlayerTierByID(tierID)
if tier ~= nil then
return tier.display
end
end
return Shared.printError('Invalid Slayer tier')
end
function p.getSlayerTierNameByLevel(lvl)
local tier = p.getSlayerTierByLevel(lvl)
if type(tier) == 'table' then
return tier.display
else
return Shared.printError('Invalid Slayer tier')
end
end
--
--- End of slayer functions
--Turns a modifier name like 'increasedHPRegenFlat' into several pieces of data:
--Base Name, Description, IsNegative, and modifyValue
--ex. "HPRegenFlat", "+${value} Flat Hitpoints Regeneration", false, "multiplyByNumberMultiplier"
function p.getModifierDetails(modifierName)
-- Unsupported
error('Function is no longer supported', 2)
--[==[
local baseName = modifierName
local modifier = GameData.rawData.modifierData[modifierName]
if modifier == nil then
return nil
end
if Shared.startsWith(modifierName, "increased") or Shared.startsWith(modifierName, "decreased") then
baseName = string.sub(modifierName, 10)
end
return baseName, modifier.description, modifier.isNegative, modifier.modifyValue
--]==]
end
function p._getModifierText(modifier, value, doColor)
return Modifiers.getModifierText(modifier, value, doColor)
end
function p.getModifierText(frame)
local modifier = frame.args ~= nil and frame.args[1] or frame[1]
local value = frame.args ~= nil and frame.args[2] or frame[2]
local skill = frame.args ~= nil and frame.args.skill or frame.skill
local doColor = frame.args ~= nil and frame.args[3] or frame[3]
if doColor ~= nil then
doColor = string.upper(doColor) ~= 'FALSE'
end
if skill ~= nil and skill ~= '' then
value = { { ["skillID"] = p.getSkillID(skill), ["value"] = value } }
end
return p._getModifierText(modifier, value, doColor)
end
function p.getModifiersText(modifiers, doColor, inline, maxVisible)
return Modifiers.getModifiersText(modifiers, doColor, inline, maxVisible)
end
function p.getModifierSkills(modifiers)
return Modifiers.getModifierSkills(modifiers)
end
-- Returns a modifiers table indicating modifiersNew less modifiersOld
-- The returned table can be passed to getModifiersText to obtain the
-- result in a human readable format
function p.getModifiersDifference(modifiersOld, modifiersNew)
local modHasPrefix = {}
local modDiff, modDiffBase = {}, {}
local allMods = {
{ ["mods"] = (modifiersNew or {}), ["mult"] = 1 },
{ ["mods"] = (modifiersOld or {}), ["mult"] = -1 }
}
-- Generate modifiers table containing only variances
-- Create modDiffBase with mod base names (less 'increased'/'decreased' prefixes),
for i, modDef in ipairs(allMods) do
for modName, value in pairs(modDef.mods) do
local modBaseName, modIsIncrease = modName, true
if Shared.startsWith(modName, "increased") or Shared.startsWith(modName, "decreased") then
modBaseName = string.sub(modName, 10)
modIsIncrease = Shared.startsWith(modName, "increased")
modHasPrefix[modBaseName] = true
end
local modMult = (modIsIncrease and 1 or -1) * modDef.mult
if type(value) == 'table' then
-- Skill specific modifier
if modDiffBase[modBaseName] == nil then
modDiffBase[modBaseName] = {}
end
for j, subVal in ipairs(value) do
if type(subVal) == 'table' and subVal.skillID ~= nil then
modDiffBase[modBaseName][subVal.skillID] = (modDiffBase[modBaseName][subVal.skillID] or 0) + subVal.value * modMult
end
end
else
modDiffBase[modBaseName] = (modDiffBase[modBaseName] or 0) + value * modMult
end
end
end
-- Transform modDiffBase into modDiff with the appropriate mod name within the return value
for modBaseName, value in pairs(modDiffBase) do
if type(value) == 'table' then
-- Skill specific modifier
for skillID, subVal in pairs(value) do
if subVal ~= 0 then
local modName = nil
if modHasPrefix[modBaseName] then
modName = (subVal < 0 and 'decreased' or 'increased') .. modBaseName
else
modName = modBaseName
end
if modDiff[modName] == nil then
modDiff[modName] = {}
end
table.insert(modDiff[modName], { ["skillID"] = skillID, ["value"] = math.abs(subVal) })
end
end
elseif value ~= 0 then
local modName = nil
if modHasPrefix[modBaseName] then
modName = (value < 0 and 'decreased' or 'increased') .. modBaseName
else
modName = modBaseName
end
modDiff[modName] = (modDiff[modName] or 0) + math.abs(value)
if GameData.rawData.modifierData[modName] == nil then
modDiff[modName] = nil
end
end
end
return modDiff
end
-- From game version 1.1 onwards, some entities have custom descriptions, while
-- many are generated based on the modifiers associated to that entity. This
-- function handles that logic given a custom description (may be nil) and
-- a modifiers object
function p.getDescription(customDescription, modifiers)
if customDescription ~= nil then
return customDescription
else
return p.getModifiersText(modifiers, false)
end
end
return p