Module:Pets

From Melvor Idle
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Data for this page is stored in Module:GameData/data


--This module contains all sorts of functions for getting data on pets

local p = {}

local Shared = require( "Module:Shared" )
local Constants = require('Module:Constants')
local GameData = require('Module:GameData')
local Icons = require('Module:Icons')

local areaDataKeys = { 'combatAreas', 'dungeons', 'slayerAreas' }
-- Compute combat pet sources once for use later
local function getCombatPetSources()
	local result = {}
	for _, key in ipairs(areaDataKeys) do
		local areas = GameData.getEntities(key, function(area) return area.pet ~= nil end)
		for i, area in ipairs(areas) do
			result[area.pet.petID] = {
				id = area.id,
				name = area.name,
				type = area.type,
				weight = area.pet.weight,
				fixedChance = (area.fixedPetClears ~= nil and area.fixedPetClears) or area.pet.weight == 1
			}
		end
	end
	return result
end
local CombatPetSources = getCombatPetSources()

function p.getPetByID(ID)
	return GameData.getEntityByID('pets', ID)
end

function p.getPet(name)
	return GameData.getEntityByName('pets', Shared.fixPagename(name))
end

function p.getPets(checkFunc)
	return GameData.getEntities('pets', checkFunc)
end

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

function p._getPetSource(pet)
	local skillID = p._getPetSkill(pet)
	if skillID ~= nil then
		local skillName = Constants.getSkillName(skillID)
		return { id = skillID, name = skillName, type = 'skill' }
	elseif CombatPetSources ~= nil then
		return CombatPetSources[pet.id]
	end
end

function p._getPetSourceText(pet)
	local sourceOverrides = {
		-- useIcon: true if Source has an associated icon, false otherwise
		['Ripper the Reindeer'] = { text = '[[Events#Christmas Event 2020|Christmas Event 2020]]', useIcon = false },
		['Festive Chio'] = { text = '[[Holiday Event 2021]]', useIcon = false },
		['Festive Cool Rock'] = { text = '[[Holiday Event 2021]]', useIcon = false },
		['Jerry the Giraffe'] = { text = '[[Golbin Raid|Golbin Raid Shop]]', useIcon = false },
		['Preston the Platypus'] = { text = '[[Golbin Raid|Golbin Raid Shop]]', useIcon = false },
		['Ty'] = { text = 'Mastery', useIcon = true },
		['Golden Golbin'] = { text = Icons.Icon({'Golbin', type='monster'}) .. ' kills', useIcon = false},
		['Saki'] = { text = 'Mastery', useIcon = true }
	}
	local petSourceText = nil
	local iconType = nil
	local useIcon = true
	local override = sourceOverrides[pet.name]
	if override ~= nil then
		petSourceText = override.text
		if override.useIcon ~= nil then
			useIcon = override.useIcon
		end
	end

	if petSourceText == nil then
		local petSource = p._getPetSource(pet)
		if petSource ~= nil then
			iconType = (petSource.type == 'slayerArea' and 'combatArea') or petSource.type
			petSourceText = petSource.name
		else
			useIcon = false
			petSourceText = ''
		end
	end

	if useIcon then
		return Icons.Icon({petSourceText, type=iconType})
	else
		return petSourceText
	end
end

function p._getPetEffect(pet)
	local modKeys = {'modifiers', 'enemyModifiers'}
	local effects = {}
	for i, key in ipairs(modKeys) do
		if pet[key] ~= nil and not Shared.tableIsEmpty(pet[key]) then
			for effectName, effectValue in pairs(pet[key]) do
				local preText = (key == 'enemyModifiers' and 'All enemies have: ' or '')
				table.insert(effects, preText .. Constants._getModifierText(effectName, effectValue, false))
			end
		end
	end
	if Shared.tableIsEmpty(effects) then
		return 'None'
	else
		return table.concat(effects, '<br/>')
	end
end

function p._getPetChance(pet)
	local source = p._getPetSource(pet)
	if source ~= nil and source.weight ~= nil then
		-- Pet is from a dungeon or combat/slayer area
		if source.fixedChance then
			return 'Guaranteed after ' .. Shared.formatnum(source.weight) .. (source.weight == 1 and ' clear' or ' clears')
		else
			return '1 in ' .. Shared.formatnum(source.weight) .. ' (' .. Shared.round(100 / source.weight, 2, 2) .. '%)'
		end
	else
		-- Skill pet or other
		return 'See: [[Pets#Acquiring Pets|Acquiring Pets]]'
	end
end

function p._getPetSkill(pet)
	local skillOverrides = {
		['melvorD:Ty'] = nil,
		['melvorF:Mark'] = 'melvorD:Summoning'
	}

	if skillOverrides[pet.id] ~= nil then
		return skillOverrides[pet.id]
	else
		return pet.skillID
	end
end

function p._getPetTable(pets)
	if type(pets) ~= 'table' or Shared.tableIsEmpty(pets) then
		return nil
	end

	local resultPart = {}
	table.insert(resultPart, '{| class="wikitable"\r\n!Pet!!Name!!Effect')

	for i, pet in ipairs(pets) do
		table.insert(resultPart, '|-')
		table.insert(resultPart, '|style="text-align: center;"|' .. Icons.Icon({pet.name, type='pet', size=60, notext=true}))
		table.insert(resultPart, '|' .. Icons.getExpansionIcon(pet.id) .. Icons.Icon({pet.name, type='pet', noicon=true}))
		table.insert(resultPart, '| ' .. p._getPetEffect(pet))
	end
	table.insert(resultPart, '|}')

	return table.concat(resultPart, '\r\n')
