The Alchemist Code Wiki

READ MORE

The Alchemist Code Wiki
(Limit break)
mNo edit summary
Line 217: Line 217:
 
}
 
}
 
for i=1,11 do
 
for i=1,11 do
local tp = t_buff['type'..i] and tostring(t_buff['type'..i]) or nil
+
if t_buff['type'..i] then
  +
local tp = tostring(t_buff['type'..i])
if tp then
 
 
local values = {}
 
local values = {}
 
local min, max = t_buff['vini'..i], t_buff['vmax'..i]
 
local min, max = t_buff['vini'..i], t_buff['vmax'..i]

Revision as of 06:10, 15 February 2020

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

local render_item_icon = require('Module:Render/Item')._icon
local render_gear_icon = require('Module:Render/Gear')._icon
local render_memento_icon = require('Module:Render/Memento')._icon
local render_unit_icon = require('Module:Render/Unit')._icon
local enums = require('Module:Data/Enums')
local model = require('Module:Data').model
local query = model.query

local function makeInfobox(args)
	local root = mw.html.create('div')
	root:addClass('infobox')
	root:addClass(args.class)
	root:css{
		['float'] = 'right',
		['margin-left'] = '15px',
		['width'] = '300px',
		['border'] = '1px solid #aaa',
		['background'] = '#eee',
		['font-size'] = '12px',
	}
	local heading = root:tag('div')
	heading:addClass('heading')
	heading:css{
		['background'] = 'goldenrod',
		['font-weight'] = 700,
		['font-size'] = '140%',
		['line-height'] = '1.25em',
		['display'] = 'flex',
		['flex-direction'] = 'row',
		['justify-items'] = 'flex-start',
		['text-align'] = 'center',
		['min-height'] = '64px',
	}
	local icon = heading:tag('div')
	icon:addClass('infobox-icon')
	icon:css{
		['flex'] = '0 0 64px',
		['padding'] = '0.25rem',
	}
	icon:node(args.icon)
	local name = heading:tag('div')
	name:addClass('name')
	name:css{
		['flex'] = '1 1 100%',
		['display'] = 'flex',
		['text-align'] = 'center',
		['align-items'] = 'center',
		['justify-content'] = 'center',
		['margin'] = '0',
		['padding'] = '0.25rem',
	}
	name:wikitext(args.name)
	local wrapper = root:tag('div')
	wrapper:addClass('wrapper')
	wrapper:css{
		['flex'] = '1 1 100%',
		['overflow']='hidden',
	}
	local dl = wrapper:tag('dl')
	dl:css{
		['display'] = 'grid',
		['grid-template-columns'] = '100px 1fr',
	}

	local function printRow(t, label, content)
		if content == nil then return end
		local dt = t:tag('dt')
		dt:css{
			['grid-column-start'] = 1,
			['padding'] = '2px 8px 2px 3px',
			['text-align'] = 'right',
			['border-right'] = '2px solid #aaa',
			['margin'] = '0 -2px 0 0',
		}
		dt:wikitext(label)
		local dd = t:tag('dd')
		dd:css{
			['grid-column-start'] = 2,
			['margin'] = 0,
			['padding'] = '2px 7px',
			['border-left'] = '2px solid #aaa',
		}
		dd:wikitext(content)
	end
	
	for i, label in ipairs(args.labels) do
		printRow(dl, label, args.rows[label])
	end

	return tostring(root)
end

local p = {}

function p.getData(iname)
	local datapage = mw.ext.cargo.query('ConceptCard', '_pageName', { where = 'iname = "'..iname..'"', groupBy = '_pageName, iname'})[1]
	local pagename = datapage and datapage._pageName or 'Data:Game/MasterParam/ConceptCard/'..iname
	local frame = mw.getCurrentFrame()
	local title = mw.title.new(pagename)
	local content = title:getContent()
	local args = {}
	local params = content:match('^%s*%{%{#invoke:Data%|insert%|(.-)%}%}%s*$')
	for param in mw.text.gsplit(params, '|', true) do
		local k, v = param:match('([^=]+)=(.+)')
		local obj = mw.text.jsonDecode(frame:preprocess(v))
		if k == 'gl' or k == 'jp' then obj.server = k end
		args[k] = obj
	end
	return args
