Jump to content

Module:Campeao: Difference between revisions

From WikiPStory
Titulos de painel viram div: h3 fazia o MediaWiki gerar indice dentro do painel
Painel de Habilidades com seletor e detalhe, no formato da referencia
Line 162: Line 162:
split:node(pRec)
split:node(pRec)


-- Mecanicas
-- Habilidades: seletor em cima, detalhe da escolhida embaixo.
local pMec = painel('Mecânicas de Vida', 'skills')
local pHab = painel('Habilidades', 'skills')
if c.habilidades and #c.habilidades > 0 then
local temAlguma = false
for _, h in ipairs(c.habilidades) do
for i, dif in ipairs(difs) do
local it = pMec:tag('div'):addClass('cp-skill')
local lista = c.habilidades and c.habilidades[dif:lower()] or {}
it:tag('div'):addClass('cp-skill-name'):wikitext(h.nome)
if #lista > 0 then
if h.hp then it:tag('span'):addClass('cp-skill-hp'):wikitext('HP ' .. h.hp) end
temAlguma = true
it:tag('div'):addClass('cp-skill-desc'):wikitext(h.desc or '')
local grupo = pHab:tag('div'):addClass('cp-skills'):attr('data-dif', dif:lower())
if i > 1 then grupo:addClass('is-hidden') end
 
local barra = grupo:tag('div'):addClass('cp-skill-bar')
for n, h in ipairs(lista) do
local b = barra:tag('span'):addClass('cp-skill-pick')
:attr('data-skill', tostring(n)):attr('role', 'button')
:attr('tabindex', '0'):wikitext(h.nome)
if n == 1 then b:addClass('is-active') end
end
 
for n, h in ipairs(lista) do
local det = grupo:tag('div'):addClass('cp-skill-detail')
:attr('data-skill', tostring(n))
if n > 1 then det:addClass('is-hidden') end
det:tag('div'):addClass('cp-skill-name'):wikitext(h.nome)
 
local meta = det:tag('div'):addClass('cp-skill-meta')
meta:tag('span'):wikitext(h.tipo)
if h.elemento and h.elemento ~= '' then
meta:tag('span'):wikitext(h.elemento)
end
meta:tag('span'):wikitext('Alcance ' .. h.alcance)
meta:tag('span'):wikitext('Recarga ' .. h.cooldown .. 's')
if h.dano and h.dano > 0 then
meta:tag('span'):wikitext('Dano ' .. h.dano)
end
if h.chance and h.chance < 100 then
meta:tag('span'):wikitext('Chance ' .. h.chance .. '%')
end
if h.nevermiss then
meta:tag('span'):addClass('cp-skill-flag'):wikitext('Não erra')
end
 
if h.desc and h.desc ~= '' then
det:tag('div'):addClass('cp-skill-desc'):wikitext(h.desc)
else
det:tag('div'):addClass('cp-skill-desc cp-empty')
:wikitext('Descrição ainda não documentada.')
end
 
if h.video and h.video ~= '' then
det:tag('div'):addClass('cp-skill-video')
:wikitext('[[File:' .. h.video .. '|center|480px|link=]]')
else
det:tag('div'):addClass('cp-skill-video cp-empty')
:wikitext('Vídeo desta habilidade ainda não gravado.')
end
end
end
end
else
pMec:tag('div'):addClass('cp-empty'):wikitext(
'As mecânicas deste Campeão ainda não foram documentadas. ' ..
'Ao atingir marcas específicas de HP ele se posiciona na arena e inicia uma mecânica.')
end
end
raiz:node(pMec)
if not temAlguma then
pHab:tag('div'):addClass('cp-empty')
:wikitext('O moveset deste Campeão ainda não foi cadastrado.')
end
raiz:node(pHab)


-- Conquistas
-- Conquistas

Revision as of 02:07, 12 September 2026

Documentation for this module may be created at Module:Campeao/doc

-- Renderizador das fichas de Campeao do Champion's Path.
--
-- A pagina de cada Campeao deve conter uma linha e nada mais:
--     {{Campeao|Tyranitar}}
--
-- Todo o layout vive aqui. Se for preciso duplicar marcacao entre dois
-- Campeoes, o erro esta neste modulo, nao na pagina.

local p = {}
local dados = mw.loadData('Module:Campeao/dados')

local PLACEHOLDER = 'ArquivoExemplo.png'

-- Formata 1000000 como "1.000.000"
local function numero(n)
	local s = tostring(n)
	local r = s:reverse():gsub('(%d%d%d)', '%1.'):reverse()
	return (r:gsub('^%.', ''))
end

