Module:CombatAreas: Difference between revisions

From Melvor Idle
(Added p.getMonsterAreas)
(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)
(26 intermediate revisions by 3 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 AreaData = mw.loadData('Module:CombatAreas/data')
local AreaData = mw.loadData('Module:CombatAreas/data')


local Constants = require('Module:Constants')
local Shared = require('Module:Shared')
local Shared = require('Module:Shared')
local Icons = require('Module:Icons')
local Icons = require('Module:Icons')
local Monsters = require('Module:Monsters')
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)
function p.getArea(name)
  local result = nil
local result = nil
  mw.log(name)
--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.name == name then
    if area.areaName == name then
return processArea(area, i, 'combat')
      result = Shared.clone(area)
end
      result.id = i - 1
end
      return result
 
    end
for i, area in pairs(AreaData.slayerAreas) do
  end
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


  for i, area in pairs(AreaData.slayerAreas) do
function p.getAreas(checkFunc)
    if area.areaName == name then
local resultArray = {}
      result = Shared.clone(area)
      result.id = i - 1
      return result
    end
  end


  for i, area in pairs(AreaData.dungeons) do
for i, area in Shared.skpairs(AreaData.combatAreas) do
    if area.name == name then
local temp = processArea(area, i, 'combat')
      result = Shared.clone(area)
if checkFunc(temp) then
      result.type = 'dungeon'
table.insert(resultArray, temp)
      result.id = i - 1
end
      return result
end
    end
for i, area in Shared.skpairs(AreaData.slayerAreas) do
  end
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
end


function p.getMonsterAreas(monsterID)
function p._getAreaRequirements(area)
  local areaArray = {}
local result = ''
  --There are three types of areas but the lists are pretty short so looping all of them isn't a real issue
local resultArray = {}
  for i, area in pairs(AreaData.combatAreas) do
local addReqsToArray = function(reqArray, requirements)
    if Shared.contains(area.monsters, monsterID) then
for i, reqDetails in Shared.skpairs(requirements) do
      result = Shared.clone(area)
if reqDetails.type == 'Level' then
      result.id = i - 1
for j, lvlDetails in Shared.skpairs(reqDetails.levels) do
      table.insert(areaArray, result)
local skill = Constants.getSkillName(lvlDetails.skill)
    end
table.insert(reqArray, Icons._SkillReq(skill, lvlDetails.level))
  end
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


  for i, area in pairs(AreaData.slayerAreas) do
if area.unlockRequirement ~= nil then
    if Shared.contains(area.monsters, monsterID) then
-- Ensure this requirement isn't already part of the entry requirements
      result = Shared.clone(area)
local addReq = true
      result.id = i - 1
if area.entryRequirements ~= nil then
      table.insert(areaArray, result)
local unlockReqStr = mw.dumpObject(area.unlockRequirement)
    end
for i, reqDetails in ipairs(area.entryRequirements) do
  end
-- 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


  for i, area in pairs(AreaData.dungeons) do
result = table.concat(resultArray, '<br/>')
    if Shared.contains(area.monsters, monsterID) then
return result
      result = Shared.clone(area)
      result.type = 'dungeon'
      result.id = i - 1
      table.insert(areaArray, result)
    end
  end
  return areaArray
end
end


function p.getAreaMonsterTable(frame)
function p._getAreaStat(area, statName)
  local areaName = frame.args ~= nil and frame.args[1] or frame
if statName == 'requirements' then
  local area = p.getArea(areaName)
return p._getAreaRequirements(area)
  if area == nil then
elseif statName == 'areaEffectDesc' then
    return "ERROR: Could not find an area named "..areaName
if area.areaEffect ~= nil and area.areaEffect then
  end
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


  if area.type == 'dungeon' then
return area[statName]
    return p.getDungeonMonsterTable(frame)
end
  end


  local tableTxt = '{| class="wikitable sortable"'
function p.getAreaStat(frame)
  tableTxt = tableTxt..'\r\n! Name !! Combat Level !! Hitpoints !! Max Hit !! [[Combat Triangle|Combat Style]]'
