Module:CombatAreas: Difference between revisions
From Melvor Idle
Falterfire (talk | contribs) (p.getAreaStat now handles Slayer areas) |
(getAreaPassives now works for dungeons and strongholds) |
||
(34 intermediate revisions by 5 users not shown) | |||
Line 1: | Line 1: | ||
--NOTE: Some tables are in Module:CombatAreas/AreaTables to prevent loop from referencing Monsters | |||
local p = {} | local p = {} | ||
local Constants = | local Constants = require('Module:Constants') | ||
local Shared = require('Module:Shared') | local Shared = require('Module:Shared') | ||
local GameData = require('Module:GameData') | |||
local Common = require('Module:Common') | |||
local Icons = require('Module:Icons') | local Icons = require('Module:Icons') | ||
function | local areaMap = { | ||
["combat"] = 'combatAreas', | |||
["dungeon"] = 'dungeons', | |||
["slayer"] = 'slayerAreas', | |||
["depth"] = 'abyssDepths', | |||
["stronghold"] = 'strongholds' | |||
} | |||
function p.getArea(name) | |||
--There are three types of areas but the lists are pretty short so looping all of them isn't a real issue | |||
for k, areaType in pairs(areaMap) do | |||
local area = GameData.getEntityByName(areaType, name) | |||
if area ~= nil then | |||
return area | |||
end | |||
end | |||
end | |||
function p.getAreaByID(id, areaType) | |||
for aType, areaKey in pairs(areaMap) do | |||
if areaType == nil or areaType == aType then | |||
local area = GameData.getEntityByID(areaKey, id) | |||
if area ~= nil then | |||
return area | |||
end | |||
end | |||
end | |||
end | |||
function p.getAreaFilterType(name, type) | |||
local areaType = areaMap[type] | |||
if areaType ~= nil then | |||
return GameData.getEntityByName(areaType, name) | |||
end | |||
end | |||
function p.getAreas(checkFunc) | |||
local resultArray = nil | |||
for i, areaType in pairs(areaMap) do | |||
local areas = GameData.getEntities(areaType, checkFunc) | |||
if resultArray == nil then | |||
resultArray = areas | |||
else | |||
for k, area in ipairs(areas) do | |||
table.insert(resultArray, area) | |||
end | |||
end | |||
end | |||
if resultArray == nil then | |||
resultArray = {} | |||
end | |||
return resultArray | |||
end | end | ||
function p.getArea( | --Returns the expansion icon for the area if it has one | ||
function p.getExpansionIcon(frame) | |||
local areaName = frame.args ~= nil and frame.args[1] or frame | |||
local area = p.getArea(areaName) | |||
if area == nil then | |||
return Shared.printError('No area named "' .. areaName .. '" exists in the data module') | |||
end | |||
return Icons.getExpansionIcon(area.id) | |||
end | |||
function p._getAreaRequirements(area) | |||
local resultArray = {} | |||
if area.entryRequirements ~= nil then | |||
local reqText = Common.getRequirementString(area.entryRequirements) | |||
if reqText ~= nil then | |||
table.insert(resultArray, reqText) | |||
end | |||
end | |||
if area.unlockRequirement ~= nil then | |||
-- Avoid repeating the same requirements twice, can happen for some dungeons e.g. Impending Darkness | |||
if area.entryRequirements == nil or mw.dumpObject(area.unlockRequirement) ~= mw.dumpObject(area.entryRequirements) then | |||
local reqText = Common.getRequirementString(area.unlockRequirement) | |||
if reqText ~= nil then | |||
table.insert(resultArray, reqText) | |||
end | |||
end | |||
end | |||
return table.concat(resultArray, '<br/>') | |||
end | |||
function p.getAreaRequirementsForBox(frame) | |||
--Returns infobox formatting for requirements, or returns nothing if there are none. | |||
local areaName = frame.args ~= nil and frame.args[1] or frame | |||
local area = p.getArea(areaName) | |||
if area == nil then | |||
return Shared.printError('No area named "' .. areaName .. '" exists in the data module') | |||
end | |||
local reqs = p._getAreaRequirements(area) | |||
if reqs ~= '' then | |||
reqs = "|-\r\n|'''Requirements:'''\r\n"..reqs | |||
end | |||
return reqs | |||
end | end | ||
function p. | function p._getAreaStat(area, statName) | ||
if statName == 'requirements' then | |||
return p._getAreaRequirements(area) | |||
elseif statName == 'areaEffectDesc' then | |||
if area.areaEffect ~= nil then | |||
local descText, subIdx = string.gsub(area.areaEffectDescription, '${effectValue}', area.areaEffect.magnitude or 0) | |||
return descText | |||
else | |||
return 'None' | |||
end | |||
elseif statName == 'difficulty' then | |||
local result = Constants.getDifficultyString(area.difficulty[1]) | |||
if area.difficulty[2] ~= nil then | |||
result = result..' - '..Constants.getDifficultyString(area.difficulty[2]) | |||
end | |||
return result | |||
end | |||
return area[statName] | |||
end | end | ||
function p.getAreaStat(frame) | function p.getAreaStat(frame) | ||
local areaName = frame.args ~= nil and frame.args[1] or frame[1] | |||
local statName = frame.args ~= nil and frame.args[2] or frame[2] | |||
local area = p.getArea(areaName) | |||
if area == nil then | |||
return Shared.printError('No area named "' .. areaName .. '" exists in the data module') | |||
end | |||
return p._getAreaStat(area, statName) | |||
end | |||
function p._isMonsterInArea(monster, area) | |||
return ( | |||
Shared.contains(area.monsterIDs, monster.id) | |||
-- Check for Lair of the Spider Queen random spiders | |||
or ( | |||
Shared.contains(area.monsterIDs, 'melvorTotH:RandomSpiderLair') | |||
and Shared.contains(GameData.rawData.spiderLairMonsters, monster.id) | |||
) | |||
) | |||
end | |||
function p._getMonsterAreas(monster) | |||
-- Special handling for Lair of the Spider Queen, which has a random list of enemies | |||
local randomSpiderCheck = Shared.contains(GameData.rawData.spiderLairMonsters, monster.id) | |||
return p.getAreas( | |||
function(area) | |||
return p._isMonsterInArea(monster, area) | |||
end) | |||
end | |||
function p.getDungeonRequirements(frame) | |||
local areaName = frame.args ~= nil and frame.args[1] or frame | |||
local area = p.getArea(areaName) | |||
if area == nil then | |||
return Shared.printError('No area named "' .. areaName .. '" exists in the data module') | |||
end | |||
local result = p._getAreaStat(area, 'requirements') | |||
if result ~= '' then | |||
result = "\r\n|-\r\n|'''Requirements:'''<br/>"..result | |||
end | |||
return result | |||
end | end | ||
function p. | function p.getAreaPassives(frame) | ||
local areaName = frame.args ~= nil and frame.args[1] or frame | |||
local area = p.getArea(areaName) | |||
if area == nil then | |||
if Shared. | return Shared.printError('No area named "' .. areaName .. '" exists in the data module') | ||
end | |||
local bossPassives = nil | |||
local nonBossPassives = nil | |||
if area.eventID ~= nil and area.eventID ~= '' then -- currently just Impending Darkness Event | |||
local event = GameData.getEntityByID('combatEvents', area.eventID) | |||
bossPassives = event.bossPassives | |||
-- nonBossPassives = event.enemyPassives -- melvorF:ControlledAffliction is missing from GameData | |||
else | |||
bossPassives = area.bossOnlyPassives -- Strongholds only | |||
nonBossPassives = area.nonBossPassives -- Dungeons only | |||
end | |||
local result = '' | |||
if type(nonBossPassives) == 'table' and not Shared.tableIsEmpty(nonBossPassives) then | |||
result = result .. '\r\n===Non-Boss Monster Passives===' | |||
for i, passiveID in ipairs(nonBossPassives) do | |||
local passive = p.getPassiveByID(passiveID) | |||
result = result .. '\r\n* ' .. passive.name .. '\r\n** ' .. Constants.getDescription(passive.customDescription, passive.modifiers) | |||
end | |||
end | end | ||
if type(bossPassives) == 'table' and not Shared.tableIsEmpty(bossPassives) then | |||
result = result .. '\r\n===Boss Monster Passives===' | |||
for i, passiveID in ipairs(bossPassives) do | |||
local passive = p.getPassiveByID(passiveID) | |||
result = result .. '\r\n* ' .. passive.name .. '\r\n** ' .. Constants.getDescription(passive.customDescription, passive.modifiers) | |||
end | |||
end | end | ||
if type(area.tiers) == 'table' and not Shared.tableIsEmpty(area.tiers) then | |||
result = result .. '\r\n===Stronghold Tier Passives===' | |||
for tierName, tierData in pairs(area.tiers) do | |||
result = result .. '\r\n* ' .. tierName .. ' Tier' | |||
for i, passiveID in ipairs(tierData.passives) do | |||
local passive = p.getPassiveByID(passiveID) | |||
result = result .. '\r\n** ' .. passive.name .. '\r\n*** ' .. Constants.getDescription(passive.customDescription, passive.modifiers) | |||
end | |||
end | |||
end | |||
return result | |||
end | |||
function p.getPassiveByID(ID) | |||
return GameData.getEntityByID('combatPassives', ID) | |||
end | end | ||
return p | return p |
Latest revision as of 00:35, 2 November 2024
Data is pulled from Module:GameData/data
NOTE: Some tables are in Module:CombatAreas/AreaTables to prevent loop from referencing Monsters
--NOTE: Some tables are in Module:CombatAreas/AreaTables to prevent loop from referencing Monsters
local p = {}
local Constants = require('Module:Constants')
local Shared = require('Module:Shared')
local GameData = require('Module:GameData')
local Common = require('Module:Common')
local Icons = require('Module:Icons')
local areaMap = {
["combat"] = 'combatAreas',
["dungeon"] = 'dungeons',
["slayer"] = 'slayerAreas',
["depth"] = 'abyssDepths',
["stronghold"] = 'strongholds'
}
function p.getArea(name)
--There are three types of areas but the lists are pretty short so looping all of them isn't a real issue
for k, areaType in pairs(areaMap) do
local area = GameData.getEntityByName(areaType, name)
if area ~= nil then
return area
end
end
end
function p.getAreaByID(id, areaType)
for aType, areaKey in pairs(areaMap) do
if areaType == nil or areaType == aType then
local area = GameData.getEntityByID(areaKey, id)
if area ~= nil then
return area
end
end
end
end
function p.getAreaFilterType(name, type)
local areaType = areaMap[type]
if areaType ~= nil then
return GameData.getEntityByName(areaType, name)
end
end
function p.getAreas(checkFunc)
local resultArray = nil
for i, areaType in pairs(areaMap) do
local areas = GameData.getEntities(areaType, checkFunc)
if resultArray == nil then
resultArray = areas
else
for k, area in ipairs(areas) do
table.insert(resultArray, area)
end
end
end
if resultArray == nil then
resultArray = {}
end
return resultArray
end
--Returns the expansion icon for the area if it has one
function p.getExpansionIcon(frame)
local areaName = frame.args ~= nil and frame.args[1] or frame
local area = p.getArea(areaName)
if area == nil then
return Shared.printError('No area named "' .. areaName .. '" exists in the data module')
end
return Icons.getExpansionIcon(area.id)
end
function p._getAreaRequirements(area)
local resultArray = {}
if area.entryRequirements ~= nil then
local reqText = Common.getRequirementString(area.entryRequirements)
if reqText ~= nil then
table.insert(resultArray, reqText)
end
end
if area.unlockRequirement ~= nil then
-- Avoid repeating the same requirements twice, can happen for some dungeons e.g. Impending Darkness
if area.entryRequirements == nil or mw.dumpObject(area.unlockRequirement) ~= mw.dumpObject(area.entryRequirements) then
local reqText = Common.getRequirementString(area.unlockRequirement)
if reqText ~= nil then
table.insert(resultArray, reqText)
end
end
end
return table.concat(resultArray, '<br/>')
end
function p.getAreaRequirementsForBox(frame)
--Returns infobox formatting for requirements, or returns nothing if there are none.
local areaName = frame.args ~= nil and frame.args[1] or frame
local area = p.getArea(areaName)
if area == nil then
return Shared.printError('No area named "' .. areaName .. '" exists in the data module')
end
local reqs = p._getAreaRequirements(area)
if reqs ~= '' then
reqs = "|-\r\n|'''Requirements:'''\r\n"..reqs
end
return reqs
end
function p._getAreaStat(area, statName)
if statName == 'requirements' then
return p._getAreaRequirements(area)
elseif statName == 'areaEffectDesc' then
if area.areaEffect ~= nil then
local descText, subIdx = string.gsub(area.areaEffectDescription, '${effectValue}', area.areaEffect.magnitude or 0)
return descText
else
return 'None'
end
elseif statName == 'difficulty' then
local result = Constants.getDifficultyString(area.difficulty[1])
if area.difficulty[2] ~= nil then
result = result..' - '..Constants.getDifficultyString(area.difficulty[2])
end
return result
end
return area[statName]
end
function p.getAreaStat(frame)
local areaName = frame.args ~= nil and frame.args[1] or frame[1]
local statName = frame.args ~= nil and frame.args[2] or frame[2]
local area = p.getArea(areaName)
if area == nil then
return Shared.printError('No area named "' .. areaName .. '" exists in the data module')
end
return p._getAreaStat(area, statName)
end
function p._isMonsterInArea(monster, area)
return (
Shared.contains(area.monsterIDs, monster.id)
-- Check for Lair of the Spider Queen random spiders
or (
Shared.contains(area.monsterIDs, 'melvorTotH:RandomSpiderLair')
and Shared.contains(GameData.rawData.spiderLairMonsters, monster.id)
)
)
end
function p._getMonsterAreas(monster)
-- Special handling for Lair of the Spider Queen, which has a random list of enemies
local randomSpiderCheck = Shared.contains(GameData.rawData.spiderLairMonsters, monster.id)
return p.getAreas(
function(area)
return p._isMonsterInArea(monster, area)
end)
end
function p.getDungeonRequirements(frame)
local areaName = frame.args ~= nil and frame.args[1] or frame
local area = p.getArea(areaName)
if area == nil then
return Shared.printError('No area named "' .. areaName .. '" exists in the data module')
end
local result = p._getAreaStat(area, 'requirements')
if result ~= '' then
result = "\r\n|-\r\n|'''Requirements:'''<br/>"..result
end
return result
end
function p.getAreaPassives(frame)
local areaName = frame.args ~= nil and frame.args[1] or frame
local area = p.getArea(areaName)
if area == nil then
return Shared.printError('No area named "' .. areaName .. '" exists in the data module')
end
local bossPassives = nil
local nonBossPassives = nil
if area.eventID ~= nil and area.eventID ~= '' then -- currently just Impending Darkness Event
local event = GameData.getEntityByID('combatEvents', area.eventID)
bossPassives = event.bossPassives
-- nonBossPassives = event.enemyPassives -- melvorF:ControlledAffliction is missing from GameData
else
bossPassives = area.bossOnlyPassives -- Strongholds only
nonBossPassives = area.nonBossPassives -- Dungeons only
end
local result = ''
if type(nonBossPassives) == 'table' and not Shared.tableIsEmpty(nonBossPassives) then
result = result .. '\r\n===Non-Boss Monster Passives==='
for i, passiveID in ipairs(nonBossPassives) do
local passive = p.getPassiveByID(passiveID)
result = result .. '\r\n* ' .. passive.name .. '\r\n** ' .. Constants.getDescription(passive.customDescription, passive.modifiers)
end
end
if type(bossPassives) == 'table' and not Shared.tableIsEmpty(bossPassives) then
result = result .. '\r\n===Boss Monster Passives==='
for i, passiveID in ipairs(bossPassives) do
local passive = p.getPassiveByID(passiveID)
result = result .. '\r\n* ' .. passive.name .. '\r\n** ' .. Constants.getDescription(passive.customDescription, passive.modifiers)
end
end
if type(area.tiers) == 'table' and not Shared.tableIsEmpty(area.tiers) then
result = result .. '\r\n===Stronghold Tier Passives==='
for tierName, tierData in pairs(area.tiers) do
result = result .. '\r\n* ' .. tierName .. ' Tier'
for i, passiveID in ipairs(tierData.passives) do
local passive = p.getPassiveByID(passiveID)
result = result .. '\r\n** ' .. passive.name .. '\r\n*** ' .. Constants.getDescription(passive.customDescription, passive.modifiers)
end
end
end
return result
end
function p.getPassiveByID(ID)
return GameData.getEntityByID('combatPassives', ID)
end
return p