Module:Constants
Documentation for this module may be created at Module:Constants/doc
local p = {}
local ConstantData = mw.loadData('Module:Constants/data')
local ItemData = mw.loadData('Module:Items/data')
local Shared = require('Module:Shared')
--Just hardcoding these because I guess that's where we're at
local modifierTypes = {
["MeleeStrengthBonus"] = { text = "{V}% Melee Strength Bonus", 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'} },
["ChanceRandomPotionHerblore"] = { text = "{V}% chance to gain a second potion of a random tier", skills = {'Herblore'} },
["FlatPrayerCostReduction"] = { text = "{V} Prayer Point Cost for Prayers", inverseSign = true, skills = {'Prayer'} },
["MinEarthSpellDmg"] = { text = "{VX} Min Earth Spell Dmg", skills = {'Magic'} },
["SlayerTaskLength"] = { text = "{V}% Slayer Task Length/Qty", skills = {'Slayer'} },
["ChanceToDoubleLootCombat"] = { text = "{V}% Chance To Double Loot in Combat", skills = {'Combat'} },
["GPFromAgility"] = { text = "{V}% GP From Agility", skills = {'Agility'} },
["SkillXP"] = { text = "{V1}% {SV0} Skill XP" },
["MiningNodeHP"] = { text = "{V} Mining Node HP", skills = {'Mining'} },
["StaminaPerObstacle"] = { text = "{V} Stamina per Agility Obstacle Completion", skills = {'Agility'} },
["ChanceToDoubleItems"] = { text = "{V} Chance To Double Items" },
["FarmingYield"] = { text = "{V}% Farming Yield", skills = {'Farming'} },
["GPFromMonstersFlat"] = { text = "{V} GP From Monsters", skills = {'Combat'} },
["GlobalPreservationChance"] = { text = "{V}% Chance to Preserve Resources in Skills" },
["RunePreservation"] = { text = "{V}% Rune Preservation", skills = {'Magic'} },
["MaxHitpoints"] = { text = "{VX} Maximum Hitpoints", skills = {'Combat'} },
["ChanceToDoubleItemsSkill"] = { text = "{V1}% Chance to Double Items in {SV0}" },
["autoSlayerUnlocked"] = { text = "{V} Auto Slayer Unlocked", skills = {'Slayer'} },
["HitpointRegeneration"] = { text = "{V}% Hitpoint Regeneration", skills = {'Combat'} },
["SlayerXP"] = { text = "{V}% Slayer XP", skills = {'Slayer'} },
["PotionChargesFlat"] = { text = "{V} Charges per Potion" },
["SkillInterval"] = { text = "{VMS1}s {SV0} Interval", isIncreaseNegative = true },
["BankSpace"] = { text = "{V} Bank Space" },
["MinHitBasedOnMaxHit"] = { text = "{V}% of Maximum Hit added to Minimum Hit", skills = {'Combat'} },
["DamageToSlayerTasks"] = { text = "{V}% Damage To Slayer Tasks", skills = {'Combat'} },
["Lifesteal"] = { text = "{V}% Lifesteal", skills = {'Combat'} },
["HPRegenFlat"] = { text = "{V} Flat HP Regen", skills = {'Combat'} },
["ChanceToDoubleOres"] = { text = "{V}% Chance to Double Ores in Mining", skills = {'Combat'} },
["MaxStamina"] = { text = "{V} Max Stamina" },
["MonsterRespawnTimer"] = { text = "{VMS}s Monster Respawn Timer", isIncreaseNegative = true, skills = {'Combat'} },
["SkillPreservationChance"] = { text = "{V1}% Chance to Preserve Resources in {SV0}" },
["DamageToCombatAreaMonsters"] = { text = "{V}% Damage To Combat Area Monsters", skills = {'Combat'} },
["TreeCutLimit"] = { text = "{V} Tree Cut Limit", skills = {'Woodcutting'} },
["EquipmentSets"] = { text = "{V} Equipment Sets" },
["HiddenSkillLevel"] = { text = "{V1} Hidden {SV0} Level" },
["ChanceToPreservePrayerPoints"] = { text = "{V}% Chance To Preserve Prayer Points", skills = {'Prayer'} },
["ReflectDamage"] = { text = "{V}% Reflect Damage", skills = {'Combat'} },
["MeleeEvasion"] = { text = "{V}% Melee Evasion", skills = {'Combat'} },
["DamageToSlayerAreaMonsters"] = { text = "{V}% Damage To Slayer Area Monsters", skills = {'Combat'} },
["GPFromMonsters"] = { text = "{V}% GP From Monsters", skills = {'Combat'} },
["MagicEvasion"] = { text = "{V}% Magic Evasion", skills = {'Combat'} },
["PlayerAttackSpeedPercent"] = { text = "{V}% Player Attack Speed", isIncreaseNegative = true, skills = {'Combat'} },
["PreservationChance"] = { text = "{V}% Chance to Preserve Resources" },
["DamageReduction"] = { text = "{V}% Damage Reduction", skills = {'Combat'} },
["MinWaterSpellDmg"] = { text = "{VX} Min Water Spell Dmg", skills = {'Magic'} },
["DamageToAllMonsters"] = { text = "{V}% Damage To All Monsters", skills = {'Combat'} },
["golbinRaidIncreasedStartingRuneCount"] = { text = "{V} to starting Elemental Rune count" },
["FoodHealingValue"] = { text = "{V}% Food Healing Value", skills = {'Combat'} },
["MinFireSpellDmg"] = { text = "{VX} Min Fire Spell Dmg", skills = {'Magic'} },
["SlayerCoins"] = { text = "{V}% Slayer Coins", skills = {'Slayer'} },
["GPFromThievingFlat"] = { text = "{V} GP From Thieving", skills = {'Thieving'} },
["GlobalAccuracy"] = { text = "{V}% Global Accuracy", skills = {'Combat'} },
["ChanceToDoubleLootThieving"] = { text = "{V}% Chance To Double Loot in Thieving", skills = {'Thieving'} },
["SlayerAreaEffectNegationFlat"] = { text = "{V}% Flat Slayer Area Effect Negation", skills = {'Combat'} },
["MagicAccuracyBonus"] = { text = "{V}% Magic Accuracy Bonus", skills = {'Combat'} },
["SkillIntervalPercent"] = { text = "{V1}% {SV0} Interval", isIncreaseNegative = true },
["GlobalSkillXP"] = { text = "{V}% Global Skill XP" },
["MeleeAccuracyBonus"] = { text = "{V}% Melee Accuracy Bonus", skills = {'Combat'} },
["DamageToBosses"] = { text = "{V}% Damage To Bosses", skills = {'Combat'} },
["ChanceToPreservePotionCharge"] = { text = "{V}% Chance To Preserve Potion Charge" },
["MaxHitPercent"] = { text = "{V}% Max Hit", skills = {'Combat'} },
["AltMagicSkillXP"] = { text = "{V}% Alt. Magic Skill XP", skills = {'Magic'} },
["StaminaPreservationChance"] = { text = "{V}% Chance to Preserve Stamina" },
["MinAirSpellDmg"] = { text = "{VX} Min Air Spell Dmg", skills = {'Combat'} },
["AutoEatEfficiency"] = { text = "{V}% Auto Eat Efficiency", skills = {'Combat'} },
["GPFromThieving"] = { text = "{V}% GP From Thieving", skills = {'Thieving'} },
["ChanceToDoubleItemsGlobal"] = { text = "{V}% Chance to Double Items Globally" },
["GPGlobal"] = { text = "{V}% GP from all sources (Except Item Selling)", skills = {'Combat', 'Thieving', 'Agility'} },
["RangedAccuracyBonus"] = { text = "{V} Ranged Accuracy Bonus", skills = {'Combat'} },
["AutoEatThreshold"] = { text = "{V}% Auto Eat Threshold", skills = {'Combat'} },
["PlayerAttackSpeed"] = { text = "{VMS}s Player Attack Speed", isIncreaseNegative = true, skills = {'Combat'} },
["freeBonfires"] = { text = "+ Automatically relight bonfires for free", skills = {'Firemaking'} },
["AutoEatHPLimit"] = { text = "{V}% Auto Eat HP Limit", skills = {'Combat'} },
["BankSpaceShop"] = { text = "{V} Bank Space from Shop" },
["BirdNestDropRate"] = { text = "{V}% Bird Nest drop rate", skills = {'Woodcutting'} },
["RangedEvasion"] = { text = "{V}% Ranged Evasion", skills = {'Combat'} },
["ChanceDoubleHarvest"] = { text = "{V}% chance for double harvest", skills = {'Farming'} },
["golbinRaidStartingWeapon"] = { text = "Start the Golbin Raid with an {IV}" },
["AttackRolls"] = { text = "+Lucky Hit Chance (Roll twice, take the better result)", skills = {'Combat'} },
["AmmoPreservation"] = { text = "{V}% Ammo Preservation", skills = {'Ranged'} },
["RangedStrengthBonus"] = { text = "{V}% Ranged Strength Bonus", skills = {'Combat'} },
["MagicDamageBonus"] = { text = "{V}% Magic Damage Bonus", skills = {'Combat'} },
["MasteryXP"] = { text = "{V1}% {SV0} Mastery XP" },
["dungeonEquipmentSwapping"] = { text = "{V} Dungeon Equipment Swapping", skills = {'Combat'} },
["SeeingGoldChance"] = { text = "{V}% chance for Silver Ore to also produce a Gold Bar when smithed", skills = {'Smithing'} },
["ElementalRuneGain"] = { text = "{V} runes received when generating random elemental runes", skills = {'Runecrafting'} },
["StaminaCost"] = { text = "{V} Stamina Cost per action", isIncreaseNegative = true },
["GPFromSales"] = { text = "{V}% GP From Sales" },
["MaxHitFlat"] = { text = "{VX} Max Hit", skills = {'Combat'} },
["ChanceNoDamageMining"] = { text = "{V}% chance to do zero damage to Ores and Rune Essence", skills = {'Mining'} },
["ChanceForElementalRune"] = { text = "{V}% chance to receive random elemental runes per Runecraft", skills = {'Runecrafting'} },
["ChanceToApplyBurn"] = { text = "{V}% Chance to apply Burn to Enemy in Combat", skills = {'Combat'} },
["SummoningShardCost"] = { text = "{V} Shard Cost when creating Familiars in Summoning", skills = {'Summoning'} },
["SummoningCreationCharges"] = { text = "{V} Base Quantity for Summoning Tablet Creation", skills = {'Summoning'} },
["SummoningChargePreservation"] = { text = "{V}% Chance to preserve Summoning Charges", skills = {'Summoning'} },
["GPOnEnemyHit"] = { text = "{V} GP Gained on successful Enemy Hit", skills = {'Combat'} },
["AdditionalRunecraftCountRunes"] = { text = "{V} Additional Runes of the same type in Runecrafting", skills = {'Runecrafting'} },
["ChanceAdditionalSkillResource"] = { text = "{V1}% Chance to gain +1 additional resource in {SV0}. Cannot be doubled" },
["EnemyMeleeEvasion"] = { text = "{V}% Enemy Melee Evasion", isIncreaseNegative = true, skills = {'Combat'} },
["EnemyRangedEvasion"] = { text = "{V}% Enemy Ranged Evasion", isIncreaseNegative = true, skills = {'Combat'} },
["EnemyMagicEvasion"] = { text = "{V}% Enemy Magic Evasion", isIncreaseNegative = true, skills = {'Combat'} }
}
--Difficulties are hard coded which is dumb but means hardcoding them here too
local Difficulties = {
[0] = 'Very Easy',
[1] = 'Easy',
[2] = 'Medium',
[3] = 'Hard',
[4] = 'Very Hard',
[5] = 'Elite',
[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)
if CombatTriangle[playerStyle].bonus == enemyStyle then
return CombatTriangle.damageBonus
elseif CombatTriangle[playerStyle].penalty == enemyStyle then
if mode == 'Hardcore' or mode == 'Adventure' then
return CombatTriangle.damagePenalty.Hardcore
else
return CombatTriangle.damagePenalty.Normal
end
else
return 1
end
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(playerStyle, enemyStyle, mode)
if CombatTriangle[playerStyle].bonus == enemyStyle then
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
function p.getDifficultyString(difficulty)
return Difficulties[difficulty]
end
function p.getSkillName(skillID)
for skName, ID in Shared.skpairs(ConstantData.skill) do
if ID == skillID then
return skName
end
end
return nil
end
function p.getSkillID(skillName)
return ConstantData.skill[skillName]
end
function p.getEquipmentSlotName(id)
for slotName, i in Shared.skpairs(ConstantData.equipmentSlot) do
if i == id then
return slotName
end
end
return 'Invalid'
end
function p.getEquipmentSlotID(name)
return ConstantData.equipmentSlot[name]
end
function p.getCombatStyleName(styleNum)
for name, num in Shared.skpairs(ConstantData.attackType) do
if num == styleNum then
return name
end
end
return "ERROR: Invalid combat style[[Category:Pages with script errors]]"
end
function p.getSlayerTierName(tier)
for name, num in Shared.skpairs(ConstantData.slayerTier) do
if num == tier then
return name
end
end
return "ERROR: Invalid Slayer tier[[Category:Pages with script errors]]"
end
function p.getSlayerTierNameByLevel(lvl)
for i, tier in Shared.skpairs(ConstantData.Slayer.Tiers) do
if tier.minLevel <= lvl and (tier.maxLevel >= lvl or tier.maxLevel == -1) then
return tier.display
end
end
return 'N/A'
end
function p.getSlayerTier(name)
for i, tier in Shared.skpairs(ConstantData.Slayer.Tiers) do
if tier.display == name then
local result = Shared.clone(tier)
result.id = i - 1
return result
end
end
end
function p.getSlayerTierByID(tierID)
if ConstantData.Slayer.Tiers[tierID + 1] == nil then
return nil
end
local result = Shared.clone(ConstantData.Slayer.Tiers[tierID + 1])
result.id = tierID
return result
end
--Turns a modifier name like 'increasedMeleeAccuracyBonus' into several pieces of data:
--Base Name, Text, Sign, and IsNegative
--ex. "MeleeAccuracyBonus", "+{V}% Melee Accuracy", "+", false
function p.getModifierDetails(modifierName)
local baseName = modifierName
local isIncrease = true
local isNegative = false
if Shared.startsWith(modifierName, "increased") or Shared.startsWith(modifierName, "decreased") then
baseName = string.sub(modifierName, 10)
isIncrease = Shared.startsWith(modifierName, "increased")
end
local modifier = modifierTypes[baseName]
if modifier == nil then
mw.log(baseName)
return nil
end
local isPositive = isIncrease
if modifier.isIncreaseNegative then
isPositive = not isPositive
end
local sign = "+"
if (not isIncrease and not modifier.inverseSign) or (isIncrease and modifier.inverseSign) then
sign = "-"
end
return baseName, modifier.text, sign, not isPositive
end
function p._getModifierText(modifier, value, doColor)
if doColor == nil then doColor = true end
local modName, modText, sign, isNegative = p.getModifierDetails(modifier)
if modName == nil then
return 'ERROR: Invalid modifier type [[Category:Pages with script errors]]'
end
local result = modText
if type(value) == 'table' then
if Shared.tableCount(value) > 0 and type(value[1]) == 'table' then
--Potentially return multiple rows if necessary
local resultArray = {}
for i, subVal in Shared.skpairs(value) do
table.insert(resultArray, p._getModifierText(modifier, subVal, doColor))
end
return table.concat(resultArray, '<br/>')
else
if value[1] ~= nil then
local skillName = p.getSkillName(value[1])
if skillName ~= nil then
result = string.gsub(result, '{SV0}', p.getSkillName(value[1]))
end
end
if value[2] ~= nil then
result = string.gsub(result, '{V1}', sign..value[2])
result = string.gsub(result, '{VMS1}', sign..(value[2] / 1000))
end
end
else
if string.find(result, '{IV}', 1, true) ~= nil and tonumber(value) ~= nil then
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}', sign..value)
result = string.gsub(result, '{VMS}', sign..(value / 1000))
result = string.gsub(result, '{VX}', sign..(value * 10))
end
if doColor then
if isNegative ~= nil and isNegative then
result = '<span style="color:red">'..result..'</span>'
else
result = '<span style="color:green">'..result..'</span>'
end
end
return result
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 = {p.getSkillID(skill), value}
end
return p._getModifierText(modifier, value, doColor)
end
function p.getModifiersText(modifiers, doColor)
if modifiers == nil or Shared.tableCount(modifiers) == 0 then
return ''
end
local modArray = {}
for bonus, value in Shared.skpairs(modifiers) do
table.insert(modArray, p._getModifierText(bonus, value, doColor))
end
return table.concat(modArray, "<br/>")
end
function p.getModifierSkills(modifiers)
local skillArray = {}
for modifier, value in Shared.skpairs(modifiers) do
if type(value) == 'table' then
for i, subVal in Shared.skpairs(value) do
local skillName = p.getSkillName(subVal[1])
if not Shared.contains(skillArray, skillName) then
table.insert(skillArray, skillName)
end
end
end
local baseName = p.getModifierDetails(modifier)
if modifierTypes[baseName].skills ~= nil then
for i, skillName in Shared.skpairs(modifierTypes[baseName].skills) do
if not Shared.contains(skillArray, skillName) then
table.insert(skillArray, skillName)
end
end
end
end
return skillArray
end
return p