Module:Pet

-- local p = {} -- Basics local loader = require('Module:Loader') local getArgs = require('Module:Arguments').getArgs local data, aliases, skindata = loader.loadData('Module:Pet/Data', 'Module:Pet/Aliases', 'Module:Pet/Skins') local string, table = loader.require('String', 'Table') -- Modules local rarityTier = require('Module:RarityTier') local statModule = require('Module:Statname') local uitext = require('Module:UIText') -- Aliases local colorAliases = require('Module:Color/Aliases') local rarityAliases = require('Module:RarityTier/Aliases') local statAliases = require('Module:Statname/aliases') -- Functions local makeColor = require('Module:Color')._colorTemplates local makeCoins = require('Module:Currency')._coins local makeAbility = require('Module:Ability')._ability local checkType = require('Module:LibraryUtil').checkType local uitextData = require('Module:UIText/Data').conversions local getFormatting = require('Module:UIText').getFormatting

local curtitle = mw.title.getCurrentTitle local pagename = curtitle.prefixedText local fullpagename = curtitle.fullText local reverseConv = table.invert(uitextData)

local function rarityOrder(rarity) return rarityTier._getTier(rarity).order end

function p.getSkinsTemplate local petSkinsTable = {} for petName, skins in pairs(skindata) do		for _,v in ipairs(skins) do			local attrs = string.split(v[2], '%s+') local r = rarityTier._getTier(attrs[1]).name table.remove(attrs,1) local animated, daynight = false, false for _,attr in ipairs(attrs) do				if attr:lower == 'animated' then animated = true elseif attr:lower == 'daynight' then daynight = true end end local suppStr = string.format('%s%s',				animated and getFormatting(r,'This skin is animated!//') or ,				daynight and getFormatting(r,'This skin adapts to the day-night cycle!//') or ) table.push(petSkinsTable, { v[1], petName, r:upper, getFormatting(r), suppStr }) end end return petSkinsTable end

function p.getSkinsList local petSkinsTable = {} for _, petName in ipairs(table.keys(data)) do		local skins = data[petName].skins; if skins then for _,v in ipairs(skins) do table.push(petSkinsTable, v[1]) end end end return petSkinsTable end

function p.getPetList(prepend, append) return table.map(table.keys(data), function(petName)		return (prepend or )..petName..(append or )	end) end

function p.getMysteryTemplate local ls = table.map(table.keys(data), function(petName)		local petData = data[petName]		local stats = {}		for stat, value in pairs(petData.stats) do			if not value.req then				value = tonumber(value[1])				table.push(stats, ('&r%s: &a%s'):format(string.ucfirst(statAliases[stat]), value < 0 and value or '+'..value))			end		end		return { petName, petData.petType, table.concat(stats, '/') }	end) return table.merge(ls, { id = 'Mystery $o Pet' }) end

function p.petStatsTable(frame) local args = getArgs(frame) local pet = args[1] or args["p"] or args["pet"] or (curtitle.namespace == 0 and (fullpagename:find("Pet") and fullpagename or 'ERROR') or 'ERROR') if pet == 'ERROR' then return string.error('Pet name expected, got none') end return frame:preprocess(string.pcall(p._petStatsTable, pet)) end

function p._petStatsTable(pet) local data = mw.loadData('Module:Pet/Data') local aliases = mw.loadData('Module:Pet/Aliases') pet = pet:lower:gsub(' pet', '') pet = aliases[mw.text.trim(pet)] or string.ucfirst(pet) data = data[pet] if not data then error("Unrecognized Pet: "..pet) end --create various variables local rarities = (data.rarities):upper:gsub('[^%a]', '') local stats = data.stats local amounts = data.abilities.amounts and data.abilities.amounts:gsub('[^%d]', '') -- or '112234' local heldItem = data.heldItem if not stats then return error(string.format('Missing pet stats (Pet: %s)', pet), 2) end local tabs = {} for i = 1, #rarities, 1 do       --================================ -- construct the table --================================       -- headers -       local ved_buttons = ' v • e • d' local wikitable = mw.html.create('table'):addClass('wikitable'):css({['width']='100%'}) wikitable:tag('tr') :tag('th'):wikitext('Base Stats ⓘ '):css({['width']='50%'}):done :tag('th'):wikitext('Level 100 '..ved_buttons):css({['width']='50%'}):done :done local rarity = { letter = rarities:sub(i,i) }       rarity.name = rarityTier._getTier(rarity.letter).name rarity.full = rarityAliases[rarity.letter:lower] rarity.num = rarityOrder(rarity.full) local currentAbilityAmount = amounts and amounts:sub(rarity.num, rarity.num) wikitable:tag('tr') -	       -- base stats -           :tag('td'):wikitext(table.concat{                p.constructStats(stats, 'base', rarity.full), --(stats, _type)                p.processAbilities(data.abilities, 'base', rarity.full, currentAbilityAmount), --(ab, type, rarity, amount)                p.processHeldItems(heldItem, 'base', rarity.full), -- (heldItem, type, rarity)            }):done -           -- level 100 stats -           :tag('td'):wikitext(table.concat{                p.constructStats(stats, '100', rarity.full), --(stats, _type)                p.processAbilities(data.abilities, '100', rarity.full, currentAbilityAmount), --(ab, type, rarity, amount)                p.processHeldItems(heldItem, '100', rarity.full), -- (heldItem, type, rarity)            }):done :done -       -- bonus headers -       wikitable:tag('tr') :tag('th'):attr({ colspan=2 }):wikitext('Leveling Bonuses '):done :done wikitable:tag('tr') -	       -- bonus stats -           :tag('td'):attr({ colspan=2 }):wikitext(table.concat{                p.constructStats(stats, 'bonus', rarity.full), --(stats, _type)                p.processAbilities(data.abilities, 'bonus', rarity.full, currentAbilityAmount) --(ab, type, rarity, amount)            }):done tabs[#tabs+1] = table.concat{ '|-|', rarity.name, '=', tostring(rarityTier._link(rarity.full)), ' stats:', tostring(wikitable) } end return table.concat{' ', table.concat(tabs), ' '} end

