14,472
edits
(_getModifierText: Emit modifier name in error message if invalid) |
(Correct RegenerationInterval attributes) |
||
(45 intermediate revisions by 3 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 from Equipment", 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'} }, | |||
["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 | |||
} | } | ||
--Difficulties are hard coded which is dumb but means hardcoding them here too | --Difficulties are hard coded which is dumb but means hardcoding them here too | ||
local Difficulties = { | local Difficulties = { | ||
[0] = 'Very Easy', | |||
[1] = 'Easy', | |||
[2] = 'Medium', | |||
[3] = 'Hard', | |||
[4] = 'Very Hard', | |||
[5] = 'Elite', | |||
[6] = 'Insane' | |||
} | |||
function p.getTriangleAttribute(attribute, attackerStyle, targetStyle, mode) | |||
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(mode) ~= 'string' then | |||
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 | |||
return attrData[attStyle][targStyle] | |||
end | |||
end | |||
function p.getTriangleDamageModifier( | 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( | function p.getTriangleDRModifier(attackerStyle, targetStyle, mode) | ||
return p.getTriangleAttribute('reductionModifier', attackerStyle, targetStyle, mode) | |||
end | end | ||
function p.getDifficultyString(difficulty) | function p.getDifficultyString(difficulty) | ||
return Difficulties[difficulty] | |||
end | end | ||
function p.getSkillName(skillID) | function p.getSkillName(skillID) | ||
return ConstantData.skill[skillID] | |||
end | end | ||
function p.getSkillID(skillName) | function p.getSkillID(skillName) | ||
return ConstantData.skill[skillName] | |||
end | end | ||
function p.getEquipmentSlotName(id) | function p.getEquipmentSlotName(id) | ||
return type(id) == 'number' and ConstantData.equipmentSlot[id] or 'Invalid' | |||
end | end | ||
function p.getEquipmentSlotID(name) | function p.getEquipmentSlotID(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 | ||
function p.getCombatStyleName(styleNum) | function p.getCombatStyleName(styleNum) | ||
if type(styleNum) == 'number' then | |||
local styleName = ConstantData.attackType[styleNum] | |||
if styleName ~= nil then | |||
return Shared.titleCase(styleName) | |||
end | |||
elseif type(styleNum) == 'string' and type(ConstantData.attackType[string.lower(styleNum)]) == 'number' then | |||
return Shared.titleCase(styleNum) | |||
end | |||
return "ERROR: Invalid combat style[[Category:Pages with script errors]]" | |||
end | end | ||
function p. | |||
--- 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. | function p.getSlayerTier(name) | ||
local tierID = ConstantData.slayerTier[name] | |||
if tierID == nil then | |||
return nil | |||
else | |||
return p.getSlayerTierByID(tierID) | |||
end | |||
end | end | ||
function p. | function p.getSlayerTierByLevel(level) -- returns a full table | ||
if type(level) ~= 'number' or level < 1 then | |||
return "ERROR: Invalid Slayer level [[Category:Pages with script errors]]" | |||
end | |||
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 | ||
-- | |||
-- the following functions just return subsets of the slayer functions above | |||
-- | |||
function p.getSlayerTierName(tierID, fallback) | |||
return type(tierID) == 'number' and ConstantData.slayerTier[tierID] or "ERROR: Invalid Slayer tier[[Category:Pages with script errors]]" | |||
end | 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 of slayer functions | |||
--Turns a modifier name like 'increasedMeleeAccuracyBonus' into several pieces of data: | --Turns a modifier name like 'increasedMeleeAccuracyBonus' into several pieces of data: | ||
Line 336: | Line 480: | ||
--ex. "MeleeAccuracyBonus", "+{V}% Melee Accuracy", "+", false | --ex. "MeleeAccuracyBonus", "+{V}% Melee Accuracy", "+", false | ||
function p.getModifierDetails(modifierName) | function p.getModifierDetails(modifierName) | ||
local baseName = modifierName | |||
local isIncrease = true | |||
local isNegative = false | |||
local valueUnsigned = 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 | |||
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 | |||
if type(modifier.unsigned) == 'boolean' then valueUnsigned = modifier.unsigned end | |||
return baseName, modifier.text, sign, not isPositive, valueUnsigned, modifier | |||
end | end | ||
function p._getModifierText(modifier, value, doColor) | function p._getModifierText(modifier, value, doColor) | ||
if doColor == nil then doColor = true end | |||
local modName, modText, sign, isNegative, valueUnsigned = p.getModifierDetails(modifier) | |||
if modName == nil then | |||
return 'ERROR: Invalid modifier type for ' .. modifier .. '[[Category:Pages with script errors]]' | |||
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 | |||
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/>') | |||
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 | |||
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 value = value[2] end | |||
end | |||
end | |||
local valSign = (valueUnsigned and '' or sign) | |||
result = string.gsub(result, '{(V[^}]*)}', function(rule) return valSign .. formatModValue(value, rule) end) | |||
result = string.gsub(result, '{S}', sign) | |||
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 | end | ||
function p.getModifierText(frame) | 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 | end | ||
function p.getModifiersText(modifiers, doColor) | 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 | end | ||
function p.getModifierSkills(modifiers) | 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 baseName == nil then | |||
return { 'ERROR: Modifier '..modifier..' is invalid' } | |||
end | |||
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 | end | ||
return p | return p |