Jump to content
Main menu
Main menu
move to sidebar
hide
Navigation
Main page
Recent changes
Random page
MediaWiki help
Creopedia
Search
Search
Appearance
Log in
Personal tools
Log in
View source for Module:Move/Components/Infobox
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
Special pages
Page information
Appearance
move to sidebar
hide
←
Module:Move/Components/Infobox
require( 'strict' ) local infoboxLua = require( 'Module:InfoboxLua' ) local gameData = require( 'Module:GameData' ) local effect = require( 'Module:Effect' ) local getThumbnail = require( 'Module:Move' ).getThumbnail local energy = require( 'Module:Energy' )._main local badge = require( 'Module:BadgeLua' ) local element = require( 'Module:Element' ) local p = {} --- Move icons are roughly 36px of pixel art. Shown at 4x, with pixelated --- rendering so the upscale stays crisp instead of being smoothed. local ICON_SIZE = 144 --- The games name the same move type differently, and EvoCreo has a NONE type --- that carries no colour of its own. local moveTypeIds = { NORMAL = 'normal', SUPER = 'super', ELITE = 'elite', HEAL = 'heal', HEALING = 'heal' } --- @param name string --- @return string local function titleCase( name ) return name:sub( 1, 1 ):upper() .. name:sub( 2 ):lower() end --- Badges return an empty string rather than nil for a field the game does not --- record, so the row can be concatenated without leaving holes in the table. --- --- @param name string|nil --- @return string local function getMoveTypeBadge( name ) if not name then return '' end local id = moveTypeIds[name:upper()] return badge.render( { text = name, class = id and ( 't-move-type t-move-type--' .. id ) or nil } ) end --- @param name string|nil --- @return string local function getClassBadge( name ) if not name then return '' end return badge.render( { text = name, class = 't-move-class t-move-class--' .. name:lower() } ) end --- Element badges are looked up from a fixed table of the nine elements. --- EvoCreo gives its typeless moves an element of NONE, which has no entry --- there, so those fall back to a plain badge instead of raising an error. --- --- @param name string|nil --- @return string local function getElementBadge( name ) if not name then return '' end local ok, html = pcall( element._main, name ) if ok then return html end return badge.render( { text = titleCase( name ) } ) end --- The row of badges heading a game's stats. --- --- Move type, category and element sit inside the game's own section rather --- than in the infobox header, because the games disagree about them: of the --- 162 moves they share, 57 change move type between EvoCreo and EvoCreo 2 and --- 27 change category. --- --- @param move table --- @param args table --- @return string local function getBadgesHtml( move, args ) local badges = { getMoveTypeBadge( args.type or move.type ), getClassBadge( args.class or move.class ), getElementBadge( args.element or move.element ) } return tostring( mw.html.create( 'div' ) :addClass( 't-move-infobox-badges' ) :wikitext( table.concat( badges ) ) ) end --- Normalise one game's record of a move into the fields this infobox renders. --- --- The two games spell the same fields differently, and EvoCreo stores accuracy --- as a fraction rather than a percentage. EvoCreo also leaves an attribute out --- of a move's record rather than writing its default value, so every field --- taken from it needs that default supplied here. --- --- @param data table --- @param gameId string --- @return table|nil local function getMove( data, gameId ) if gameId == 'evocreo2' then local ec2 = data.evocreo2 if not ec2 then return nil end return { name = ec2.name, class = ec2.moveClass.name, type = ec2.moveType.name, element = ec2.element.name, damage = ec2.damage, accuracy = ec2.accuracy, recharge = ec2.recharge, -- Only EvoCreo 2 records what a move actually does. The EvoCreo -- data has no effects at all, so its section leaves this nil and -- renders no Effects block. effectMaps = ec2.moveEffectMaps, icon = getThumbnail( ec2.name ) } end local ec1 = data.evocreo if not ec1 then return nil end return { name = data.name, class = ec1.type, -- Bite and Scratch carry no skill type of their own. type = ec1.skilltype or 'NORMAL', element = ec1.element, damage = ec1.basedamage, accuracy = math.floor( tonumber( ec1.accuracy or 1 ) * 100 + 0.5 ), -- Confused Strike and Rest carry no recharge, meaning none is needed. recharge = ec1.recharge or 0, icon = getThumbnail( data.name, 'evocreo' ) } end --- Every game this move appears in, in the order the games are defined. --- --- @param data table --- @return table[] local function getMoves( data ) local moves = {} for _, game in ipairs( gameData.getGames() ) do local move = getMove( data, game.id ) if move then table.insert( moves, { game = game, move = move } ) end end return moves end --- @param move table --- @param gameId string --- @param args table --- @return table[] local function getStatsItems( move, gameId, args ) local statsItems = { { label = 'Power', content = args.power or tostring( move.damage ) }, { label = 'Accuracy', content = args.accuracy or tostring( move.accuracy ) }, { -- EvoCreo moves take a number of turns to recharge; they do not -- consume energy the way EvoCreo 2 moves do. label = gameId == 'evocreo' and 'Recharge' or 'Energy', content = energy( args.energy or move.recharge ) } } -- Appended rather than built in, because a move with no effects should show -- no Effects block at all, and the EvoCreo section never has any. for _, card in ipairs( effect.getInfoboxCards( move.effectMaps, 'move' ) ) do table.insert( statsItems, card ) end return statsItems end --- One game's account of the move: how it is classified, then its numbers. --- --- @param entry table --- @param args table --- @return table local function getGameSection( entry, args ) return { label = entry.game.name, columns = 3, content = getBadgesHtml( entry.move, args ), items = getStatsItems( entry.move, entry.game.id, args ) } end --- Every field below the header can differ between the games, so each game --- gets its own tab. A move that only ever appeared in one game gets a plain --- section instead, which needs no heading to say which game it belongs to. --- --- @param moves table[] --- @param args table --- @return table local function getGamesSection( moves, args ) if #moves == 1 then local section = getGameSection( moves[1], args ) section.label = nil return section end local sections = {} for _, entry in ipairs( moves ) do table.insert( sections, getGameSection( entry, args ) ) end return { sections = sections } end --- Build the infobox data needed from the raw data --- --- @param moves table[] --- @param args table --- @return table local function getInfoboxData( moves, args ) local primary = moves[1].move return { title = primary.name, image = { src = args.image or primary.icon, size = ICON_SIZE, class = 'cp-image-pixelated t-move-infobox-image' }, sections = { getGamesSection( moves, args ) } } end --- @param context ComponentContext --- @return string function p.render( context ) local moves = getMoves( context.data ) if #moves == 0 then return tostring( mw.html.create( 'div' ) :addClass( 'error' ) :wikitext( 'Move data is currently unavailable.' ) ) end return mw.getCurrentFrame():extensionTag { name = 'templatestyles', args = { src = 'Module:Move/Components/Infobox/styles.css' } } .. infoboxLua.render( getInfoboxData( moves, context.args or {} ) ) end return p
Templates used on this page:
Template:Documentation
(
view source
)
Module:Move/Components/Infobox/doc
(
view source
)
Return to
Module:Move/Components/Infobox
.