function p.constructStats(stats, _type, rarity) checkType('constructStats', 1, stats, 'table') checkType('constructStats', 2, _type, {'string', 'nil'}) rarity = rarityAliases[rarity] or rarity local list = {} for key, value in pairs(stats) do   	local base = value.base or value[2] or 0 local lvl = value.level or value.lvl or value.bonus or value[1] reqRarity = value.req and rarityAliases[value.req:lower] or nil if not value.req or rarityOrder(rarity) >= rarityOrder(reqRarity) then local num if _type == '100' then num = base + 100 * lvl elseif _type == 'bonus' then num = lvl else num = base end table.push(list, string.wrapHtml({ tostring(statModule._getStatName(key)), (num < 0 and ': ' or ': +'), num, (_type == 'bonus' and ' per level' or '') }, 'li')) end end return table.concat{ _type == '100' and 'Stats:' or (           _type == 'bonus'             and 'Bonus stats:'            or 'Base stats:'        ), string.wrapHtml(list, 'ul') } end

function p.processVariables(variable, type, pet) -- check for errors if not variable then return end if not variable.color then error(string.format('Variable argument missing (color) (Pet: %s)', pet), 2) end if variable.is_roman then if variable.per_lvl then return type == "tooltip" and getFormatting(variable.color, variable.per_lvl).."&r" or makeColor(variable.color, variable.per_lvl) else return type == "tooltip" and getFormatting(variable.color, variable.base).."&r" or makeColor(variable.color, variable.base) end end -- check for errors again if not variable.per_lvl and variable.per_lvl ~= 0 then return error(string.format('Variable argument missing (per_lvl) (Pet: %s)', pet), 2) end --perform calculations local num if type and tostring(type) == '100' then num = (variable.base or 0) + 100 * variable.per_lvl elseif type and type == 'bonus' then num = variable.per_lvl else num = (variable.base or 0) end if variable.round_to_full then num = math.floor(num) end --add suffix num = tostring(num)..(variable.suffix or '') --colorize return type == "tooltip" and getFormatting(variable.color, num).."&r" or makeColor(variable.color, num) end

function p.processSTAT(str, type) if str:find('STAT_[%u-]+') then str = str:gsub('STAT_([%u-]+)', function(s)			local dt = statModule._getstatdata(s)       	return type == "tooltip" and getFormatting(dt.color, dt.character.." "..dt.name).."&r" or statModule._getStatName(s)        end) end if str:find('STATs_([%u-]+)') then str = str:gsub('STATs_([%u-]+)', function(s)			local dt = statModule._getstatdata(s)       	return type == "tooltip" and getFormatting(dt.color, dt.character.." "..dt.nameShort).."&r" or statModule._getStatName(s, nil, true)        end) end return str end

function p.processRARITY(str, type) if str:find('RARITY_%u+') then str = str:gsub('RARITY_(%u+)', function(s)			local dt = rarityTier._getTier(s)			return type == "tooltip" and getFormatting(dt.color, dt.name).."&r" or rarityTier._link(s)		end) end return str end

function p.replaceCoins(str, type) return str:gsub('COINS', type == "tooltip" and "&6coins" or tostring(makeCoins)) end

-- function p.recursiveGsub(val, t) --    for i = 1,#t,1 do --         val = val:gsub(t[i][1], t[i][2]) --    end --    return val -- end

function p.formatFakeAbility(s, type) checkType('formatFakeAbility', 1, s, 'string') return s:gsub('%{ABILITY%}(.+)%{/ABILITY%}', function(s)		return type == "tooltip" and "&6"..s or makeAbility(s)	end) end

function p.xmlColorConvert(s, type) checkType('xmlColorConvert', 1, s, 'string') return s:gsub(       '(.-)',        function(tag, str, endTag)             tag = string.trim(tag):lower            endTag = string.trim(endTag):lower            mw.log(tag)            if tag and (not endTag or endTag == "")                    then error(string.format('XML color tags syntax error: No closing tag found for tag ', tag), 4)                elseif tag:lower ~= endTag:lower                    then error( string.format(                           'XML color tags syntax error: Expected closing tag for \'\' is \'\', got ',                            tag,                            tag,                            endTag                        ), 4)           end            mw.log(tag)            local c = colorAliases[tag] or reverseConv[tag]            return c and (type == "tooltip" and getFormatting(c, str).."&r" or makeColor(c, str)) or '<'..tag..'>'..str..''        end    ) end