-- Chip de item: icone, contador e tooltip. Enquanto nao houver sprite, cai
-- no placeholder, entao a ficha ja fica montada e so troca a imagem depois.
local function chip(nomeItem, qtd)
	local arquivo = 'Item ' .. nomeItem:gsub('[%(%):]', ''):gsub('%s+', ' ') .. '.png'
	local existe = mw.title.new('File:' .. arquivo)
	local usar = (existe and existe.fileExists) and arquivo or PLACEHOLDER

	local w = mw.html.create('span'):addClass('cp-item')
	w:tag('span'):addClass('cp-item-icon')
		:wikitext('[[File:' .. usar .. '|40px|link=|alt=' .. nomeItem .. ']]')
	if qtd and qtd ~= '' then
		w:tag('span'):addClass('cp-item-qty'):wikitext(qtd)
	end
	local tip = w:tag('span'):addClass('cp-tip')
	tip:tag('span'):addClass('cp-tip-name'):wikitext(nomeItem)
	if qtd and qtd ~= '' then
		tip:tag('span'):addClass('cp-tip-qty'):wikitext('Quantidade: ' .. qtd)
	end
	return w
end

local function stat(rotulo, valor)
	local d = mw.html.create('div'):addClass('cp-stat')
	d:tag('span'):addClass('cp-stat-label'):wikitext(rotulo)
	d:tag('span'):addClass('cp-stat-value'):wikitext(valor)
	return d
end

local function painel(titulo, modificador)
	local s = mw.html.create('div'):addClass('cp-panel')
	if modificador then s:addClass('cp-panel--' .. modificador) end
	-- div, nao h3: um heading de verdade faria o MediaWiki criar secao e
	-- indice automatico dentro do painel, alem de reestruturar o HTML.
	s:tag('div'):addClass('cp-panel-title'):wikitext(titulo)
	return s
end

-- Recompensas de uma dificuldade: EXP em destaque e os itens como chips.
local function recompensas(c, dif)
	local box = mw.html.create('div'):addClass('cp-rewards'):attr('data-dif', dif:lower())
	local exp = (dif == 'Hard') and c.expHard or c.expNormal

	if exp then
		box:tag('div'):addClass('cp-rewards-label'):wikitext('Experiência')
		local linha = box:tag('div'):addClass('cp-rewards-row')
		linha:tag('span'):addClass('cp-exp'):wikitext(numero(exp) .. ' EXP')
	end

	box:tag('div'):addClass('cp-rewards-label'):wikitext('Itens possíveis')
	local linha = box:tag('div'):addClass('cp-rewards-row')
	for _, r in ipairs(dados.loot[dif] or {}) do
		linha:node(chip(r.item, r.qtd))
	end
	if c.megaStone and c.megaStone ~= '' then
		linha:node(chip(c.megaStone, '1'))
	end

	box:tag('div'):addClass('cp-rewards-hint')
		:wikitext('Passe o mouse sobre um item para ver o nome.')
	return box
end

local function requisitos(c, dif)
	local box = mw.html.create('div'):addClass('cp-req'):attr('data-dif', dif:lower())
	local ul = box:tag('ul')
	ul:tag('li'):wikitext("Nível '''" .. ((dif == 'Hard') and '425' or '350') .. "''' ou superior.")
	ul:tag('li'):wikitext("Equipe de '''exatamente 3 jogadores'''.")
	ul:tag('li'):wikitext("'''1 Pokémon''' por jogador, sem troca durante a batalha.")
	ul:tag('li'):wikitext("'''1 Champion's Ticket''' para entrar.")
	ul:tag('li'):wikitext('Acesso liberado com o ' .. (c.aceTrainer or '') .. '.')
	if dif == 'Hard' then
		ul:tag('li'):wikitext("O Campeão enfrentado é a versão '''Shiny'''.")
	end
	return box
end

local function conquistas(dif)
	local box = mw.html.create('div'):addClass('cp-ach'):attr('data-dif', dif:lower())
	local ul = box:tag('ul'):addClass('cp-ach-list')
	local chave = (dif == 'Hard') and 'hard' or 'normal'
	for _, a in ipairs(dados.conquistas or {}) do
		if a[chave] then ul:tag('li'):wikitext(a.desc) end
	end
	return box
end

