Difference between revisions of "Module:CombatAreas"

From Melvor Idle
(Fixed an issue with getting difficulty not working when multiple difficulties were present)
(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)
 
(11 intermediate revisions by 2 users not shown)
Line 8: Line 8:
 
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')
 +
 +
p.eventData = AreaData.event
  
 
function processArea(area, index, type)
 
function processArea(area, index, type)
  local result = Shared.clone(area)
+
local result = Shared.clone(area)
  result.id = index - 1
+
result.id = index - 1
  if result.name == nil then
+
if result.name == nil then
    result.name = result.areaName
+
result.name = result.areaName
  end
+
end
  result.type = type
+
result.type = type
  return result
+
return result
 
end
 
end
  
 
function p.getArea(name)
 
function p.getArea(name)
  local result = nil
+
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 i, area in pairs(AreaData.combatAreas) do
    if area.areaName == name then
+
if area.name == name then
      return processArea(area, i, 'combat')
+
return processArea(area, i, 'combat')
    end
+
end
  end
+
end
  
  for i, area in pairs(AreaData.slayerAreas) do
+
for i, area in pairs(AreaData.slayerAreas) do
    if area.areaName == name then
+
if area.name == name then
      return processArea(area, i, 'slayer')
+
return processArea(area, i, 'slayer')
    end
+
end
  end
+
end
  
  for i, area in pairs(AreaData.dungeons) do
+
for i, area in pairs(AreaData.dungeons) do
    if area.name == name then
+
if area.name == name then
      return processArea(area, i, 'dungeon')
+
return processArea(area, i, 'dungeon')
    end
+
end
  end
+
end
  
  return nil
+
return nil
 
end
 
end
  
 
function p.getAreaByID(type, id)
 
function p.getAreaByID(type, id)
  if type == 'dungeon' then type = 'dungeons'
+
if type == 'dungeon' then type = 'dungeons'
  elseif type == 'combat' then type = 'combatAreas'
+
elseif type == 'combat' then type = 'combatAreas'
  elseif type == 'slayer' then type = 'slayerAreas' end
+
elseif type == 'slayer' then type = 'slayerAreas' end
  return processArea(AreaData[type][id + 1], id + 1)
+
return processArea(AreaData[type][id + 1], id + 1)
 
end
 
end
  
 
function p.getAreaFilterType(type, name)
 
function p.getAreaFilterType(type, name)
  local areaName = nil
+
local areaName = nil
  if type == 'dungeon' then areas = AreaData.dungeons
+
if type == 'dungeon' then areas = AreaData.dungeons
  elseif type == 'combat' then areas = AreaData.combatAreas
+
elseif type == 'combat' then areas = AreaData.combatAreas
  elseif type == 'slayer' then areas = AreaData.slayerAreas  
+
elseif type == 'slayer' then areas = AreaData.slayerAreas  
  else return nil end
+
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
  
  for i, area in pairs(areas) do
+
function p.getAreas(checkFunc)
    if type == 'dungeon' then areaName = area.name
+
local resultArray = {}
    else areaName = area.areaName end
 
  
    if areaName == name then
+
for i, area in Shared.skpairs(AreaData.combatAreas) do
      return processArea(area, i, type)
+
local temp = processArea(area, i, 'combat')
    end
+
if checkFunc(temp) then
  end
+
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 nil
+
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
 
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 and area.areaEffect then
      local slayItem = Items.getItemByID(area.slayerItem)
+
local descText, subIdx = string.gsub(area.areaEffectDescription, '${effectValue}', area.areaEffectValue 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 = {}
+
local areaArray = {}
  --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 i, area in pairs(AreaData.combatAreas) do
    if Shared.contains(area.monsters, monsterID) then
+
if Shared.contains(area.monsters, monsterID) then
      table.insert(areaArray, processArea(area, i, 'combat'))
+
table.insert(areaArray, processArea(area, i, 'combat'))
    end
+
end
  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.slayerAreas) do
+
for i, area in pairs(AreaData.dungeons) do
    if Shared.contains(area.monsters, monsterID) then
+
if Shared.contains(area.monsters, monsterID) then
      table.insert(areaArray, processArea(area, i, 'slayer'))
+
table.insert(areaArray, processArea(area, i, 'dungeon'))
    end
+
end
  end
+
end
  
  --Hill Giants specifically ignore dungeons to prevent the issue with Into the Mist incorrectly being listed.
+
return areaArray
  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

Latest revision as of 23:08, 7 January 2022

Data is pulled from Module:CombatAreas/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

	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

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