local function processVars(desc, _type, vars) desc = p.xmlColorConvert(desc, _type) desc = p.processSTAT(desc, _type) desc = p.processRARITY(desc, _type) desc = p.replaceCoins(desc, _type) desc = p.formatFakeAbility(desc, _type) if vars then local MAX = 10 -- process double digits first for j = 10, MAX, 1 do			if desc:find('VAR'..tostring(j)) then local subst = p.processVariables(vars[j], _type, pet) desc = subst and desc:gsub('VAR'..tostring(j), subst) or desc end end -- process single digit for j = 1, 9, 1 do			if desc:find('VAR'..tostring(j)) then local subst = p.processVariables(vars[j], _type, pet) desc = subst and desc:gsub('VAR'..tostring(j), subst) or desc end end end -- fullstop handler if _type ~= "tooltip" then if desc:match("%w$") then desc = desc..'.' end else if desc:match(".$") then desc = desc:sub(1,#desc-1) end -- linebreaks handler desc = desc:gsub("", "/") end return desc end

function p.processAbilities(ab, type, rarity, amount) checkType('processAbilities', 1, ab, 'table') checkType('processAbilities', 2, type, 'string') checkType('processAbilities', 3, rarity, 'string') --if not ab.names[ab.amounts] then error(string.format('Missing ability name #%s', amount), 2) end --if not ab.descs[ab.amounts] then error(string.format('Missing ability description #%s', amount), 2) end local list = {} for i=1, amount or table.length(ab.variables[rarity]), 1 do       if type == '100' then desc = processVars(ab.desc[i], type, ab.variables[rarity][i]) table.push(list,                    string.wrapHtml({ makeAbility(ab.name[i]), ' - ', desc }, 'li')           ) elseif type == 'base' then desc = processVars(ab.desc[i], type, ab.variables[rarity][i]) table.push(list,                string.wrapHtml({ makeAbility(ab.name[i]), ' - ', desc }, 'li')           ) elseif type == 'bonus' then desc = processVars(ab.bonus_desc[i] or 'no leveling bonus', type, ab.variables[rarity][i]) table.push(list,               string.wrapHtml({ makeAbility(ab.name[i]), ': ', desc }, 'li')           ) end end return table.concat{ makeAbility('Abilities:'), string.wrapHtml{ list, '', { style = "list-style-type: circle; line-height: inherit;" } }   } end

function p.processHeldItems(heldItem, type, rarity) checkType('processHeldItems', 1, heldItem, 'table', true) checkType('processHeldItems', 2, type, 'string') checkType('processHeldItems', 3, rarity, 'string') local list, desc if heldItem and (type == '100' or type == 'base') and rarity == heldItem.req then desc = processVars(heldItem.desc, type) list = string.wrapHtml(desc, 'li') else return end return table.concat{ makeAbility('Held Item: '..heldItem.name), string.wrapHtml{ list, '', { style = "list-style-type: none; line-height: inherit;" } }   } end

function p.getPetsTemplate return table.merge(table.map(table.keys(data), function(pet) local data = data[pet] if not data then return end if not data.rarities then return end local rarities = (data.rarities):upper:gsub('[^%a]', '') i = #rarities -- highest rarity local rarity = rarityTier._getTier(rarities:sub(i,i)).name if not data.stats then return end local stats = data.stats local statStr = {} for key, value in pairs(stats) do	   	reqRarity = value.req and rarityAliases[value.req:lower] or nil if not value.req or rarityOrder(rarity) >= rarityOrder(reqRarity) then local num = (value[2] or 0) + 100 * value[1] table.push(statStr,("&7%s: &a%s%s"):format( statModule._getstatdata(key).name, (num < 0 and '' or '+'), num ))       	end end statStr = table.concat(statStr,'/')..'//' local ab_names = data.abilities.name local ab_tooltips = data.abilities.tooltip or data.abilities.tooltips local abilityStr = (ab_tooltips and (#ab_names == #ab_tooltips)) and (table.concat(table.map(ab_names, function(name, i)		   	if not ab_tooltips[i] then error(pet..' Pet: desc and tooltip length mismatch') end		    	return ('&6%s/&r%s'):format( name, ab_tooltips[i]:gsub('^/+(.*)','%1'):gsub('(.-)/+$','%1') )	    	end),'//')..'//') or '' local hi = data.heldItem local hiTooltip = hi and (hi.tooltip or hi.tooltips) local helditemStr = (hi and hiTooltip and (rarity == rarityTier._getTier(hi.req).name)) and ('&6Held Item: %s/&r%s//'):format( hi.name, hiTooltip:gsub('^/+(.*)','%1'):gsub('(.-)/+$','%1') ) or '' return { pet, data.petType, rarity:upper, getFormatting(rarity), statStr, abilityStr, helditemStr } end), { id = '$o Pet' }) end

return p