Module:CombatAreas: Difference between revisions

From Melvor Idle
(Use tabs instead of spaces for indentation; getMonsterAreas: Remove check for ID 1/Hill Giants - Game data no longer flags ITM afflicted monsters in this way)
(_getAreaRequirements: Resolve cases where requirement text returned could contain empty lines)
 
(8 intermediate revisions by 2 users not shown)
Line 1: Line 1:
--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 p = {}
local AreaData = mw.loadData('Module:CombatAreas/data')


local Constants = require('Module: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')
local Items = require('Module:Items')
local Shop = require('Module:Shop')
p.eventData = AreaData.event


function processArea(area, index, type)
local areaMap = {
local result = Shared.clone(area)
["combat"] = 'combatAreas',
result.id = index - 1
["dungeon"] = 'dungeons',
if result.name == nil then
["slayer"] = 'slayerAreas'
result.name = result.areaName
}
end
result.type = type
return result
end


function p.getArea(name)
function p.getArea(name)
local result = nil
--There are three types of areas but the lists are pretty short so looping all of them isn't a real issue
--There are three types of areas but the lists are pretty short so looping all of them isn't a real issue
for i, area in pairs(AreaData.combatAreas) do
for k, areaType in pairs(areaMap) do
if area.name == name then
local area = GameData.getEntityByName(areaType, name)
return processArea(area, i, 'combat')
if area ~= nil then
return area
end
end
end
end
end


for i, area in pairs(AreaData.slayerAreas) do
function p.getAreaByID(id, type)
if area.name == name then
local areaType = areaMap[type]
return processArea(area, i, 'slayer')
if areaType ~= nil then
end
return GameData.getEntityByID(areaType, id)
end
end
for i, area in pairs(AreaData.dungeons) do
if area.name == name then
return processArea(area, i, 'dungeon')
end
end
return nil
end
function p.getAreaByID(type, id)
if type == 'dungeon' then type = 'dungeons'
elseif type == 'combat' then type = 'combatAreas'
elseif type == 'slayer' then type = 'slayerAreas' end
return processArea(AreaData[type][id + 1], id + 1)
end
end


function p.getAreaFilterType(type, name)
function p.getAreaFilterType(name, type)
local areaName = nil
local areaType = areaMap[type]
if type == 'dungeon' then areas = AreaData.dungeons
if areaType ~= nil then
elseif type == 'combat' then areas = AreaData.combatAreas
return GameData.getEntityByName(areaType, name)
elseif type == 'slayer' then areas = AreaData.slayerAreas
else return nil end
 
for i, area in pairs(areas) do
if type == 'dungeon' then areaName = area.name
else areaName = area.areaName end
 
if areaName == name then
return processArea(area, i, type)
end
end
end
return nil
end
end


function p.getAreas(checkFunc)
function p.getAreas(checkFunc)
local resultArray = {}
local resultArray = nil


for i, area in Shared.skpairs(AreaData.combatAreas) do
for i, areaType in pairs(areaMap) do
local temp = processArea(area, i, 'combat')
local areas = GameData.getEntities(areaType, checkFunc)
if checkFunc(temp) then
if resultArray == nil then
table.insert(resultArray, temp)
resultArray = areas
else
for k, area in ipairs(areas) do
table.insert(resultArray, area)
end
end
end
end
end
for i, area in Shared.skpairs(AreaData.slayerAreas) do
if resultArray == nil then
local temp = processArea(area, i, 'slayer')
resultArray = {}
if checkFunc(temp) then
table.insert(resultArray, temp)
end
end
for i, area in Shared.skpairs(AreaData.dungeons) do
local temp = processArea(area, i, 'dungeon')
if checkFunc(temp) then
table.insert(resultArray, temp)
end
end
end


return resultArray
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
end


function p._getAreaRequirements(area)
function p._getAreaRequirements(area)
local result = ''
local resultArray = {}
local resultArray = {}
local addReqsToArray = function(reqArray, requirements)
if area.entryRequirements ~= nil then
for i, reqDetails in Shared.skpairs(requirements) do
local reqText = Common.getRequirementString(area.entryRequirements)
if reqDetails.type == 'Level' then
if reqText ~= nil then
for j, lvlDetails in Shared.skpairs(reqDetails.levels) do
table.insert(resultArray, reqText)
local skill = Constants.getSkillName(lvlDetails.skill)
table.insert(reqArray, Icons._SkillReq(skill, lvlDetails.level))
end
elseif reqDetails.type == 'SlayerItem' then
local item = Items.getItemByID(reqDetails.itemID)
table.insert(reqArray, Icons.Icon({item.name, type='item'})..' Equipped')
elseif reqDetails.type == 'Dungeon' then
for j, dungDetails in Shared.skpairs(reqDetails.dungeons) do
local dung = p.getAreaByID('dungeon', dungDetails.dungeonID)
if dungDetails.count > 1 then
table.insert(reqArray, dungDetails.count..'x '..Icons.Icon({dung.name, type='dungeon'})..' Completions')
else
table.insert(reqArray, Icons.Icon({dung.name, type='dungeon'})..' Completed')
end
end
elseif reqDetails.type == 'ShopPurchase' then
local shopPurchase = Shop.processPurchase(reqDetails.category, reqDetails.id)
if shopPurchase ~= nil then
table.insert(reqArray, Shop._getPurchaseIcon({ shopPurchase }) .. ' Purchased')
end
else
table.insert(reqArray, 'ERROR: Unknown requirement type ' .. (reqDetails.type or 'nil') .. '[[Category:Pages with script errors]]')
end
end
end
end
if area.entryRequirements ~= nil then
addReqsToArray(resultArray, area.entryRequirements)
end
end