end

local typeMap = {
	['1'] = 'Equipment',
	['2'] = 'Enhance EXP',
	['3'] = 'Enhance Trust',
}

local maxLevels = {1, 25, 30, 35, 40}

local function getVCR(data)
	local t = {}
	local f = function(s, render_icon)
		local counts = data['trust_'..s..'_counts']
		local names = data['trust_'..s..'_names']
		if not names then return end
		for i, v in ipairs(names) do
			-- table.insert(sb2, i)
			-- table.insert(sb2, (counts[i] > 1) and counts[i] or nil)
			table.insert(t, render_icon({v, name = 'none', count = counts[i] > 1 and counts[i] or nil}))
		end
	end
	f('item', render_item_icon)
	f('artifact', render_gear_icon)
	return #t > 0 and table.concat(t) or nil
end

local function getUnitReward(data)
	local iname = data.first_get_unit or ''
	if iname == '' then return nil end
	return render_unit_icon{iname, size='small'}
end

local function minQuery(tables, fields, args)
	if type(fields) == 'table' then
		fields = table.concat(fields, ',')
	elseif fields == '*' then
		local subModel = mw.loadData('Module:Data/Model/'..tables)
		local t = {'_pageName,server'}
		for k,v in pairs(subModel) do
			t[#t+1] = k
		end
		fields = table.concat(t, ',')
	end
	local row = query(tables, fields, args)[1]
	if not row then return end
	local obj = {}
	for k,v in pairs(row) do
		if type(v) == 'table' then
			if #v > 0 then obj[k] = v end
		elseif v ~= '' then
			obj[k] = v
		end
	end
	return obj
end
local function queryBuff(iname)
	if not iname then return end
	return minQuery('Buff','*',{where='iname="'..iname..'" AND server="gl"'})
end
local function querySkill(iname)
	if not iname then return end
	return minQuery('Skill','*',{
		where = 'iname="'..iname..'" AND server="gl"'
	})
end


local h = {}
function h.printEffects(root, args)
	if not args then return end
	if not args.effects then return end
	
	local maxLevel = maxLevels[args.rare+1]
	for i, eff in ipairs(args.effects) do
		if eff.statusup_skill then
			root:tag('h2'):wikitext('Stats')
			h.printStatsTable(root, eff.statusup_skill, maxLevel)
		end
	end
	
	for i, eff in ipairs(args.effects) do
		mw.logObject(eff)
		if eff.card_skill then
			root:tag('h2'):wikitext('Card skill')
			h.printStatsTable(root, eff.card_skill, maxLevel)
		end
		if eff.add_card_skill_buff_awake then -- limit break buff
			root:tag('h3'):wikitext('Limit Break')
			h.printAddCardSkillBuffAwake(root, eff.add_card_skill_buff_awake)
		end
	end

end

function h.printStatsTable(root, skill_iname, maxLevel)
	local skill = querySkill(skill_iname)
	if not skill then return end
	
	local t_buff = queryBuff(skill.t_buff)
	local s_buff = queryBuff(skill.s_buff)
	
	mw.logObject(t_buff, 't_buff')
	mw.logObject(s_buff, 's_buff')
	
	local stats = {
		
	}
	for i=1,11 do
		if t_buff['type'..i] then
			local tp = tostring(t_buff['type'..i])
			local values = {}
			local min, max = t_buff['vini'..i], t_buff['vmax'..i]
			local per = (max - min) / (maxLevel - 1)
			for level=1,maxLevel do
				values[level] = math.floor((level - 1) * per + min)
			end
			stats[tp] = values
		end
	end
	
	-- Render
	root:tag('h3'):wikitext('Simple stats')
	local simple = root:tag('table'):addClass('wikitable')
	local tr = simple:tag('tr')
	tr:tag('th'):wikitext('Type')
	tr:tag('th'):wikitext('Lvl 1')
	tr:tag('th'):wikitext('Lvl '..(maxLevel-10))
	tr:tag('th'):wikitext('Lvl '..maxLevel)
	for i=1,11 do
		if t_buff['type'..i] then
			local tr = simple:tag('tr')
			local tp = tostring(t_buff['type'..i])
			local values = stats[tp]
			tr:tag('td'):wikitext(enums.statNameFromType(tp))
			tr:tag('td'):wikitext(string.format('%+d', values[1]))
			tr:tag('td'):wikitext(string.format('%+d', values[maxLevel-10]))
			tr:tag('td'):wikitext(string.format('%+d', values[maxLevel]))
		end
	end
	
	--[==[ Scrollable table?
		<div style="display: table">
		<div style="max-height: 240px; overflow-y: scroll; box-sizing: border-box; padding: 4px; border: 1px solid #131313">
		-- Long table here
		</div>
		</div>
	--]==]

	root:tag('h3'):wikitext('Detailed stats')
	local detailed = root:tag('div'):css{
		display = 'flex',
		['flex-wrap'] = 'wrap',
	}
	for col = 1, maxLevel/10 do
		local flexitem = detailed:tag('div'):css{
			flex = 0,
			background = col % 2 == 0 and 'orange' or 'salmon', -- yum ^_^
		}
		local wikitable = flexitem:tag('table'):addClass('wikitable')
		local tr = wikitable:tag('tr')
		tr:tag('th'):wikitext('Level')
		for i = 1, 11 do
			if t_buff['type'..i] then
				local tp = tostring(t_buff['type'..i])
				tr:tag('th'):wikitext(enums.statNameFromType(tp))
			end
		end
		for row = 1, 10 do
			local level = (col - 1) * 10 + row
			local tr = wikitable:tag('tr')
			tr:tag('td'):wikitext(level)
			for i=1,11 do
				if t_buff['type'..i] then
					local tp = tostring(t_buff['type'..i])
					tr:tag('td'):wikitext(string.format('%+d', stats[tp][level]))
				end
			end
		end
	end
end

function h.printAddCardSkillBuffAwake(root, buff_iname)
	-- add_card_skill_buff_awake = table#1 {
	-- ["_pageName"] = "Data:Game/MasterParam/Buff/BUFF GS1 LOST ZWEI 01 BONUS 01",
	-- ["calc1"] = 0,
	-- ["chktgt"] = 0,
	-- ["cond"] = 4,
	-- ["custom_targets"] = table#2 {
	-- "CT_LOST",
	-- "CT_UROBOROS",
	-- },
	-- ["iname"] = "BUFF_GS1_LOST_ZWEI_01_BONUS_01",
	-- ["server"] = "gl",
	-- ["timing"] = 1,
	-- ["type1"] = 7,
	-- ["vini1"] = 8,
	-- ["vmax1"] = 30,
	-- }
	local buff = queryBuff(buff_iname)
	-- Show limit break
	local tbl = root:tag('table'):addClass('wikitable')
	local tr = tbl:tag('tr')
	tr:tag('th'):wikitext('Type')
	for lb=1,5 do tr:tag('th'):wikitext('LB'..lb) end
	for i=1,11 do
		tr = tbl:tag('tr')
		if buff['type'..i] then
			local tp = tostring(buff['type'..i])
			tr:tag('td'):wikitext(enums.statNameFromType(tp))
			local min, max = buff['vini'..i], buff['vmax'..i]
			local per = (max - min) / 4
			for lb=1,5 do
				local value = math.floor((lb - 1) * per + min)
				tr:tag('td'):wikitext(string.format('%+d', value))
			end
		end
	end
	-- TODO: Target groups
	if buff.custom_targets then
		
	end
	-- mw.logObject(buff, 'add_card_skill_buff_awake')