function p.ficha(frame)
	local chave = frame.args[1] or frame.args.campeao or ''
	chave = mw.text.trim(chave)
	local c = dados.campeoes[chave]
	if not c then
		return '<span class="error">Campeão desconhecido: ' .. mw.text.nowiki(chave)
			.. '. Cadastre-o em [[Module:Campeao/dados]].</span>'
	end

	local difs = { 'Normal' }
	if c.hard then table.insert(difs, 'Hard') end

	local raiz = mw.html.create('div'):addClass('cp-boss'):attr('data-tema', 'claro')

	-- Alternador de tema. O JS em MediaWiki:Common.js troca data-tema e guarda
	-- a preferencia; sem JS o botao some e a ficha fica no tema claro.
	raiz:tag('span'):addClass('cp-tema'):attr('role', 'button'):attr('tabindex', '0')
		:attr('data-cp-tema', '1'):css('display', 'none'):wikitext('Modo escuro')

	-- Cabecalho
	local head = raiz:tag('div'):addClass('cp-head')
	local arte = (c.arte and c.arte ~= '') and c.arte or PLACEHOLDER
	head:tag('div'):addClass('cp-art')
		:wikitext('[[File:' .. arte .. '|200px|link=|alt=' .. c.nome .. ']]')
	local info = head:tag('div'):addClass('cp-head-info')
	info:tag('div'):addClass('cp-title'):wikitext(c.nome)
	info:tag('span'):addClass('cp-badge'):wikitext("Campeão das Expedições")
	info:tag('p'):addClass('cp-desc'):wikitext(
		'Campeão da Expedition do ' .. c.expedition ..
		', enfrentado no [[Champion\'s Path]] em uma arena que representa o seu habitat natural.')
	local stats = info:tag('div'):addClass('cp-stats')
	stats:node(stat('Expedition', c.expedition))
	stats:node(stat('Ace Trainer', c.aceTrainer))
	stats:node(stat('Jogadores', '3'))
	stats:node(stat('Tempo alvo', c.tempoAlvo .. ' min'))

	-- Abas de dificuldade
	local abas = raiz:tag('div'):addClass('cp-tabs')
	for i, dif in ipairs(difs) do
		local b = abas:tag('span'):addClass('cp-tab'):attr('data-dif', dif:lower())
			:attr('role', 'button'):attr('tabindex', '0'):wikitext(dif)
		if i == 1 then b:addClass('is-active') end
	end

	-- Paineis lado a lado
	local split = raiz:tag('div'):addClass('cp-split')
	local pReq = painel('Requisitos')
	local pRec = painel('Recompensas', 'rewards')
	for i, dif in ipairs(difs) do
		local r1, r2 = requisitos(c, dif), recompensas(c, dif)
		if i > 1 then r1:addClass('is-hidden'); r2:addClass('is-hidden') end
		pReq:node(r1)
		pRec:node(r2)
	end
	split:node(pReq)
	split:node(pRec)

	-- Habilidades: seletor em cima, detalhe da escolhida embaixo.
	local pHab = painel('Habilidades', 'skills')
	local temAlguma = false
	for i, dif in ipairs(difs) do
		local lista = c.habilidades and c.habilidades[dif:lower()] or {}
		if #lista > 0 then
			temAlguma = true
			local grupo = pHab:tag('div'):addClass('cp-skills'):attr('data-dif', dif:lower())
			if i > 1 then grupo:addClass('is-hidden') end

			local barra = grupo:tag('div'):addClass('cp-skill-bar')
			for n, h in ipairs(lista) do
				local b = barra:tag('span'):addClass('cp-skill-pick')
					:attr('data-skill', tostring(n)):attr('role', 'button')
					:attr('tabindex', '0'):wikitext(h.nome)
				if n == 1 then b:addClass('is-active') end
			end

			for n, h in ipairs(lista) do
				local det = grupo:tag('div'):addClass('cp-skill-detail')
					:attr('data-skill', tostring(n))
				if n > 1 then det:addClass('is-hidden') end
				det:tag('div'):addClass('cp-skill-name'):wikitext(h.nome)

				local meta = det:tag('div'):addClass('cp-skill-meta')
				meta:tag('span'):wikitext(h.tipo)
				if h.elemento and h.elemento ~= '' then
					meta:tag('span'):wikitext(h.elemento)
				end
				meta:tag('span'):wikitext('Alcance ' .. h.alcance)
				meta:tag('span'):wikitext('Recarga ' .. h.cooldown .. 's')
				if h.dano and h.dano > 0 then
					meta:tag('span'):wikitext('Dano ' .. h.dano)
				end
				if h.chance and h.chance < 100 then
					meta:tag('span'):wikitext('Chance ' .. h.chance .. '%')
				end
				if h.nevermiss then
					meta:tag('span'):addClass('cp-skill-flag'):wikitext('Não erra')
				end

				if h.desc and h.desc ~= '' then
					det:tag('div'):addClass('cp-skill-desc'):wikitext(h.desc)
				else
					det:tag('div'):addClass('cp-skill-desc cp-empty')
						:wikitext('Descrição ainda não documentada.')
				end

				if h.video and h.video ~= '' then
					det:tag('div'):addClass('cp-skill-video')
						:wikitext('[[File:' .. h.video .. '|center|480px|link=]]')
				else
					det:tag('div'):addClass('cp-skill-video cp-empty')
						:wikitext('Vídeo desta habilidade ainda não gravado.')
				end
			end
		end
	end
	if not temAlguma then
		pHab:tag('div'):addClass('cp-empty')
			:wikitext('O moveset deste Campeão ainda não foi cadastrado.')
	end
	raiz:node(pHab)

	-- Conquistas
	local pCon = painel('Conquistas', 'ach')
	for i, dif in ipairs(difs) do
		local bloco = conquistas(dif)
		if i > 1 then bloco:addClass('is-hidden') end
		pCon:node(bloco)
	end
	raiz:node(pCon)

	local tip = raiz:tag('div'):addClass('cp-tip-bar')
	tip:tag('span'):addClass('cp-tip-tag'):wikitext('Dica')
	tip:tag('span'):wikitext('Não há Potions nem Revives nesta sala: sobreviver às mecânicas vale mais do que causar dano.')

	return frame:extensionTag{ name = 'templatestyles', args = { src = 'Campeao/styles.css' } }
		.. tostring(raiz)
end

return p