Module:Pets: Difference between revisions

From Melvor Idle
m (TODOs)
(getPetNavbox: Migrate to Module:Navboxes)
 
(65 intermediate revisions by 3 users not shown)
Line 1: Line 1:
--This module contains all sorts of functions for getting data on pets
--This module contains all sorts of functions for getting data on pets
--[[ TODOs
    Add getPetBySkill function
        acquiredBy field will work for all skills but Slayer
        May need to do skill look up by ID
            Ty has skill ID of 0, which is Woodcutting, for some reason
        Or maybe just take the first word
    Use the getPetBySkill function to build pet info table
        Similar to {{SkillCapeInfo}}
--]]


local p = {}
local p = {}
local PetData = mw.loadData('Module:Pets/data')


local Shared = require( "Module:Shared" )
local Shared = require( "Module:Shared" )
local Constants = require('Module:Constants')
local GameData = require('Module:GameData')
local Icons = require('Module:Icons')
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)
function p.getPetByID(ID)
  local result = Shared.clone(PetData.Pets[ID + 1])
return GameData.getEntityByID('pets', ID)
  if result ~= nil then
    result.id = ID
  end
  return result
end
end


function p.getPet(name)
function p.getPet(name)
  local result = nil
return GameData.getEntityByName('pets', Shared.fixPagename(name))
  name = string.gsub(name, "%%27", "'")
end
  name = string.gsub(name, "'", "'")
 
  name = string.gsub(name, "'", "'")
function p.getPets(checkFunc)
  for i, pet in pairs(PetData.Pets) do
return GameData.getEntities('pets', checkFunc)
    local PetName = string.gsub(pet.name, '#', '')
end
    if(name == PetName) then
 
      result = Shared.clone(pet)
--Returns the expansion icon for the pet if it has one
      --Make sure every pet has an id, and account for Lua being 1-index
function p.getExpansionIcon(frame)
      result.id = i - 1
local petName = frame.args ~= nil and frame.args[1] or frame
      break
local pet = p.getPet(petName)
    end
if pet == nil then
  end
return Shared.printError('No pet named "' .. petName .. '" exists in the data module')
  return result
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
end


function p.getPetTable(frame)
function p._getPetChance(pet)
  local petName = frame.args ~= nil and frame.args[1] or frame
local source = p._getPetSource(pet)
  local pet = p.getPet(petName)
if source ~= nil and source.weight ~= nil then
  local result = '{| class="wikitable"\r\n'
-- Pet is from a dungeon or combat/slayer area
  result = result..'!Pet!!Name!!Effect'
if source.fixedChance then
  result = result..'\r\n|-\r\n|'..Icons.Icon({pet.name, type='pet', size='60', notext=true})
return 'Guaranteed after ' .. Shared.formatnum(source.weight) .. (source.weight == 1 and ' clear' or ' clears')
  --result = result..'\r\n|-\r\n|[[File:'..pet.name..'_(pet).png|60px]]'
else
  result = result..'||[['..pet.name..']]||'..pet.description
return '1 in ' .. Shared.formatnum(source.weight) .. ' (' .. Shared.round(100 / source.weight, 2, 2) .. '%)'
  result = result..'\r\n|}'
end
  return result
else
-- Skill pet or other
return 'See: [[Pets#Acquiring Pets|Acquiring Pets]]'
end
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 Shared.printError('No pet named "' .. (name or 'Unknown') .. '" exists in the data module')
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 Shared.printError('No dungeon named "' .. dungeonName .. '" exists in the data module')
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
return p

Latest revision as of 20:41, 15 January 2023

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 Shared.printError('No pet named "' .. petName .. '" exists in the data module')
	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 Shared.printError('No pet named "' .. (name or 'Unknown') .. '" exists in the data module')
	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 Shared.printError('No dungeon named "' .. dungeonName .. '" exists in the data module')
	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

return p