end

local renderPage = function(iname)
	local data = minQuery('ConceptCard', '*', {where='iname = "'..iname..'"'})
	if not data then
		return '`'..iname..'` not found in ConceptCard table.'
	end
	local data2 = p.getData(iname)
	local getLoc = function(param) return model.getLoc(data._pageName, param) end
	local name = getLoc('name')
	local icon = mw.html.create('div')
	icon:addClass('item-icon')
	local img = icon:tag('div')
	img:addClass('img x-'..data.rare..' y-4')
	img:css{
		['width'] = '57px',
		['height'] = '57px',
		['padding'] = '3.5px',
	}
	img:wikitext('[[File:Game,ConceptCardIcon,',data.icon,'.png|57px]]')
	local maxLevels = {1, 25, 30, 35, 40}
	-- Memento extra data
	local extra = mw.loadData("Module:Data/Extra/Memento")[iname] or {}
	local releaseDates
	for _, region in ipairs{'jp', 'gl'} do
		local date = extra[region..'Date']
		if date then
			releaseDates = releaseDates or mw.html.create('ul')
			releaseDates:tag('li'):wikitext(region:upper(), ': ', date)
		end
	end

	local cats = {
		'Memento'
	}
	local root = mw.html.create()
	-- Info Box
	local infobox = makeInfobox{
		name = name,
		icon = icon,
		labels = {
			'Type',
			'Rank',
			'Max level',
			'Enhancer cost',
			'Enhancer EXP',
			'Enhancer trust',
			'Vision Clear Reward',
			'Gives unit',
			'Source',
			'Release dates',
			'Global only',
			'External links',
		},
		rows = {
			['Type'] = typeMap[data.type],
			['Rank'] = (data.rare + 1)..'★',
			['Max level'] = maxLevels[data.rare + 1],
			['Enhancer cost'] = data.en_cost, -- zeni required to upgrade a memento with this memento
			['Enhancer EXP'] = data.en_exp, -- EXP given by this memento
			['Enhancer trust'] = data.en_trust,
			['Vision Clear Reward'] = getVCR(data),
			['Gives unit'] = getUnitReward(data),
			['Source'] = extra.source or 'Unreleased',
			['Release dates'] = releaseDates and tostring(releaseDates) or nil,
			['Global only'] = extra.glOnly and 'Yes' or nil,
			['External links'] = '[http://www.alchemistcodedb.com/card/'..iname:gsub('_','-'):lower()..' AlchemistCodeDB]',
		}
	}
	root:node(infobox)
	if data.type and typeMap[data.type] then
		cats[#cats+1] = typeMap[data.type] .. ' memento'
	end

	-- Body
	-- Card Image + Flavor
	root:tag('div'):addClass('responsive-img')
		:css{
			['margin'] = 'auto',
			['width'] = 'fit-content',
		}
		:wikitext('[[File:Game,ConceptCard,', data.icon, '.png]]')
		:tag('div'):addClass('flavor')
			:css{
				['max-width'] = '1024px',
				['padding'] = '8px',
			}
			:wikitext(getLoc('flavor'))
	-- TODO: Stats + Effects
	h.printEffects(root, data2.gl)
	-- Category
	for i, cat in ipairs(cats) do
		root:wikitext('[[Category:', cat, ']]')
	end
	-- TODO Implement http://cdn.alchemistcodedb.com/assets/big-card-frames-b34ac394d6035fb657d491b956e2c4764836b51b9361fccc4b31e722a27df510.png
	
	return tostring(root)
end

local renderFuncs = {}
renderFuncs.Icon = render_memento_icon

local renderTransclude = function(iname, args)
	local type = mw.text.trim(args[1])
	args[1] = iname
	return (renderFuncs[type] or renderFuncs.Name)(args)
end

function p._main(iname, args)
	if not args or args.isPage then
		return renderPage(iname)
	else
		return renderTransclude(iname, args)
	end
end

p.renderPage = renderPage

function p.main(frame)
	local args = require('Module:Arguments').getArgs(frame, {parentFirst = true})
	return renderPage(args[1])
end

function p.test(frame)
	return p.main{'TS_LOST_ZWEI_01'}
end

return p