Anonymous

Module:Constants: Difference between revisions

From Melvor Idle
_getModifierText: Fix issue with interpretation of 'V+100' modifier values
m (Further corrections to RolledReflectDamage)
(_getModifierText: Fix issue with interpretation of 'V+100' modifier values)
(19 intermediate revisions by 2 users not shown)
Line 8: Line 8:
--Just hardcoding these because I guess that's where we're at
--Just hardcoding these because I guess that's where we're at
local modifierTypes = {
local modifierTypes = {
["MeleeStrengthBonus"] = { text = "{V}% Melee Strength Bonus", skills = {'Combat'} },
["MeleeStrengthBonus"] = { text = "{V}% Melee Strength Bonus from Equipment", skills = {'Combat'} },
["DamageToDungeonMonsters"] = { text = "{V}% Damage To Dungeon Monsters", skills = {'Combat'} },
["DamageToDungeonMonsters"] = { text = "{V}% Damage To Dungeon Monsters", skills = {'Combat'} },
["GlobalMasteryXP"] = { text = "{V}% Global Mastery XP", skills = {'Woodcutting', 'Fishing', 'Firemaking', 'Cooking', 'Mining', 'Smithing', 'Thieving', 'Farming', 'Fletching', 'Crafting', 'Runecrafting', 'Herblore', 'Agility', 'Summoning', 'Astrology'} },
["GlobalMasteryXP"] = { text = "{V}% Global Mastery XP", skills = {'Woodcutting', 'Fishing', 'Firemaking', 'Cooking', 'Mining', 'Smithing', 'Thieving', 'Farming', 'Fletching', 'Crafting', 'Runecrafting', 'Herblore', 'Agility', 'Summoning', 'Astrology'} },
Line 65: Line 65:
["MaxHitPercent"] = { text = "{V}% Max Hit", skills = {'Combat'} },
["MaxHitPercent"] = { text = "{V}% Max Hit", skills = {'Combat'} },
["AltMagicSkillXP"] = { text = "{V}% Alt. Magic Skill XP", skills = {'Magic'} },
["AltMagicSkillXP"] = { text = "{V}% Alt. Magic Skill XP", skills = {'Magic'} },
["MinAirSpellDmg"] = { text = "{VX} Min Air Spell Dmg", skills = {'Combat'} },
["MinAirSpellDmg"] = { text = "{VX} Min Air Spell Dmg", skills = {'Magic'} },
["AutoEatEfficiency"] = { text = "{V}% Auto Eat Efficiency", skills = {'Combat'} },
["AutoEatEfficiency"] = { text = "{V}% Auto Eat Efficiency", skills = {'Combat'} },
["GPFromThieving"] = { text = "{V}% GP From Thieving", skills = {'Thieving'} },
["GPFromThieving"] = { text = "{V}% GP From Thieving", skills = {'Thieving'} },
Line 78: Line 78:
["RangedEvasion"] = { text = "{V}% Ranged Evasion", skills = {'Combat'} },
["RangedEvasion"] = { text = "{V}% Ranged Evasion", skills = {'Combat'} },
["ChanceDoubleHarvest"] = { text = "{V}% chance for double harvest", skills = {'Farming'} },
["ChanceDoubleHarvest"] = { text = "{V}% chance for double harvest", skills = {'Farming'} },
["golbinRaidStartingWeapon"] = { text = "Start the Golbin Raid with an {IV}" },
["golbinRaidStartingWeapon"] = { text = "Start the Golbin Raid with an {VITEM}", unsigned = true },
["AttackRolls"] = { text = "+Lucky Hit Chance (Roll twice, take the better result)", skills = {'Combat'} },
["AttackRolls"] = { text = "+Lucky Hit Chance (Roll twice, take the better result)", skills = {'Combat'} },
["AmmoPreservation"] = { text = "{V}% Ammo Preservation", skills = {'Ranged'} },
["AmmoPreservation"] = { text = "{V}% Ammo Preservation", skills = {'Ranged'} },
["RangedStrengthBonus"] = { text = "{V}% Ranged Strength Bonus", skills = {'Combat'} },
["RangedStrengthBonus"] = { text = "{V}% Ranged Strength Bonus from Equipment", skills = {'Combat'} },
["MagicDamageBonus"] = { text = "{V}% Magic Damage Bonus", skills = {'Combat'} },
["MagicDamageBonus"] = { text = "{V}% Magic Damage Bonus from Equipment", skills = {'Combat'} },
["MasteryXP"] = { text = "{V}% {SV0} Mastery XP" },
["MasteryXP"] = { text = "{V}% {SV0} Mastery XP" },
["dungeonEquipmentSwapping"] = { text = "{V} Dungeon Equipment Swapping", skills = {'Combat'} },
["dungeonEquipmentSwapping"] = { text = "{V} Dungeon Equipment Swapping", skills = {'Combat'} },
Line 122: Line 122:
["summoningSynergy_3_11"] = {text = "When successfully pickpocketing the Lumberjack in Thieving, grants {V} Bird Nest instead of GP.", skills = {'Thieving'}},
["summoningSynergy_3_11"] = {text = "When successfully pickpocketing the Lumberjack in Thieving, grants {V} Bird Nest instead of GP.", skills = {'Thieving'}},
["summoningSynergy_3_16"] = {text = "In Woodcutting, {V}% chance for a random Silver or Gold Jewelry to drop instead of a Bird Nest.", skills = {'Woodcutting'}},
["summoningSynergy_3_16"] = {text = "In Woodcutting, {V}% chance for a random Silver or Gold Jewelry to drop instead of a Bird Nest.", skills = {'Woodcutting'}},
["summoningSynergy_3_17"] = {text = "{V}% chance to gain +1 Base Logs from Woodcutting, or produced Items from Smithing.", skills = {'Woodcutting'}},
["summoningSynergy_3_17"] = {text = "{V}% chance to gain +1 Base Logs from Woodcutting, or produced Items from Smithing.", skills = {'Woodcutting', 'Smithing'}},
["summoningSynergy_3_18"] = {text = "While the Bird Nest Potion is active in Woodcutting, grants {V} minimum Bird Nest.", skills = {'Woodcutting'}},
["summoningSynergy_3_18"] = {text = "While the Bird Nest Potion is active in Woodcutting, grants {V} minimum Bird Nest.", skills = {'Woodcutting'}},
["summoningSynergy_3_19"] = {text = "{V}% of Woodcutting Skill XP is earned as Firemaking Skill XP. Chance to double Logs is halved.", skills = {'Woodcutting', 'Firemaking'}},
["summoningSynergy_3_19"] = {text = "{V}% of Woodcutting Skill XP is earned as Firemaking Skill XP. Chance to double Logs is halved.", skills = {'Woodcutting', 'Firemaking'}},
Line 155: Line 155:
["summoningSynergy_9_11"] = {text = "The Chef in Thieving now deals no damage to you.", skills = {'Thieving'}},
["summoningSynergy_9_11"] = {text = "The Chef in Thieving now deals no damage to you.", skills = {'Thieving'}},
["summoningSynergy_9_16"] = {text = "Crafting Recipes that require Dragonhide now use {V} quantity to create. Recipe cost cannot go below 1.", skills = {'Crafting'}, inverseSign = true},
["summoningSynergy_9_16"] = {text = "Crafting Recipes that require Dragonhide now use {V} quantity to create. Recipe cost cannot go below 1.", skills = {'Crafting'}, inverseSign = true},
["summoningSynergy_9_17"] = {text = "-{VMS}s Skill Interval for Cooking & Smithing.", skills = {'Cooking', 'Smithing'}},
["summoningSynergy_9_17"] = {text = "{VMS}s Skill Interval for Cooking & Smithing.", inverseSign = true, skills = {'Cooking', 'Smithing'}},
["summoningSynergy_9_18"] = {text = "Generous Cook Potions now provide {V}% charges. This bonus is applied when a new potion is activated.", skills = {'Cooking'}},
["summoningSynergy_9_18"] = {text = "Generous Cook Potions now provide {V}% charges. This bonus is applied when a new potion is activated.", skills = {'Cooking'}},
["summoningSynergy_10_11"] = {text = "Successfully pickpocketting the Miner in Thieving will now grant {V} Rune Essence.", skills = {'Thieving'}},
["summoningSynergy_10_11"] = {text = "Successfully pickpocketting the Miner in Thieving will now grant {V} Rune Essence.", skills = {'Thieving'}},
Line 207: Line 207:
["debuffImmunity"] = { text = "Immune to debuffs", skills = {'Combat'} },
["debuffImmunity"] = { text = "Immune to debuffs", skills = {'Combat'} },
["Decay"] = { text = "Take {V}% of Max HP as damage on a succesful attack", isIncreaseNegative = true, skills = {'Combat'} },
["Decay"] = { text = "Take {V}% of Max HP as damage on a succesful attack", isIncreaseNegative = true, skills = {'Combat'} },
["doubleItemsSkill"] = { text = "x{VMUL} Items received from {SV0}" },
["doubleItemsSkill"] = { text = "x{VMUL} Items received from {SV0}", unsigned = true },
["doubleOresMining"] = { text = "x{VMUL} Ores received from Mining", skills = {'Mining'} },
["doubleOresMining"] = { text = "x{VMUL} Ores received from Mining", unsigned = true, skills = {'Mining'} },
["DragonBreathDamage"] = { text = "{V}% damage taken from dragonbreath", isIncreaseNegative = true, skills = {'Combat'} },
["DragonBreathDamage"] = { text = "{V}% damage taken from dragonbreath", isIncreaseNegative = true, skills = {'Combat'} },
["FiremakingCoalChance"] = { text = "{V}% chance to receive coal when burning logs in Firemaking", skills = {'Firemaking'} },
["FiremakingCoalChance"] = { text = "{V}% chance to receive coal when burning logs in Firemaking", skills = {'Firemaking'} },
Line 256: Line 256:
["RedemptionThreshold"] = { text = "{V}% redemption threshold", skills = {'Combat'} },
["RedemptionThreshold"] = { text = "{V}% redemption threshold", skills = {'Combat'} },
["RolledReflectDamage"] = { text = "{S}0-{VX} Reflect Damage", unsigned = true, skills = {'Combat'} },
["RolledReflectDamage"] = { text = "{S}0-{VX} Reflect Damage", unsigned = true, skills = {'Combat'} },
["RuneProvision"] = { text = "Rune providing items provide {VMUL}x as many runes", skills = {'Combat'} },
["RuneProvision"] = { text = "Rune providing items provide {VMUL}x as many runes", unsigned = true, skills = {'Combat'} },
["SecondaryFoodBurnChance"] = { text = "{V}% Secondary Chance to burn food when Cooking", isIncreaseNegative = true, skills = {'Cooking'} },
["SecondaryFoodBurnChance"] = { text = "{V}% Secondary Chance to burn food when Cooking", isIncreaseNegative = true, skills = {'Cooking'} },
["sleepImmunity"] = { text = "Immune to Sleep", skills = {'Combat'} },
["sleepImmunity"] = { text = "Immune to Sleep", skills = {'Combat'} },
Line 298: Line 298:
["frostBurnImmunity"] = { text = "{V}% chance to ignore Frostburn", skills = {'Combat'} },
["frostBurnImmunity"] = { text = "{V}% chance to ignore Frostburn", skills = {'Combat'} },
["globalEvasionHPScaling"] = { text = "Evasion Ratings are multiplied by {V} times current Hitpoints percent", skills = {'Combat'} },
["globalEvasionHPScaling"] = { text = "Evasion Ratings are multiplied by {V} times current Hitpoints percent", skills = {'Combat'} },
["GPFromFiremaking"] = { text = "{V}% GP from Firemaking.", skills = {'Firemaking'} },
["infiniteLootContainer"] = { text = "The loot container has an infinite amount of slots", skills = {'Combat'} },
["infiniteLootContainer"] = { text = "The loot container has an infinite amount of slots", skills = {'Combat'} },
["magicImmunity"] = { text = "Immune to Magic attacks", skills = {'Combat'} },
["magicImmunity"] = { text = "Immune to Magic attacks", skills = {'Combat'} },
Line 328: Line 329:
[4] = 'Very Hard',
[4] = 'Very Hard',
[5] = 'Elite',
[5] = 'Elite',
[6] = 'Insane'}
[6] = 'Insane'
 
--07/03/21: Hardcoding in Combat Triangle Modifiers
local CombatTriangle = {
damageBonus = 1.1,
drBonus = 1.25,
damagePenalty = { Normal = 0.85,
Hardcore = 0.75 },
drPenalty = { Melee = { Normal = 0.5,
Hardcore = 0.25 },
Ranged = { Normal = 0.95,
Hardcore = 0.75 },
Magic = { Normal = 0.85,
Hardcore = 0.75 }},
Melee = { bonus = "Ranged", penalty = "Magic" },
Ranged = { bonus = "Magic", penalty = "Melee" },
Magic = { bonus = "Melee", penalty = "Ranged" },
}
}


