Module:CombatAreas: Difference between revisions

From Melvor Idle
(Expose eventData for use in other modules)
(_getAreaRequirements: Crude attempt to prevent the same requirement appearing twice)
Line 98: Line 98:


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


  if area.unlockRequirement ~= nil then
if area.entryRequirements ~= nil then
    addReqsToArray(resultArray, { area.unlockRequirement })
addReqsToArray(resultArray, area.entryRequirements)
  end
end


  result = table.concat(resultArray, '<br/>')
if area.unlockRequirement ~= nil then
  return result
-- Ensure this requirement isn't already part of the entry requirements
local addReq = true
if area.entryRequirements ~= nil then
local unlockReqStr = mw.dumpObject(area.unlockRequirement)
for i, reqDetails in ipairs(area.entryRequirements) do
-- 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
if addReq then
addReqsToArray(resultArray, { area.unlockRequirement })
end
end
 
result = table.concat(resultArray, '<br/>')
return result
end
end



Revision as of 21:57, 2 January 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 AreaData = mw.loadData('Module:CombatAreas/data')

local Constants = require('Module:Constants')
local Shared = require('Module:Shared')
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 result = Shared.clone(area)
  result.id = index - 1
  if result.name == nil then
    result.name = result.areaName
  end
  result.type = type
  return result
end

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
  for i, area in pairs(AreaData.combatAreas) do
    if area.name == name then
      return processArea(area, i, 'combat')
    end
  end

  for i, area in pairs(AreaData.slayerAreas) do
    if area.name == name then
      return processArea(area, i, 'slayer')
    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

function p.getAreaFilterType(type, name)
  local areaName = nil
  if type == 'dungeon' then areas = AreaData.dungeons
  elseif type == 'combat' then areas = AreaData.combatAreas
  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

  return nil
end

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

  for i, area in Shared.skpairs(AreaData.combatAreas) do
    local temp = processArea(area, i, 'combat')
    if checkFunc(temp) then
      table.insert(resultArray, temp)
    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
end

function p._getAreaRequirements(area)
	local result = ''
	local resultArray = {}
	local addReqsToArray = function(reqArray, requirements)
		for i, reqDetails in Shared.skpairs(requirements) do
			if reqDetails.type == 'Level' then
				for j, lvlDetails in Shared.skpairs(reqDetails.levels) do
					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

	if area.entryRequirements ~= nil then
		addReqsToArray(resultArray, area.entryRequirements)
	end

	if area.unlockRequirement ~= nil then
		-- Ensure this requirement isn't already part of the entry requirements
		local addReq = true
		if area.entryRequirements ~= nil then
			local unlockReqStr = mw.dumpObject(area.unlockRequirement)
			for i, reqDetails in ipairs(area.entryRequirements) do
				-- 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
		if addReq then
			addReqsToArray(resultArray, { area.unlockRequirement })
		end
	end

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

function p._getAreaStat(area, statName)
  if statName == 'requirements' then
    return p._getAreaRequirements(area)
  elseif statName == 'areaEffectDesc' then
    if area.areaEffect ~= nil and area.areaEffect then
      local descText, subIdx = string.gsub(area.areaEffectDescription, '${effectValue}', area.areaEffectValue 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)
  local areaArray = {}
  --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
    if Shared.contains(area.monsters, monsterID) then
      table.insert(areaArray, processArea(area, i, 'combat'))
    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

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