if area.unlockRequirement ~= nil then
if area.unlockRequirement ~= nil then
-- Ensure this requirement isn't already part of the entry requirements
-- Avoid repeating the same requirements twice, can happen for some dungeons e.g. Impending Darkness
local addReq = true
if area.entryRequirements == nil or mw.dumpObject(area.unlockRequirement) ~= mw.dumpObject(area.entryRequirements) then
if area.entryRequirements ~= nil then
local reqText = Common.getRequirementString(area.unlockRequirement)
local unlockReqStr = mw.dumpObject(area.unlockRequirement)
if reqText ~= nil then
for i, reqDetails in ipairs(area.entryRequirements) do
table.insert(resultArray, reqText)
-- Using mw.dumpObject() as a lazy way to compare tables
if area.unlockRequirement.type == reqDetails.type and mw.dumpObject(reqDetails) == unlockReqStr then
addReq = false
break
end
end
end
end
end
if addReq then
addReqsToArray(resultArray, { area.unlockRequirement })
end
end
end


result = table.concat(resultArray, '<br/>')
return table.concat(resultArray, '<br/>')
return result
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


Line 160: Line 110:
return p._getAreaRequirements(area)
return p._getAreaRequirements(area)
elseif statName == 'areaEffectDesc' then
elseif statName == 'areaEffectDesc' then
if area.areaEffect ~= nil and area.areaEffect then
if area.areaEffect ~= nil then
local descText, subIdx = string.gsub(area.areaEffectDescription, '${effectValue}', area.areaEffectValue or 0)
local descText, subIdx = string.gsub(area.areaEffectDescription, '${effectValue}', area.areaEffect.magnitude or 0)
return descText
return descText
else
else
Line 182: Line 132:
local area = p.getArea(areaName)
local area = p.getArea(areaName)
if area == nil then
if area == nil then
return "ERROR: Could not find an area named "..areaName
return Shared.printError('No area named "' .. areaName .. '" exists in the data module')
end
end


Line 189: Line 139:


function p.getMonsterAreas(monsterID)
function p.getMonsterAreas(monsterID)
local areaArray = {}
-- Special handling for Lair of the Spider Queen, which has a random list of enemies
--There are three types of areas but the lists are pretty short so looping all of them isn't a real issue
local randomSpiderCheck = Shared.contains(GameData.rawData.spiderLairMonsters, monsterID)
for i, area in pairs(AreaData.combatAreas) do
return p.getAreas(
if Shared.contains(area.monsters, monsterID) then
function(area)
table.insert(areaArray, processArea(area, i, 'combat'))
return Shared.contains(area.monsterIDs, monsterID) or
end
(randomSpiderCheck and Shared.contains(area.monsterIDs, 'melvorTotH:RandomSpiderLair'))
end
end)
 
for i, area in pairs(AreaData.slayerAreas) do
if Shared.contains(area.monsters, monsterID) then
table.insert(areaArray, processArea(area, i, 'slayer'))
end
end
 
for i, area in pairs(AreaData.dungeons) do
if Shared.contains(area.monsters, monsterID) then
table.insert(areaArray, processArea(area, i, 'dungeon'))
end
end
 
return areaArray
end
end


Line 216: Line 152:
local area = p.getArea(areaName)
local area = p.getArea(areaName)
if area == nil then
if area == nil then
return "ERROR: Could not find an area named "..areaName
return Shared.printError('No area named "' .. areaName .. '" exists in the data module')
end
end



Latest revision as of 21:58, 6 October 2023

Data is pulled from Module:GameData/data


--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'
}

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, type)
	local areaType = areaMap[type]
	if areaType ~= nil then
		return GameData.getEntityByID(areaType, id)
	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.getMonsterAreas(monsterID)
	-- Special handling for Lair of the Spider Queen, which has a random list of enemies
	local randomSpiderCheck = Shared.contains(GameData.rawData.spiderLairMonsters, monsterID)
	return p.getAreas(
		function(area)
			return Shared.contains(area.monsterIDs, monsterID) or
				(randomSpiderCheck and Shared.contains(area.monsterIDs, 'melvorTotH:RandomSpiderLair'))
		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

return p