Jump to content
Main menu
Main menu
move to sidebar
hide
Discord
PRO Wiki Discord
PRO Wiki
Main page
Rules
Recent changes
Random page
Help
Pokémon Revolution Online
About
Downloads
Events
FAQs
The Staff Team
Current Pokétime
Official PRO Resources
Website
Forums
PRO Discord
Twitter
Reddit
Instagram
YouTube
Search
Search
Appearance
Log in
Personal tools
Log in
View source for Module:Pokemon
Module
Discussion
English
Read
View source
View history
Tools
Tools
move to sidebar
hide
Actions
Read
View source
View history
General
What links here
Related changes
Page information
Appearance
move to sidebar
hide
←
Module:Pokemon
You do not have permission to edit this page.
You can view and copy the source of this page.
local p = {} local DATA_FORMAT = 'CSV with header' local COLUMNS = { number = 'Pokedex Number', name = 'Name', type1 = 'Type1', type2 = 'Type2', ability1 = 'Ability 1', ability2 = 'Ability 2', ha = 'Hidden Ability', generation = 'Generation', hp = 'HP', atk = 'Attack', def = 'Defense', spatk = 'Special Attack', spdef = 'Special Defense', spd = 'Speed', catch = 'Catch Rate', evhp = 'EVHP', evatk = 'EVATK', evdef = 'EVDEF', evspa = 'EVSPA', evspd = 'EVSPD', evsp = 'EVSP', male = 'Male Ratio', height = 'Height', weight = 'Weight', npc = 'NPC', exp = 'Base Experience', rarity = 'Tier', } local GEN_NUMERALS = { 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX' } local STATS = { { key = 'hp', label = 'HP', template = 'HP' }, { key = 'atk', label = 'Atk', template = 'Attack' }, { key = 'def', label = 'Def', template = 'Defense' }, { key = 'spatk', label = 'Sp.Atk', template = 'Special Attack' }, { key = 'spdef', label = 'Sp.Def', template = 'Special Defense' }, { key = 'spd', label = 'Spd', template = 'Speed' }, } local EV_KEYS = { 'evhp', 'evatk', 'evdef', 'evspa', 'evspd', 'evsp' } local function nonEmpty(s) if s == nil then return nil end s = mw.text.trim(tostring(s)) if s == '' then return nil end return s end local function templateArgs(frame) local parent = frame:getParent() return (parent and parent.args) or frame.args end local function padNumber(n) n = tonumber(n) or 0 return string.format('%03d', n) end local PokemonForms = require('Module:PokemonForms') local FORM_SUFFIXES = PokemonForms.FORM_SUFFIXES local STRIP_SUFFIXES = PokemonForms.STRIP_SUFFIXES local MEGA_VARIANTS = PokemonForms.MEGA_VARIANTS or { '', ' X', ' Y' } -- The single data fetch: the whole raw list is loaded once per page render -- and every lookup (by name, by number, form probing) reads from it. local allRowsCache = nil local numberIndexCache = nil local function loadAllRows() if allRowsCache then return allRowsCache end local csvData = mw.ext.externalData.getExternalData{ url = 'https://wiki.pokemonrevolution.net/index.php?title=Special:GetData/PokemonRawList', format = DATA_FORMAT, data = COLUMNS, } allRowsCache = {} numberIndexCache = {} if csvData then for _, row in ipairs(csvData) do if nonEmpty(row.name) then allRowsCache[row.name] = row local num = nonEmpty(row.number) -- First occurrence wins so base forms beat Megas sharing a number. if num and numberIndexCache[num] == nil then numberIndexCache[num] = row end end end end return allRowsCache end local function hyphenSpaceVariant(s) if mw.ustring.find(s, '-', 1, true) then return (mw.ustring.gsub(s, '%-', ' ')) end return (mw.ustring.gsub(s, ' ', '-')) end local function byName(name) local rows = loadAllRows() return rows[name] or rows[hyphenSpaceVariant(name)] end local function byNumber(number) loadAllRows() return numberIndexCache[tostring(number)] end local MEGA_COLUMNS = { number = 'Pokedex Number', name = 'Name', type1 = 'Type1', type2 = 'Type2', ability1 = 'Ability 1', ability2 = 'Ability 2', ha = 'Hidden Ability', generation = 'Generation', hp = 'HP', atk = 'Attack', def = 'Defense', spatk = 'Special Attack', spdef = 'Special Defense', spd = 'Speed', evhp = 'EVHP', evatk = 'EVATK', evdef = 'EVDEF', evspa = 'EVSPA', evspd = 'EVSPD', evsp = 'EVSP', height = 'Height', weight = 'Weight', stone = 'Stone', } local MEGA_SPEC do local parts = {} for key, header in pairs(MEGA_COLUMNS) do parts[#parts + 1] = key .. '=' .. header end MEGA_SPEC = table.concat(parts, ',') end local megaCache = {} local function megaByName(name) if megaCache[name] == nil then local ok, values = pcall(function() return mw.ext.externalData.getFileData{ source = 'data', ['file name'] = 'RawMegaPokemonList.csv', format = DATA_FORMAT, filters = 'Name=' .. name, data = MEGA_SPEC, } end) if ok and values and values.name ~= nil then megaCache[name] = values else megaCache[name] = false end end return megaCache[name] or nil end -- formStem/rawListFormName now live in Module:PokemonForms, shared with -- Module:Learnsets, so both resolve a form's raw-list name identically. local formStem = PokemonForms.formStem local rawListFormName = PokemonForms.rawListFormName local typeColorsCache = {} local function typeColors(frame, pokeType) if not typeColorsCache[pokeType] then typeColorsCache[pokeType] = { light = frame:expandTemplate{ title = pokeType .. ' color light' }, base = frame:expandTemplate{ title = pokeType .. ' color' }, dark = frame:expandTemplate{ title = pokeType .. ' color dark' }, } end return typeColorsCache[pokeType] end local statColorCache = {} local function statColors(frame, statTemplate) if not statColorCache[statTemplate] then statColorCache[statTemplate] = { base = frame:expandTemplate{ title = statTemplate .. ' color' }, dark = frame:expandTemplate{ title = statTemplate .. ' color dark' }, } end return statColorCache[statTemplate] end local function navTableHtml(frame, data, colors, pageName, widthPercent) widthPercent = widthPercent or 65 local number = tonumber(data.number) local prevCell = '' if number and number > 1 then local prev = byNumber(number - 1) if prev then prevCell = ' [[File:' .. prev.number .. 'Icon.png|' .. prev.name .. '|link=' .. prev.name .. ']] #' .. padNumber(prev.number) .. ' [[' .. prev.name .. ']]' end end local nextCell = '' if number then local nxt = byNumber(number + 1) if nxt then nextCell = '[[' .. nxt.name .. ']] #' .. padNumber(nxt.number) .. ' [[File:' .. nxt.number .. 'Icon.png|' .. nxt.name .. '|link=' .. nxt.name .. ']]' end end return '<table style="margin-left: auto; margin-right: auto; margin-bottom: 15px; height: 60px; ' .. 'border: 4px #' .. colors.dark .. ' solid; font-weight: bold; width: ' .. widthPercent .. '%; color: #' .. colors.dark .. '; border-radius: 20px; padding: 3px; background: #' .. colors.base .. ';">' .. '<tr>' .. '<td style="text-align: left; width: 36%; background: #' .. colors.light .. '; border-radius: 15px 1px 1px 15px; border: 1px solid #' .. colors.dark .. ';">' .. prevCell .. '</td>' .. '<td style="text-align: center; width: 28%; background: #' .. colors.light .. '; border: 1px solid #' .. colors.dark .. ';">#' .. padNumber(number) .. ' - ' .. pageName .. '</td>' .. '<td style="text-align: right; width: 36%; padding-right: 10px; background: #' .. colors.light .. '; border: 1px solid #' .. colors.dark .. '; border-radius: 1px 15px 15px 1px;">' .. nextCell .. '</td>' .. '</tr></table>' end function p.navTable(frame) local args = templateArgs(frame) local pageName = mw.title.getCurrentTitle().text local name = nonEmpty(args.Name) or pageName local data = byName(name) if not data then return '<strong class="error">PokeNavTable: no data found for "' .. name .. '"</strong>' end return navTableHtml(frame, data, typeColors(frame, data.type1), pageName, 65) end local function infoCell(colors, labelHtml, valueHtml) return '<td colspan="3" style="width: 50%; border: 1px solid #' .. colors.dark .. '; background-color: #' .. colors.light .. '; border-radius: 15px; padding: 5px;">' .. '<p style="margin-bottom: 7px; font-weight: bold; color: #' .. colors.dark .. ';">' .. labelHtml .. '</p>' .. '<span style="border-radius: 12px; padding: 4px 10px; border: 1px solid #' .. colors.dark .. '; background-color: #FFFFFF;"> ' .. valueHtml .. ' </span></td>' end local function abilityCell(colors, label, ability, widthPercent) if not ability then return '' end local style = 'border-radius: 12px; padding: 4px 10px; border: 1px solid #' .. colors.dark .. '; background-color: #FFFFFF;' if widthPercent then style = 'width: ' .. widthPercent .. '%; ' .. style end return '<td style="' .. style .. '"><b>' .. label .. '</b><br>[[' .. ability .. '_(ability)|' .. ability .. ']]</td>' end local function abilitiesRow(colors, data) local entries = { { 'Ability 1', nonEmpty(data.ability1) }, { 'Ability 2', nonEmpty(data.ability2) }, { 'Hidden Ability', nonEmpty(data.ha) }, } local present = {} for _, entry in ipairs(entries) do if entry[2] then present[#present + 1] = entry end end local widthPercent = (#present > 0) and string.format('%.2f', 100 / #present) or nil local cells = {} for _, entry in ipairs(present) do cells[#cells + 1] = abilityCell(colors, entry[1], entry[2], widthPercent) end return table.concat(cells) end local function statValueCell(frame, stat, value) local colors = statColors(frame, stat.template) return '<td style="width: 16.66%; border: 1px solid #' .. colors.dark .. '; background-color: #' .. colors.base .. '; border-radius: 12px; padding: 4px; font-size: 11px;">\'\'\'' .. stat.label .. '\'\'\'<br>' .. value .. '</td>' end local function statBarRow(frame, stat, value) local labelColors = statColors(frame, stat.template) local pct = math.floor(value / 255 * 100 + 0.5) if pct < 2 then pct = 2 end if pct > 100 then pct = 100 end local hue = math.floor(math.max(0, math.min(180, value * 180 / 255)) + 0.5) local fill = 'hsl(' .. hue .. ', 85%, 45%)' return '<tr>' .. '<td style="text-align: right; padding: 2px 8px 2px 4px; font-weight: bold; font-size: 12px; ' .. 'color: #' .. labelColors.dark .. '; white-space: nowrap;">' .. stat.label .. '</td>' .. '<td style="width: 100%; padding: 2px 0;"><div style="background-color: #FFFFFF; border: 1px solid ' .. '#999999; border-radius: 8px; height: 13px; overflow: hidden;">' .. '<div style="width: ' .. pct .. '%; height: 100%; background-color: ' .. fill .. ';"></div>' .. '</div></td>' .. '<td style="text-align: left; padding: 2px 4px 2px 8px; font-weight: bold; font-size: 12px; ' .. 'width: 34px;">' .. value .. '</td></tr>' end local MALE_COLOR = '3B6BF5' local FEMALE_COLOR = 'F5629C' local function genderRatioHtml(male) if male == 'Genderless' then return '<span style="display: inline-block; color: #000000; background-color: #FFFFFF; ' .. 'border-radius: 12px; border: 1px solid #000000; padding: 3px 12px; font-weight: bold;">' .. 'Genderless</span>' end local m = tonumber(male) if m == nil then m = nonEmpty(male) and 100 or 0 end if m < 0 then m = 0 end if m > 100 then m = 100 end local f = 100 - m local segments = '' if m > 0 then segments = segments .. '<div style="width: ' .. m .. '%; background-color: #' .. MALE_COLOR .. ';"></div>' end if f > 0 then segments = segments .. '<div style="width: ' .. f .. '%; background-color: #' .. FEMALE_COLOR .. ';"></div>' end local labels = {} if m > 0 then labels[#labels + 1] = '<span style="color: #' .. MALE_COLOR .. '; font-weight: bold;">' .. m .. '% ♂</span>' end if f > 0 then labels[#labels + 1] = '<span style="color: #' .. FEMALE_COLOR .. '; font-weight: bold;">' .. f .. '% ♀</span>' end return '<div style="width: 85%; margin: 4px auto 0;">' .. '<div style="display: flex; height: 12px; border-radius: 8px; overflow: hidden; ' .. 'border: 1px solid #555555; background-color: #FFFFFF;">' .. segments .. '</div>' .. '<div style="margin-top: 4px; font-size: 12px;">' .. table.concat(labels, ' · ') .. '</div></div>' end local function categories(data, gen, bstCategory, args) local cats = { '[[Category:Pokémon species]]' } if gen then cats[#cats + 1] = '[[Category:Generation ' .. gen .. ' Pokémon]]' end cats[#cats + 1] = '[[Category:' .. data.type1 .. '-type Pokémon]]' if nonEmpty(data.type2) then cats[#cats + 1] = '[[Category:' .. data.type2 .. '-type Pokémon]]' end cats[#cats + 1] = '[[Category:' .. data.rarity .. ' Pokémon]]' if nonEmpty(data.npc) then cats[#cats + 1] = '[[Category:NPC-obtainable Pokémon]]' end if not nonEmpty(args.EvolvesFrom) then cats[#cats + 1] = '[[Category:Base-stage Pokémon]]' end cats[#cats + 1] = '[[Category:' .. bstCategory .. '-plus-BST Pokémon]]' return table.concat(cats, ' ') end local function infoboxHtml(frame, args, data, displayName, width, pageName, includeNav) local colors = typeColors(frame, data.type1) -- Regional forms carry values like '1A'/'5A'; use the leading digits. local gen = GEN_NUMERALS[tonumber(mw.ustring.match(tostring(data.generation or ''), '^%d+') or '')] -- Types pill(s). local typesHtml if nonEmpty(data.type2) then local type2Colors = typeColors(frame, data.type2) typesHtml = '<td style="width: 50%; background-color: #' .. colors.dark .. '; border-radius: 25px 1px 1px 25px;">' .. '[[' .. data.type1 .. '_(type)|<span style="color: #FFFFFF;">' .. data.type1 .. '</span>]]</td>' .. '<td style="width: 50%; background-color: #' .. type2Colors.dark .. '; border-radius: 1px 25px 25px 1px;">' .. '[[' .. data.type2 .. '_(type)|<span style="color: #FFFFFF;">' .. data.type2 .. '</span>]]</td>' else typesHtml = '<td style="width:100%; background-color: #' .. colors.dark .. '; border-radius: 25px;">' .. '[[' .. data.type1 .. '_(type)|<span style="color: #FFFFFF;">' .. data.type1 .. '</span>]]</td>' end -- Base stats local statRows, bst = {}, 0 for _, stat in ipairs(STATS) do local value = tonumber(data[stat.key]) or 0 bst = bst + value statRows[#statRows + 1] = statBarRow(frame, stat, value) end local bstCategory = math.floor(bst / 100 + 0.5) * 100 -- EV yield. local evCells, evTotal = {}, 0 for i, stat in ipairs(STATS) do local ev = tonumber(data[EV_KEYS[i]]) or 0 evTotal = evTotal + ev evCells[#evCells + 1] = statValueCell(frame, stat, ev) end -- Catch rate. local catchRaw = tonumber(data.catch) or 0 local catchPercent = string.format('%.2f', catchRaw / 255 / 3 * 100) local buf = {} if includeNav then buf[#buf + 1] = navTableHtml(frame, data, colors, pageName) end buf[#buf + 1] = '<table align="right" class="informational-box" cellpadding="4" cellspacing="4" ' .. 'style="width: ' .. width .. '%; border: 4px solid #' .. colors.dark .. '; background-color: #' .. colors.base .. '; padding: 4px; border-radius: 15px;">' -- Header: dex number + icon, name. buf[#buf + 1] = '<tr><td colspan="3" style="width: 50%; border: 1px solid #' .. colors.dark .. '; background-color: #' .. colors.light .. '; border-radius: 15px;"><span style="margin-bottom: 7px; font-weight: bold; color:#' .. colors.dark .. ';">#' .. padNumber(data.number) .. '</span> [[File:' .. data.number .. 'Icon.png]]</td><td colspan="3" style="width: 50%; border: 1px solid #' .. colors.dark .. '; background-color: #' .. colors.light .. '; border-radius: 15px;"><span style="margin-bottom: 7px; font-weight: bold; color:#' .. colors.dark .. ';">' .. displayName .. '</span></td></tr>' -- Artwork. buf[#buf + 1] = '<tr><td colspan="6" style="border: 1px solid #' .. colors.dark .. '; background-color: #' .. colors.light .. '; border-radius: 15px; padding: 5px;"><div style="border-radius: 15px; ' .. 'text-align: center; padding: 5px; background-color: #FFFFFF;">[[File:' .. data.number .. data.name .. '.png|150px]]</div></td></tr>' -- Types + Generation. local genHtml = '—' if gen then genHtml = '[[:Category:Generation ' .. gen .. ' Pokémon|<span style="color:#' .. colors.dark .. ';">' .. gen .. '</span>]]' end buf[#buf + 1] = '<tr><td colspan="3" style="width: 50%; border: 1px solid #' .. colors.dark .. '; background-color: #' .. colors.light .. '; padding: 11px; border-radius: 15px;"><p style="margin-bottom: 7px; font-weight: bold; ' .. 'color: #' .. colors.dark .. ';">Types</p><table align="center" style="width: 75%; font-weight: bold; ' .. 'padding: 3px;"><tr>' .. typesHtml .. '</tr></table></td>' .. '<td colspan="3" style="width: 50%; border: 1px solid #' .. colors.dark .. '; background-color: #' .. colors.light .. '; border-radius: 15px;"><p style="margin-bottom: 7px; font-weight: bold; color: #' .. colors.dark .. ';">Generation</p><span style="border-radius: 12px; padding: 4px 10px; border: 1px solid #' .. colors.dark .. '; background-color: #FFFFFF;"> ' .. genHtml .. ' </span></td></tr>' -- Abilities. buf[#buf + 1] = '<tr><td colspan="6" style="border: 1px solid #' .. colors.dark .. '; background-color: #' .. colors.light .. '; padding: 11px; border-radius: 15px; width: 100%;"><table width="100%">' .. '<tr><th colspan="6"><p style="margin-bottom: 7px; font-weight: bold; color:#' .. colors.dark .. ';">[[Abilities|<span style="color:#' .. colors.dark .. ';">Abilities</span>]]</p></th></tr>' .. '<tr>' .. abilitiesRow(colors, data) .. '</tr></table></td></tr>' -- Rarity + Catch rate. buf[#buf + 1] = '<tr>' .. infoCell(colors, '[[List of Pokémon by Rarity Tier|<span style="color:#' .. colors.dark .. ';">Rarity Tier</span>]]', '[[:Category:' .. data.rarity .. ' Pokémon|<span style="color:#' .. colors.dark .. ';">' .. data.rarity .. '</span>]]') .. infoCell(colors, '[[Catch Rates|<span style="color:#' .. colors.dark .. ';">Catch rate</span>]]', data.catch .. '/255 (' .. catchPercent .. '%)') .. '</tr>' -- Base stats. buf[#buf + 1] = '<tr><td colspan="6" style="border: 1px solid #' .. colors.dark .. '; background-color: #' .. colors.light .. '; border-radius: 15px; padding: 8px; width: 100%">' .. '<table width="100%" style="border-collapse: collapse;">' .. '<tr><th colspan="3"><p style="margin-bottom: 7px; font-weight: bold; color: #' .. colors.dark .. ';">[[Base stats|<span style="color: #' .. colors.dark .. ';">Base stats</span>]]</p></th></tr>' .. table.concat(statRows) .. '<tr><td colspan="3" style="text-align: center; padding-top: 6px;">' .. '<div style="display: inline-block; background-color: #FFFFFF; border: 1px solid #' .. colors.dark .. '; padding: 4px 14px; border-radius: 12px;">Base-stat total: ' .. bst .. '</div></td></tr>' .. '</table></td></tr>' -- EV yield. buf[#buf + 1] = '<tr><td colspan="6" style="border: 1px solid #' .. colors.dark .. '; background-color: #' .. colors.light .. '; border-radius: 15px; padding: 5px; width: 100%"><table width="100%">' .. '<tr><th colspan="6">[[EVs|<span style="margin-bottom: 7px; font-weight: bold; color: #' .. colors.dark .. ';">EV Yield</span>]]</th></tr><tr>' .. table.concat(evCells) .. '</tr>' .. '<tr><td colspan="6"><div style="margin: auto; background-color:#FFFFFF; border: 1px solid #' .. colors.dark .. '; padding: 4px 14px; border-radius: 12px; margin-bottom: 5px; width: 50%;">' .. 'EV-yield total: ' .. evTotal .. '</div></td></tr></table></td></tr>' -- Base experience + Gender ratio. buf[#buf + 1] = '<tr>' .. infoCell(colors, '[[Experience System#Base Experience|<span style="color:#' .. colors.dark .. ';">Base Experience</span>]]', data.exp) .. '<td colspan="3" style="width: 50%; border: 1px solid #' .. colors.dark .. '; background-color: #' .. colors.light .. '; border-radius: 15px; padding: 5px;"><p style="margin-bottom: 7px; font-weight: bold; color: #' .. colors.dark .. ';">Gender Ratio</p>' .. genderRatioHtml(data.male) .. '</td>' .. '</tr>' -- Height + Weight. buf[#buf + 1] = '<tr>' .. infoCell(colors, 'Height', data.height .. 'm') .. infoCell(colors, 'Weight', data.weight .. 'kg') .. '</tr>' buf[#buf + 1] = '</table>' buf[#buf + 1] = categories(data, gen, bstCategory, args) return table.concat(buf) end local function megaInfoboxHtml(frame, data, width) local colors = typeColors(frame, data.type1) local gen = GEN_NUMERALS[tonumber(mw.ustring.match(tostring(data.generation or ''), '^%d+') or '')] local displayName = 'Mega ' .. (data.name or '') local typesHtml if nonEmpty(data.type2) then local type2Colors = typeColors(frame, data.type2) typesHtml = '<td style="width: 50%; background-color: #' .. colors.dark .. '; border-radius: 25px 1px 1px 25px;">' .. '[[' .. data.type1 .. '_(type)|<span style="color: #FFFFFF;">' .. data.type1 .. '</span>]]</td>' .. '<td style="width: 50%; background-color: #' .. type2Colors.dark .. '; border-radius: 1px 25px 25px 1px;">' .. '[[' .. data.type2 .. '_(type)|<span style="color: #FFFFFF;">' .. data.type2 .. '</span>]]</td>' else typesHtml = '<td style="width:100%; background-color: #' .. colors.dark .. '; border-radius: 25px;">' .. '[[' .. data.type1 .. '_(type)|<span style="color: #FFFFFF;">' .. data.type1 .. '</span>]]</td>' end local statRows, bst = {}, 0 for _, stat in ipairs(STATS) do local value = tonumber(data[stat.key]) or 0 bst = bst + value statRows[#statRows + 1] = statBarRow(frame, stat, value) end local evCells, evTotal = {}, 0 for i, stat in ipairs(STATS) do local ev = tonumber(data[EV_KEYS[i]]) or 0 evTotal = evTotal + ev evCells[#evCells + 1] = statValueCell(frame, stat, ev) end local buf = {} buf[#buf + 1] = '<table align="right" class="informational-box" cellpadding="4" cellspacing="4" ' .. 'style="width: ' .. width .. '%; border: 4px solid #' .. colors.dark .. '; background-color: #' .. colors.base .. '; padding: 4px; border-radius: 15px;">' -- Header: name across the whole top line. buf[#buf + 1] = '<tr><td colspan="6" style="border: 1px solid #' .. colors.dark .. '; background-color: #' .. colors.light .. '; border-radius: 15px;"><span style="margin-bottom: 7px; font-weight: bold; color:#' .. colors.dark .. ';">' .. displayName .. '</span></td></tr>' -- Artwork. buf[#buf + 1] = '<tr><td colspan="6" style="border: 1px solid #' .. colors.dark .. '; background-color: #' .. colors.light .. '; border-radius: 15px; padding: 5px;"><div style="border-radius: 15px; ' .. 'text-align: center; padding: 5px; background-color: #FFFFFF;">[[File:' .. (data.number or '') .. (data.name or '') .. '-Mega.png|150px]]</div></td></tr>' -- Types + Generation. local genHtml = '—' if gen then genHtml = '[[:Category:Generation ' .. gen .. ' Pokémon|<span style="color:#' .. colors.dark .. ';">' .. gen .. '</span>]]' end buf[#buf + 1] = '<tr><td colspan="3" style="width: 50%; border: 1px solid #' .. colors.dark .. '; background-color: #' .. colors.light .. '; padding: 11px; border-radius: 15px;"><p style="margin-bottom: 7px; font-weight: bold; ' .. 'color: #' .. colors.dark .. ';">Types</p><table align="center" style="width: 75%; font-weight: bold; ' .. 'padding: 3px;"><tr>' .. typesHtml .. '</tr></table></td>' .. '<td colspan="3" style="width: 50%; border: 1px solid #' .. colors.dark .. '; background-color: #' .. colors.light .. '; border-radius: 15px;"><p style="margin-bottom: 7px; font-weight: bold; color: #' .. colors.dark .. ';">Generation</p><span style="border-radius: 12px; padding: 4px 10px; border: 1px solid #' .. colors.dark .. '; background-color: #FFFFFF;"> ' .. genHtml .. ' </span></td></tr>' -- Abilities. buf[#buf + 1] = '<tr><td colspan="6" style="border: 1px solid #' .. colors.dark .. '; background-color: #' .. colors.light .. '; padding: 11px; border-radius: 15px; width: 100%;"><table width="100%">' .. '<tr><th colspan="6"><p style="margin-bottom: 7px; font-weight: bold; color:#' .. colors.dark .. ';">[[Abilities|<span style="color:#' .. colors.dark .. ';">Abilities</span>]]</p></th></tr>' .. '<tr>' .. abilitiesRow(colors, data) .. '</tr></table></td></tr>' -- Mega Stone, linked to its quest page ("Venusaurite (quest)"). local stone = nonEmpty(data.stone) local stoneHtml = '—' if stone then stoneHtml = '[[' .. stone .. ' (quest)|<span style="color:#' .. colors.dark .. ';">' .. stone .. '</span>]]' end buf[#buf + 1] = '<tr><td colspan="6" style="border: 1px solid #' .. colors.dark .. '; background-color: #' .. colors.light .. '; border-radius: 15px; padding: 5px;">' .. '<p style="margin-bottom: 7px; font-weight: bold; color: #' .. colors.dark .. ';">Mega Stone</p>' .. '<span style="border-radius: 12px; padding: 4px 10px; border: 1px solid #' .. colors.dark .. '; background-color: #FFFFFF;"> ' .. stoneHtml .. ' </span></td></tr>' -- Base stats. buf[#buf + 1] = '<tr><td colspan="6" style="border: 1px solid #' .. colors.dark .. '; background-color: #' .. colors.light .. '; border-radius: 15px; padding: 8px; width: 100%">' .. '<table width="100%" style="border-collapse: collapse;">' .. '<tr><th colspan="3"><p style="margin-bottom: 7px; font-weight: bold; color: #' .. colors.dark .. ';">[[Base stats|<span style="color: #' .. colors.dark .. ';">Base stats</span>]]</p></th></tr>' .. table.concat(statRows) .. '<tr><td colspan="3" style="text-align: center; padding-top: 6px;">' .. '<div style="display: inline-block; background-color: #FFFFFF; border: 1px solid #' .. colors.dark .. '; padding: 4px 14px; border-radius: 12px;">Base-stat total: ' .. bst .. '</div></td></tr>' .. '</table></td></tr>' -- EV yield. buf[#buf + 1] = '<tr><td colspan="6" style="border: 1px solid #' .. colors.dark .. '; background-color: #' .. colors.light .. '; border-radius: 15px; padding: 5px; width: 100%"><table width="100%">' .. '<tr><th colspan="6">[[EVs|<span style="margin-bottom: 7px; font-weight: bold; color: #' .. colors.dark .. ';">EV Yield</span>]]</th></tr><tr>' .. table.concat(evCells) .. '</tr>' .. '<tr><td colspan="6"><div style="margin: auto; background-color:#FFFFFF; border: 1px solid #' .. colors.dark .. '; padding: 4px 14px; border-radius: 12px; margin-bottom: 5px; width: 50%;">' .. 'EV-yield total: ' .. evTotal .. '</div></td></tr></table></td></tr>' -- Height + Weight. buf[#buf + 1] = '<tr>' .. infoCell(colors, 'Height', (data.height or '—') .. 'm') .. infoCell(colors, 'Weight', (data.weight or '—') .. 'kg') .. '</tr>' buf[#buf + 1] = '</table>' buf[#buf + 1] = '[[Category:Mega-Evolvable Pokémon]]' return table.concat(buf) end function p.infobox(frame) local args = templateArgs(frame) local pageName = mw.title.getCurrentTitle().text local name = nonEmpty(args.Name) or pageName local width = nonEmpty(args.Width) or '45' local data = byName(name) if not data then return '<strong class="error">PokemonInfo: no data found for "' .. name .. '"</strong>' end frame:callParserFunction('#vardefine', 'type', data.type1 or 'Normal') return infoboxHtml(frame, args, data, name, width, pageName, true) end function p.primaryType(frame) local args = templateArgs(frame) local name = nonEmpty(args.Name) or mw.title.getCurrentTitle().text local data = byName(name) or byName(formStem(name)) return (data and nonEmpty(data.type1)) or 'Normal' end local function requestedName(frame) local parent = frame:getParent() return nonEmpty(frame.args.Name) or (parent and nonEmpty(parent.args.Name)) or mw.title.getCurrentTitle().text end local participantsCache = {} local function computeParticipants(frame, name) if participantsCache[name] ~= nil then return participantsCache[name] or nil end local rows = loadAllRows() local function rowFor(n) return rows[n] or rows[hyphenSpaceVariant(n)] end local stem = formStem(name) local baseData = rowFor(stem) or rowFor(name) if not baseData then participantsCache[name] = false return nil end local baseDexNumber = mw.ustring.match(tostring(baseData.number or ''), '^%d+') local parts = { { data = baseData, label = 'Normal' } } local seen = { [baseData.name] = true } for _, form in ipairs(FORM_SUFFIXES) do local row = rowFor(rawListFormName(form, stem)) -- A candidate must share the same base dex number to be a real form of -- this Pokémon. Without this check, stripping "Nidoran Male" down to -- the stem "Nidoran" (done because "Male" is a real form suffix for -- Indeedee/Meowstic-style species) lets "Nidoran" + " Female" happen to -- match the raw list's "Nidoran Female" row — a wholly different -- species (dex #29 vs Male's #32), not this one's gender form. local rowDexNumber = row and mw.ustring.match(tostring(row.number or ''), '^%d+') if row and not seen[row.name] and rowDexNumber == baseDexNumber then seen[row.name] = true parts[#parts + 1] = { data = row, label = form.label } if form.baseLabel then parts[1].label = form.baseLabel end end end for _, variant in ipairs(MEGA_VARIANTS) do local row = megaByName(stem .. variant) if row then parts[#parts + 1] = { data = row, label = 'Mega' .. variant, mega = true } end end participantsCache[name] = parts return parts end function p.formLabel(frame) local idx = tonumber(frame.args[1]) or 0 local parts = computeParticipants(frame, requestedName(frame)) if not parts then return '' end local part = parts[idx + 1] return part and part.label or '' end function p.rawName(frame) local name = requestedName(frame) local parts = computeParticipants(frame, name) return (parts and parts[1].data.name) or name end -- Per-form tab-button colors (index-based, same convention as formLabel): -- Tabs:MultiformTab only ever had one shared color for the whole button row -- (set once via TabbedInfoBoxes' own {{Trichrome}} call), so no button could -- ever reflect its own form. These feed Border=/Cell= overrides added to -- Tabs:MultiformTab so each button is colored to the form it actually opens. function p.formBorder(frame) local idx = tonumber(frame.args[1]) or 0 local parts = computeParticipants(frame, requestedName(frame)) local part = parts and parts[idx + 1] if not part then return '' end return '#' .. typeColors(frame, part.data.type1).dark end function p.formCell(frame) local idx = tonumber(frame.args[1]) or 0 local parts = computeParticipants(frame, requestedName(frame)) local part = parts and parts[idx + 1] if not part then return '' end return '#' .. typeColors(frame, part.data.type1).light end -- Nav bar duplicated per form (index-based) so it can be embedded inside -- each tab's own content instead of once above the whole tab shell, which -- is what made it structurally unable to react to which tab is active. -- Prev/next always come from the base species' own dex number (form dex -- strings like "52A" aren't a meaningful sequence to navigate by) -- only -- the color changes per form. function p.formNavTable(frame) local pageName = mw.title.getCurrentTitle().text local idx = tonumber(frame.args[1]) or 0 local parts = computeParticipants(frame, requestedName(frame)) if not parts then return '<strong class="error">PokeNavTable: no data found for "' .. pageName .. '"</strong>' end local basePart = parts[1] local activePart = parts[idx + 1] or basePart -- Fills the tab shell's own width (100%) rather than the 65% that made -- sense for navTable's unconstrained, page-wide context -- this nav bar -- sits inside the same width-45%-of-page tab content as the infobox -- card now, so 65% of *that* would look small and off-center. return navTableHtml(frame, basePart.data, typeColors(frame, activePart.data.type1), pageName, 100) end function p.formBox(frame) local idx = tonumber(frame.args[1]) or 0 local width = nonEmpty(frame.args.Width) or '100' local name = requestedName(frame) local parts = computeParticipants(frame, name) if not parts then return '<strong class="error">PokemonInfo: no data found for "' .. name .. '"</strong>' end local part = parts[idx + 1] if not part then return '' end if part.mega then return megaInfoboxHtml(frame, part.data, width) end local parent = frame:getParent() local args = (parent and parent.args) or frame.args return infoboxHtml(frame, args, part.data, part.data.name, width, mw.title.getCurrentTitle().text, false) end return p
Page included on this page:
Module:Pokemon/doc
(
view source
)
Return to
Module:Pokemon
.
Search
Search
View source for Module:Pokemon
Add topic