function p.getTriangleDamageModifier(playerStyle, enemyStyle, mode)
function p.getTriangleAttribute(attribute, attackerStyle, targetStyle, mode)
if CombatTriangle[playerStyle].bonus == enemyStyle then
if type(attribute) ~= 'string' then
return CombatTriangle.damageBonus
error("Parameter 'attribute' must be a string", 2)
elseif CombatTriangle[playerStyle].penalty == enemyStyle then
elseif type(attackerStyle) ~= 'string' then
if mode == 'Hardcore' or mode == 'Adventure' then
error("Parameter 'attackerStyle' must be a string", 2)
return CombatTriangle.damagePenalty.Hardcore
elseif type(targetStyle) ~= 'string' then
else
error("Parameter 'targetStyle' must be a string", 2)
return CombatTriangle.damagePenalty.Normal
elseif type(mode) ~= 'string' then
end
error("Parameter 'mode' must be a string", 2)
end
local modeID = p.getGamemodeID(mode)
if modeID == nil then
error("Invalid gamemode '" .. mode .. "'", 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 triangleID = ConstantData.Gamemode.Data[modeID + 1].combatTriangle
local attrData = ConstantData.CombatTriangle[triangleID + 1][attribute]
if attrData == nil then
error("No such attribute: " .. attribute)
else
else
return 1
return attrData[attStyle][targStyle]
end
end
end
function p.getTriangleDamageModifier(attackerStyle, targetStyle, mode)
return p.getTriangleAttribute('damageModifier', attackerStyle, targetStyle, mode)
end
end


--Syntax is like p.getTriangleDRModifier('Melee', 'Ranged', 'Normal')
--Syntax is like p.getTriangleDRModifier('Melee', 'Ranged', 'Normal')
--Returns a multiplier that can be multiplied with base DR to get the post-Triangle result
--Returns a multiplier that can be multiplied with base DR to get the post-Triangle result
function p.getTriangleDRModifier(playerStyle, enemyStyle, mode)
function p.getTriangleDRModifier(attackerStyle, targetStyle, mode)
if CombatTriangle[playerStyle].bonus == enemyStyle then
return p.getTriangleAttribute('reductionModifier', attackerStyle, targetStyle, mode)
return CombatTriangle.drBonus
elseif CombatTriangle[playerStyle].penalty == enemyStyle then
if mode == 'Hardcore' or mode == 'Adventure' then
return CombatTriangle.drPenalty[playerStyle].Hardcore
else
return CombatTriangle.drPenalty[playerStyle].Normal
end
else
return 1
end
end
end


Line 395: Line 393:
function p.getEquipmentSlotID(name)
function p.getEquipmentSlotID(name)
return ConstantData.equipmentSlot[name]
return ConstantData.equipmentSlot[name]
end
function p.getGamemodeName(id)
return ConstantData.Gamemode.Enum[id]
end
function p.getGamemodeID(name)
return ConstantData.Gamemode.Enum[name]
end
end


Line 403: Line 409:
return Shared.titleCase(styleName)
return Shared.titleCase(styleName)
end
end
elseif type(styleNum) == 'string' and type(ConstantData.attackType[string.lower(styleNum)]) == 'number' then
return Shared.titleCase(styleNum)
end
end
return "ERROR: Invalid combat style[[Category:Pages with script errors]]"
return "ERROR: Invalid combat style[[Category:Pages with script errors]]"
end
end


function p.getSlayerTierName(tier)
 
return type(tier) == 'number' and ConstantData.slayerTier[tier] or "ERROR: Invalid Slayer tier[[Category:Pages with script errors]]"
--- Slayer functions
--
function p.getSlayerTierByID(tierID, slayerLevel) -- returns a full table
if slayerLevel == nil then
slayerLevel = 99 -- this might upgrade to 120 in some update
end
if type(tierID) ~= 'number' then
return nil
elseif ConstantData.Slayer.Tiers[tierID + 1] == nil then
return nil
else
local result = Shared.clone(ConstantData.Slayer.Tiers[tierID + 1])
result.id = tierID
result.minQuantity = 10*(tierID+1) + 4
result.maxQuantity = 10*(tierID+1) + 4*slayerLevel
return result
end
end
end


function p.getSlayerTierNameByLevel(lvl)
function p.getSlayerTier(name)
for i, tier in Shared.skpairs(ConstantData.Slayer.Tiers) do
local tierID = ConstantData.slayerTier[name]
if tier.minLevel <= lvl and (tier.maxLevel == nil or tier.maxLevel >= lvl) then
if tierID == nil then
return tier.display
return nil
end
else
return p.getSlayerTierByID(tierID)
end
end
return 'N/A'
end
end


function p.getSlayerTier(name)
function p.getSlayerTierByLevel(level) -- returns a full table
for i, tier in Shared.skpairs(ConstantData.Slayer.Tiers) do
if type(level) ~= 'number' or level < 1 then
if tier.display == name then
return "ERROR: Invalid Slayer level [[Category:Pages with script errors]]"
local result = Shared.clone(tier)
end
result.id = i - 1
return result
for i, tier in ipairs(ConstantData.Slayer.Tiers) do
if tier.minLevel <= level and (tier.maxLevel == nil or tier.maxLevel >= level) then
return p.getSlayerTierByID(i - 1)
end
end
end
end
end
end


function p.getSlayerTierByID(tierID)
--
if ConstantData.Slayer.Tiers[tierID + 1] == nil then
-- the following functions just return subsets of the slayer functions above
return nil
--
 
function p.getSlayerTierName(tierID, fallback)
return type(tierID) == 'number' and ConstantData.slayerTier[tierID] or "ERROR: Invalid Slayer tier[[Category:Pages with script errors]]"
end
 
function p.getSlayerTierNameByLevel(lvl, fallback)
local tier = p.getSlayerTierByLevel(lvl)
if type(tier) == 'table' then
return tier.display
else
return fallback or "ERROR: Invalid Slayer tier[[Category:Pages with script errors]]"
end
end
end


local result = Shared.clone(ConstantData.Slayer.Tiers[tierID + 1])
--
result.id = tierID
--- End of slayer functions
return result
end


--Turns a modifier name like 'increasedMeleeAccuracyBonus' into several pieces of data:
--Turns a modifier name like 'increasedMeleeAccuracyBonus' into several pieces of data:
Line 481: Line 517:
return 'ERROR: Invalid modifier type for ' .. modifier .. '[[Category:Pages with script errors]]'
return 'ERROR: Invalid modifier type for ' .. modifier .. '[[Category:Pages with script errors]]'
end
end
local formatModValue = function(value, rule)
local ruleFunctions = {
['V'] = function(val) return val end,
['VD'] = function(val) return val / 10 end,
['VMS'] = function(val) return val / 1000 end,
['VX'] = function(val) return val * 10 end,
['VX100'] = function(val) return val * 100 end,
['V+100'] = function(val) return val + 100 end,
['VMUL'] = function(val) return 2^val end,
['VITEM'] = function(val)
local item = ItemData.Items[tonumber(val) + 1]
if item ~= nil then
return item.name
end
end
}
local ruleFunc = ruleFunctions[rule] or ruleFunctions['V']
if type(value) == 'table' then
-- If table is a pair of values then format both & add a separator
return ruleFunc(value[1]) .. '-' .. ruleFunc(value[2])
else
return ruleFunc(value)
end
end


local result = modText
local result = modText
Line 492: Line 554:
end
end
return table.concat(resultArray, '<br/>')
return table.concat(resultArray, '<br/>')
else
elseif Shared.contains(modText, '{SV0}') then
-- If the value is a table and the mod text contains {SV0}, then
-- the value is a {skillID, val} pair, otherwise it is a range of
-- values {minVal, maxVal}
if value[1] ~= nil then
if value[1] ~= nil then
local skillName = p.getSkillName(value[1])
local skillName = p.getSkillName(value[1])
Line 502: Line 567:
end
end
end
end
-- Re-check the type of value, as it may have been modified above even if it was originally a table
if type(value) ~= 'table' then
local valSign = (valueUnsigned and '' or sign)
local valSign = (valueUnsigned and '' or sign)
result = string.gsub(result, '{(V[^}]*)}', function(rule) return valSign .. formatModValue(value, rule) end)
if string.find(result, '{IV}', 1, true) ~= nil and tonumber(value) ~= nil then
result = string.gsub(result, '{S}', sign)
local item = ItemData.Items[tonumber(value) + 1]
if item ~= nil then
result = string.gsub(result, '{IV}', item.name)
end
end
result = string.gsub(result, '{V}', valSign..value)
result = string.gsub(result, '{VD}', valSign..(value / 10))
result = string.gsub(result, '{VMS}', valSign..(value / 1000))
result = string.gsub(result, '{VX}', valSign..(value * 10))
result = string.gsub(result, '{VX100}', valSign..(value * 100))
result = string.gsub(result, '{V%+100}', valSign..(value + 100))
result = string.gsub(result, '{VMUL}', 2^value)
result = string.gsub(result, '{S}', sign)
end


if doColor then
if doColor then