Module:CombatAreas: Difference between revisions

From Melvor Idle
(Formatting changes)
(getExpansionIcon: Implement)
(21 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
local p = {}
local p = {}


local Constants = mw.loadData('Module:Constants/data')
local Constants = require('Module:Constants')
local AreaData = mw.loadData('Module:CombatAreas/data')
 
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
end


  return nil
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.getAreaByID(type, id)
--Returns the expansion icon for the area if it has one
  if type == 'dungeon' then type = 'dungeons'
function p.getExpansionIcon(frame)
  elseif type == 'combat' then type = 'combatAreas'
local areaName = frame.args ~= nil and frame.args[1] or frame
  elseif type == 'slayer' then type = 'slayerAreas' end
local area = p.getArea(areaName)
  return processArea(AreaData[type][id + 1], id + 1)
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
end


function p.getAreaFilterType(type, name)
function p._getAreaRequirements(area)
  local areaName = nil
local resultArray = {}
  if type == 'dungeon' then areas = AreaData.dungeons
local addReqsToArray = function(reqArray, requirements)
  elseif type == 'combat' then areas = AreaData.combatAreas
for i, reqDetails in ipairs(requirements) do
  elseif type == 'slayer' then areas = AreaData.slayerAreas
if reqDetails.type == 'SkillLevel' then
  else return nil end
                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


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


    if areaName == name then
if area.unlockRequirement ~= nil then
      return processArea(area, i, type)
-- Avoid repeating the same requirements twice, can happen for some dungeons e.g. Impending Darkness
    end
if area.entryRequirements == nil or mw.dumpObject(area.unlockRequirement) ~= mw.dumpObject(area.entryRequirements) then
  end
        addReqsToArray(resultArray, area.unlockRequirement)
        end
end


  return nil
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
      return Icons.Icon({dung.name, type='dungeon'})..' Completed'
result = result..' - '..Constants.getDifficultyString(area.difficulty[2])
    else
end
      return ''
return result
    end
end
  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
 
  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


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