end

function p.getPetTableBySkill(frame)
	local skillName = frame.args ~= nil and frame.args[1] or frame
	local skillID = Constants.getSkillID(skillName)

	if skillID == nil then
		return ''
	else
		local pets = p.getPets(function(pet) return p._getPetSkill(pet) == skillID end)
		if pets == nil or Shared.tableIsEmpty(pets) then
			return ''
		else
			return p._getPetTable(pets)
		end
	end
end

function p.getPetSidebar(frame)
	local args = frame.args ~= nil and frame.args or frame
	local result = nil
	local name = (args.name ~= nil and args.name ~= '') and args.name or args[1]
	local pet = p.getPet(name)
	if pet == nil then
		return 'ERROR: Could not find pet with name ' .. (name or 'Unknown') .. '[[Category:Pages with script errros]]'
	end
	local effect = (args.effect ~= nil and args.effect ~= '') and args.effect or p._getPetEffect(pet)
	local completionReq = (pet.ignoreCompletion ~= nil and pet.ignoreCompletion) and 'No' or 'Yes'
	local dropChance = p._getPetChance(pet)

	result = '{| class="wikitable infobox"\r\n|-\r\n'
	result = result..'! ' .. Icons.getExpansionIcon(pet.id) .. name .. '\r\n|-\r\n| '
	result = result..'style="text-align: center;"|' .. Icons.Icon({name, type='pet', size='250', notext=true})
	result = result.."\r\n|-\r\n|'''Pet ID:''' "..pet.id
	result = result.."\r\n|-\r\n|'''Source:''' "..p._getPetSourceText(pet)
	if dropChance ~= nil then
		result = result.."\r\n|-\r\n|'''Drop Chance:''' "..dropChance
	end
	result = result.."\r\n|-\r\n| style =\"width: 250px;\"|'''Effect:''' "..effect
	result = result .. "\r\n|-\r\n|'''Part of 100% Completion:''' " .. completionReq .. "\r\n|}"

	return result
end

function p.getPetPageTable()
	local result = ''

	result = '{|class="wikitable sortable lighttable stickyHeader"'
	result = result..'\r\n|- class="headerRow-0"\r\n! colspan="2"| Pet !! Acquired From !! Effect'

	for i, thisPet in ipairs(GameData.rawData.pets) do
		result = result..'\r\n|-\r\n|class="table-img" data-sort-value="' .. thisPet.name .. '"| ' .. Icons.Icon({thisPet.name, size='60', type='pet', notext=true})
		result = result..'||' .. Icons.getExpansionIcon(thisPet.id) ..Icons.Icon({thisPet.name, type='pet', noicon=true})
		result = result..'||'..p._getPetSourceText(thisPet)
		result = result..'||'..p._getPetEffect(thisPet)
	end
	result = result..'\r\n|}'

	return result
end

function p.getDungeonBoxPetText(frame)
	local dungeonName = frame.args ~= nil and frame.args[1] or frame
	local dung = nil
	for i, key in ipairs(areaDataKeys) do
		dung = GameData.getEntityByName(key, dungeonName)
		if dung ~= nil then
			break
		end
	end
	if dung == nil then
		return 'ERROR: Invalid dungeon name '..dungeonName..'[[Category:Pages with script errors]]'
	end

	if dung.pet ~= nil then
		local pet = p.getPetByID(dung.pet.petID)
		if pet ~= nil then
			local result = "\r\n|-\r\n|'''[[Pets#Boss Pets|Pet]]:'''<br/>"
			result = result..Icons.Icon({pet.name, type='pet'})
			result = result.."\r\n|-\r\n|'''Pet Drop Chance:'''<br/>"..p._getPetChance(pet)
			return result
		end
	end
end

-- TODO Move to Module:Navboxes
function p.getPetNavbox()
	local resultPart = {}
	table.insert(resultPart, '{| class="wikitable" style="margin:auto; text-align:center; clear:both; width: 100%"')
	table.insert(resultPart, '\r\n|-\r\n!colspan="2"|[[Pets]]')

	local petList = {
		["skill"] = {},
		["boss"] = {},
		["other"] = {}
	}
	local skillPetList = {}
	local bossPetList = {}
	local otherPetList = {}
	for i, petData in ipairs(GameData.rawData.pets) do
		local source = p._getPetSource(petData)
		local listCat = 'other'
		if type(source) == 'table' and source.type ~= nil then
			if source.type == 'skill' then
				listCat = 'skill'
			elseif source.type == 'dungeon' or source.type == 'slayerArea' then
				listCat = 'boss'
			else
				listCat = 'other'
			end
		end
		table.insert(petList[listCat], petData.name)
	end

	local getIconList =
	function(pets)
		local result = {}
		for i, pet in ipairs(pets) do
			table.insert(result, Icons.Icon({pet, type='pet'}))
		end
		return table.concat(result, ' • ')
	end
	for cat, catData in pairs(petList) do
		table.sort(catData, function(a, b) return a < b end)
		table.insert(resultPart, '\r\n|-\r\n!' .. Shared.titleCase(cat) .. ' Pets\r\n|' .. getIconList(catData))
	end
	table.insert(resultPart, '\r\n|}')
	return table.concat(resultPart)
end

return p