local areaName = frame.args ~= nil and frame.args[1] or frame[1]
  for i, monsterID in pairs(area.monsters) do
local statName = frame.args ~= nil and frame.args[2] or frame[2]
    local monster = Monsters.getMonsterByID(monsterID)
local area = p.getArea(areaName)
    tableTxt = tableTxt..'\r\n|-\r\n|'..Icons.Icon({monster.name, type='monster'})
if area == nil then
    tableTxt = tableTxt..'||'..Monsters.getMonsterCombatLevel(monster.name)
return "ERROR: Could not find an area named "..areaName
    tableTxt = tableTxt..'||'..Shared.formatnum(Monsters.getMonsterHP(monster.name))
end
    tableTxt = tableTxt..'||'..Shared.formatnum(Monsters.getMonsterMaxHit(monster.name))
 
    tableTxt = tableTxt..'||'..Monsters.getMonsterStyleIcon({monster.name, nolink='true'})
return p._getAreaStat(area, statName)
  end
  tableTxt = tableTxt..'\r\n|}'
  return tableTxt
end
end


function p.getDungeonMonsterTable(frame)
function p.getMonsterAreas(monsterID)
  local areaName = frame.args ~= nil and frame.args[1] or frame
local areaArray = {}
  local area = p.getArea(areaName)
--There are three types of areas but the lists are pretty short so looping all of them isn't a real issue
  if area == nil then
for i, area in pairs(AreaData.combatAreas) do
    return "ERROR: Could not find a dungeon named "..areaName
if Shared.contains(area.monsters, monsterID) then
  end
table.insert(areaArray, processArea(area, i, 'combat'))
end
end


  --For Dungeons, go through and count how many of each monster are in the dungeon first
for i, area in pairs(AreaData.slayerAreas) do
  local monsterCounts = {}
if Shared.contains(area.monsters, monsterID) then
  for i, monsterID in pairs(area.monsters) do
table.insert(areaArray, processArea(area, i, 'slayer'))
    if monsterCounts[monsterID] == nil then  
end
      monsterCounts[monsterID] = 1
end
    else
 
      monsterCounts[monsterID] = monsterCounts[monsterID] + 1
for i, area in pairs(AreaData.dungeons) do
    end
if Shared.contains(area.monsters, monsterID) then
  end
table.insert(areaArray, processArea(area, i, 'dungeon'))
end
end
 
return areaArray
end


  local usedMonsters = {}
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 tableTxt = '{| class="wikitable sortable"'
local result = p._getAreaStat(area, 'requirements')
  tableTxt = tableTxt..'\r\n! Name !! Combat Level !! Hitpoints !! Max Hit !! [[Combat Triangle|Combat Style]] !! Count'
if result ~= '' then
  for i, monsterID in pairs(area.monsters) do
result = "\r\n|-\r\n|'''Requirements:'''<br/>"..result
    if not Shared.contains(usedMonsters, monsterID) then
end
      local monster = Monsters.getMonsterByID(monsterID)
return result
      local name = monster.name
      if monsterID == 51 then name = 'Spider2' end
      tableTxt = tableTxt..'\r\n|-\r\n|'..Icons.Icon({name, type='monster'})
      tableTxt = tableTxt..'||'..Monsters.getMonsterCombatLevel(name)
      tableTxt = tableTxt..'||'..Shared.formatnum(Monsters.getMonsterHP(name))
      tableTxt = tableTxt..'||'..Shared.formatnum(Monsters.getMonsterMaxHit(name))
      tableTxt = tableTxt..'||'..Monsters.getMonsterStyleIcon({name, nolink='true'})
      tableTxt = tableTxt..'||'..monsterCounts[monsterID]
      table.insert(usedMonsters, monsterID)
    end
  end
  tableTxt = tableTxt..'\r\n|}'
  return tableTxt
end
end


return p
return p

Revision as of 23:08, 7 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

	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