Module:CombatAreas: Difference between revisions

From Melvor Idle
(Added p.getAreas so I can call it in CombatAreas/Tables)
(getExpansionIcon: Implement)
(14 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 Icons = require('Module:Icons')
local Icons = require('Module:Icons')
local Items = require('Module:Items')
local Items = require('Module:Items')
local Shop = require('Module:Shop')


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 k, areaType in pairs(areaMap) do
  for i, area in pairs(AreaData.combatAreas) do
        local area = GameData.getEntityByName(areaType, name)
    if area.areaName == name then
        if area ~= nil then
      return processArea(area, i, 'combat')
            return area
        end
     end
     end
  end
end


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


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


function p.getAreaByID(type, id)
function p.getAreas(checkFunc)
  if type == 'dungeon' then type = 'dungeons'
local resultArray = nil
  elseif type == 'combat' then type = 'combatAreas'
  elseif type == 'slayer' then type = 'slayerAreas' end
  return processArea(AreaData[type][id + 1], id + 1)
end


function p.getAreaFilterType(type, name)
    for i, areaType in pairs(areaMap) do
  local areaName = nil
        local areas = GameData.getEntities(areaType, checkFunc)
  if type == 'dungeon' then areas = AreaData.dungeons
        if resultArray == nil then
  elseif type == 'combat' then areas = AreaData.combatAreas
            resultArray = areas
  elseif type == 'slayer' then areas = AreaData.slayerAreas
        else
  else return nil end
            for k, area in ipairs(areas) do
                table.insert(resultArray, area)
            end
        end
    end
    if resultArray == nil then
        resultArray = {}
    end


  for i, area in pairs(areas) do
     return resultArray
     if type == 'dungeon' then areaName = area.name
end
    else areaName = area.areaName end


    if areaName == name then
--Returns the expansion icon for the area if it has one
      return processArea(area, i, type)
function p.getExpansionIcon(frame)
    end
local areaName = frame.args ~= nil and frame.args[1] or frame
  end
local area = p.getArea(areaName)
if area == nil then
return "ERROR: No area named " .. areaName .. " exists in the data module[[Category:Pages with script errors]]"
end
return Icons.getExpansionIcon(area.id)
end


  return nil
function p._getAreaRequirements(area)
end
local resultArray = {}
local addReqsToArray = function(reqArray, requirements)
for i, reqDetails in ipairs(requirements) do
if reqDetails.type == 'SkillLevel' then
                local skillName = Constants.getSkillName(reqDetails.skillID)
                if skillName ~= nil then
                    table.insert(reqArray, Icons._SkillReq(skillName, reqDetails.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 == 'DungeonCompletion' then
                local dung = p.getAreaByID(reqDetails.dungeonID, 'dungeon')
                if dung ~= nil then
                    if reqDetails.count > 1 then
                        table.insert(reqArray, Shared.formatnum(reqDetails.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 = GameData.getEntityByID('shopPurchases', reqDetails.purchaseID)
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


function p.getAreas(checkFunc)
if area.entryRequirements ~= nil then
  local resultArray = {}
addReqsToArray(resultArray, area.entryRequirements)
end


  for i, area in Shared.skpairs(AreaData.combatAreas) do
if area.unlockRequirement ~= nil then
    local temp = processArea(area, i, 'combat')
-- Avoid repeating the same requirements twice, can happen for some dungeons e.g. Impending Darkness
    if checkFunc(temp) then
if area.entryRequirements == nil or mw.dumpObject(area.unlockRequirement) ~= mw.dumpObject(area.entryRequirements) then
      table.insert(resultArray, temp)
        addReqsToArray(resultArray, area.unlockRequirement)
    end
        end
  end
end
  for i, area in Shared.skpairs(AreaData.slayerAreas) do
    local temp = processArea(area, i, 'slayer')
    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


  return resultArray
return table.concat(resultArray, '<br/>')
end
end


function p._getAreaStat(area, statName)
function p._getAreaStat(area, statName)
  if statName == 'slayerLevel' then
if statName == 'requirements' then
    return Icons._SkillReq('Slayer', area.slayerLevel)
return p._getAreaRequirements(area)
  elseif statName == 'slayerItem' then
elseif statName == 'areaEffectDesc' then
    if area.slayerItem ~= nil and area.slayerItem > 0 then
if area.areaEffect ~= nil then
      local slayItem = Items.getItemByID(area.slayerItem)
local descText, subIdx = string.gsub(area.areaEffectDescription, '${effectValue}', area.areaEffect.magnitude or 0)
      return Icons.Icon({slayItem.name, type='item'})
return descText
    else
else
      return 'None'
return 'None'
    end
end
  elseif statName == 'dungeonReq' then
elseif statName == 'difficulty' then
    if area.requiresCompletion ~= nil and area.requiresCompletion >= 0 then
local result = Constants.getDifficultyString(area.difficulty[1])
      local dung = p.getAreaByID('dungeon', area.requiresCompletion)
if area.difficulty[2] ~= nil then
      local compCount = area.requiresCompletionCount ~= nil and area.requiresCompletionCount or 1
result = result..' - '..Constants.getDifficultyString(area.difficulty[2])
      if compCount > 1 then
end
        return compCount..'x '..Icons.Icon({dung.name, type='dungeon'})..' Completions'
return result
      else
end
        return Icons.Icon({dung.name, type='dungeon'})..' Completed'
      end
    else
      return ''
    end
  elseif statName == 'areaEffectDesc' then
    if area.areaEffect ~= nil and area.areaEffect then
      return area.areaEffectDescription
    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]
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 areaName = frame.args ~= nil and frame.args[1] or frame[1]
  local statName = frame.args ~= nil and frame.args[2] or frame[2]
local statName = frame.args ~= nil and frame.args[2] or frame[2]
  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 "ERROR: Could not find an area named "..areaName
  end
end


  return p._getAreaStat(area, statName)
return p._getAreaStat(area, statName)
end
end


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
 
  --Hill Giants specifically ignore dungeons to prevent the issue with Into the Mist incorrectly being listed.
  if monsterID ~= 1 then
    for i, area in pairs(AreaData.dungeons) do
      if Shared.contains(area.monsters, monsterID) then
        table.insert(areaArray, processArea(area, i, 'dungeon'))
      end
    end
  end
  return areaArray
end
end


function p.getDungeonRequirements(frame)
function p.getDungeonRequirements(frame)
  local areaName = frame.args ~= nil and frame.args[1] or frame
local areaName = frame.args ~= nil and frame.args[1] or frame
  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 "ERROR: Could not find an area named "..areaName
  end
end


  local result = p._getAreaStat(area, 'dungeonReq')
local result = p._getAreaStat(area, 'requirements')
  if result ~= '' then
if result ~= '' then
    result = "\r\n|-\r\n|'''Requirements:'''<br/>"..result
result = "\r\n|-\r\n|'''Requirements:'''<br/>"..result
  end
end
  return result
return result
end
end


return p
return p

Revision as of 22:18, 8 November 2022

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 Icons = require('Module:Icons')
local Items = require('Module:Items')
local Shop = require('Module:Shop')

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 "ERROR: No area named " .. areaName .. " exists in the data module[[Category:Pages with script errors]]"
	end
	
	return Icons.getExpansionIcon(area.id)
end

function p._getAreaRequirements(area)
	local resultArray = {}
	local addReqsToArray = function(reqArray, requirements)
		for i, reqDetails in ipairs(requirements) do
			if reqDetails.type == 'SkillLevel' then
                local skillName = Constants.getSkillName(reqDetails.skillID)
                if skillName ~= nil then
                    table.insert(reqArray, Icons._SkillReq(skillName, reqDetails.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 == 'DungeonCompletion' then
                local dung = p.getAreaByID(reqDetails.dungeonID, 'dungeon')
                if dung ~= nil then
                    if reqDetails.count > 1 then
                        table.insert(reqArray, Shared.formatnum(reqDetails.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 = GameData.getEntityByID('shopPurchases', reqDetails.purchaseID)
				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

	if area.entryRequirements ~= nil then
		addReqsToArray(resultArray, area.entryRequirements)
	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
        	addReqsToArray(resultArray, area.unlockRequirement)
        end
	end

	return table.concat(resultArray, '<br/>')
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 "ERROR: Could not find an area named "..areaName
	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 "ERROR: Could not find an area named "..areaName
	end

	local result = p._getAreaStat(area, 'requirements')
	if result ~= '' then
		result = "\r\n|-\r\n|'''Requirements:'''<br/>"..result
	end
	return result
end

return p