The Alchemist Code Wiki

READ MORE

The Alchemist Code Wiki
Advertisement

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')
enums["EAbilitySlot"] = {
	[0] = "Action",
	[1] = "Support",
	[2] = "Reaction"
}
enums["EAbilityType"] = {
	[0] = "Active",
	[1] = "Passive"
}
enums["EAbilityTypeDetail"] = {
	[0] = "Default",
	[1] = "Job_Unique",
	[2] = "Job_Basic",
	[3] = "Job_Support",
	[4] = "Job_Reaction",
	[5] = "MasterAbility",
	[6] = "CollaboAbility",
	[7] = "WeaponAbility",
	[8] = "VisionAbility",
	[9] = "MapEffectAbility",
	[10] = "TobiraAbility"
}
enums["AttackDetailTypes"]= { -- atk type
	[0] = "None",
	[1] = "Slash",
	[2] = "Stab",
	[3] = "Blow",
	[4] = "Shot",
	[5] = "Magic",
	[6] = "Jump",
	[7] = "MAX"
}
enums["AttackTypes"] = { -- dmg type
	[0] = "None",
	[1] = "PhyAttack",
	[2] = "MagAttack"
}
enums["SkillEffectTypes"] = {
	[0] = "None",
	[1] = "Equipment",
	[2] = "Attack",
	[3] = "Defend",
	[4] = "Heal",
	[5] = "Buff",
	[6] = "Debuff",
	[7] = "Revive",
	[8] = "Shield",
	[9] = "ReflectDamage",
	[10] = "DamageControl",
	[11] = "FailCondition",
	[12] = "CureCondition",
	[13] = "DisableCondition",
	[14] = "GemsGift",
	[15] = "GemsIncDec",
	[16] = "Guard",
	[17] = "Teleport",
	[18] = "Changing",
	[19] = "RateHeal",
	[20] = "RateDamage",
	[21] = "PerfectAvoid",
	[22] = "Throw",
	[23] = "EffReplace",
	[24] = "SetTrick",
	[25] = "TransformUnit",
	[26] = "SetBreakObj",
	[27] = "ChangeWeather",
	[28] = "RateDamageCurrent",
	[29] = "TransformUnitTakeOverHP",
	[30] = "DynamicTransformUnit"
}
enums["ESelectType"] = {
	[0] = "Cross",
	[1] = "Diamond",
	[2] = "Square",
	[3] = "Laser",
	[4] = "All",
	[5] = "Wall",
	[6] = "WallPlus",
	[7] = "Bishop",
	[8] = "Victory",
	[9] = "LaserSpread",
	[10] = "LaserWide",
	[11] = "Horse",
	[12] = "LaserTwin",
	[13] = "LaserTriple",
	[14] = "SquareOutline"
}

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 function queryAbility(iname)
	if not iname then return end
	return minQuery('Ability', '*', {
		where = 'iname="'..iname..'" AND server="gl"'
	})
end

local function getUnitInamesByOrigins(birth_ids)
	if type(birth_ids) == 'number' then
		birth_ids = {birth_ids}
	end
	local ids = {}
	for i, birth_id in ipairs(birth_ids) do
		ids[i] = string.format('%q', birth_id)
	end

	local t = {}
	local rows = query('Unit', 'iname', {where = 'ai = "AI_PLAYER" AND (notsmn IS NULL OR hero = 1) AND server = "gl" AND birth_id IN ('..table.concat(ids, ',')..')'})
	for i, row in ipairs(rows) do
		t[i] = row.iname
	end
	return t
end

local function getUnitInamesByGender(sex)
	local t = {}
	local rows = query('Unit', 'iname', {where='ai = "AI_PLAYER" AND (notsmn IS NULL OR hero = 1) AND server = "gl" AND sex = "'..sex..'"'})
	for i, row in ipairs(rows) do
		t[i] = row.iname
	end
	return t
end

local function getOriginalJobInamesFromJobInames( jobs )
	local t = {}
	local inames = {}
	for i, v in ipairs(jobs) do
		inames[i] = string.format('%q', v)
	end
	if #inames == 0 then return t end
	local rows = query('Job', 'iname, origin', {where = 'iname IN ('..table.concat(inames, ',')..') AND server = "gl"'})
	for i, row in ipairs(rows) do
		t[i] = (row.origin or '') ~= '' and row.origin or row.iname
	end
	return t
end

local function getOriginalJobInamesFromJobGroups( job_groups )
	if type(job_groups) == 'string' then
		job_groups = {job_groups}
	end
	local t, i = {}, 0
	for _, jg_iname in ipairs(job_groups) do
		local job_group = mw.loadData('Module:Data/MasterParam/JobGroup')[jg_iname]
		local inames = getOriginalJobInamesFromJobInames(job_group and job_group.jobs or {})
		for _, iname in ipairs(inames) do
			i = i + 1
			t[i] = iname
		end
	end
	return t
end

local function getUnitInamesFromUnitGroups( unit_groups )
	local t, i = {}, 0
	for _, ug_iname in ipairs(unit_groups) do
		local units = mw.loadData('Module:Data/MasterParam/UnitGroup')[ug_iname].units
		for _, iname in ipairs(units) do
			i = i + 1
			t[i] = iname
		end
	end
	return t
end

local h = {}
function h.printEffects(root, args)
	if not args then return end
	if not args.effects then return end

	local stat = nil
	local card_skills = {}
	local abilities = {}

	for i, eff in ipairs(args.effects) do
		if eff.statusup_skill then
			stat = eff
		end
		if eff.card_skill then
			card_skills[#card_skills+1] = eff
		end
		if eff.abil_iname then
			abilities[#abilities+1] = eff
		end
	end
	
	local maxLevel = maxLevels[args.rare+1]
	if stat then
		root:tag('h2'):wikitext('Stats')
		h.printStatsTable(root, stat.statusup_skill, maxLevel)
	end

	if #card_skills > 0 then
		root:tag('h2'):wikitext('Group skills')
		for i, eff in ipairs(card_skills) do
			local skill = query('Skill, Loc', 'value', {
				where = 'iname = "'..eff.card_skill..'" AND server = "gl" AND param = "name" AND lang = "english"',
				join = 'Skill._pageName = Loc._pageName',
			})[1]

			root:tag('h3'):wikitext(skill.value)
			h.printStatsTable(root, eff.card_skill, maxLevel)
			if eff.add_card_skill_buff_awake then -- limit break buff
				root:tag('h4'):wikitext('Limit Break')
				h.printAddCardSkillBuffAwake(root, eff.add_card_skill_buff_awake)
			end
			if eff.add_card_skill_buff_lvmax then
				root:tag('h4'):wikitext('Max Limit Break')
				local buff = queryBuff(eff.add_card_skill_buff_lvmax)
				local tbl = root:tag('table'):addClass('wikitable')
				local tr = tbl:tag('tr')
				tr:tag('th'):wikitext('Type')
				for lb=5,5 do tr:tag('th'):wikitext('LB'..lb) end
				for i=1,11 do
					tr = tbl:tag('tr')
					if tonumber(buff['type'..i] or 0) > 0 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=5,5 do
							local value = math.floor((lb - 1) * per + min)
							tr:tag('td'):wikitext(string.format('%+d', value))
						end
					end
				end
			end

			if eff.cnds_iname then
				h.printEffect(root, eff)
			end
		end
	end
	if #abilities > 0 then
		root:tag('h2'):wikitext('Vision abilities')

		local function printAbility(root, eff)
			if not eff then return end
			if not eff.abil_iname then return end
			if not eff.abil_iname_lvmax then return end

			local ability = {
				base = queryAbility(eff.abil_iname),
				max = queryAbility(eff.abil_iname_lvmax),
			}

			local baseName = model.getLoc(ability.base._pageName, 'name')
			local maxName = model.getLoc(ability.max._pageName, 'name')
			root:tag('h3'):wikitext(baseName)
			if maxName ~= baseName then
				error('Expected max ability name to be `'..baseName..'` but was `'..maxName..'`.')
			end

			for _, key in ipairs{'base', 'max'} do
				root:tag('h4'):wikitext('Ability '..key)
				local ab = ability[key]
				local abType = ab.type_detail and enums.EAbilityTypeDetail[ab.type_detail] or nil
				if abType ~= 'VisionAbility' then
					error('Expected ability type "VisionAbility", but was "'..tostring(abType)..'".')
				end
				local ul = root:tag('ul')
				if ab.slot then
					local slot = enums.EAbilitySlot[ab.slot]
					ul:tag('li'):wikitext('Slot: [[File:MasterAbilityIcon.png|20px|'..slot..'|link=]] '..slot)
				end
				if ab.skl1 then
					local skill = querySkill(ab.skl1)
					if tonumber(skill.atk_type or 0) > 0 then
						local atk_type = enums.AttackTypes[skill.atk_type]
						if atk_type == 'MagAttack' then
							atk_type = 'Magical'
						elseif atk_type == 'PhyAttack' then
							atk_type = 'Physical'
						end
						ul:tag('li'):wikitext('DMG Type: [[File:Attack Class '..atk_type..'.png|20px|'..atk_type..'|link=]] '..atk_type)
					end
					if tonumber(skill.atk_det or 0) > 0 then
						local atk_det = enums.AttackDetailTypes[skill.atk_det]
						ul:tag('li'):wikitext('ATK Type: [[File:Attack Type '..atk_det..'.png|20px|'..atk_det..'|link=]] '..atk_det)
					end
					if tonumber(skill.elem or 0) > 0 then
						local elem = enums.elemFromKey(skill.elem)
						ul:tag('li'):wikitext('Element: [[File:'..elem..'Element.png|20px|link=]] '..elem)
					end

					-- Explanation
					local expr = model.getLoc(skill._pageName, 'expr')
					root:tag('p'):wikitext(expr)

					-- Skill effect
					if tonumber(skill.eff_type or 0) > 0 and skill.eff_val_ini and skill.eff_val_max then
						local tbl = root:tag('table'):addClass('wikitable')
						tbl:tag('caption'):wikitext('Skill Effect')
						local tr = tbl:tag('tr')
						tr:tag('th'):wikitext('Type')
						tr:tag('th'):wikitext('Min')
						tr:tag('th'):wikitext('Max')
						tr = tbl:tag('tr')
						tr:tag('td'):wikitext(enums.SkillEffectTypes[skill.eff_type])
						tr:tag('td'):wikitext((100+skill.eff_val_ini)..'%')
						tr:tag('td'):wikitext((100+skill.eff_val_max)..'%')
					end

					-- Scaling
					-- Jewel cost
					local ul = root:tag('ul')
					if tonumber(skill.count or 0) > 0 then
						ul:tag('li'):wikitext('Charges: ' .. skill.count)
					end
					if tonumber(skill.cost or 0) > 0 then
						ul:tag('li'):wikitext('Jewel Cost: ' .. skill.cost)
					end
					if tonumber(skill.eff_h or 0) > 0 then
						ul:tag('li'):wikitext('Height: ' .. skill.eff_h)
					end
					if skill.sran then
						ul:tag('li'):wikitext('Select Range: ' .. enums.ESelectType[skill.sran])
						ul:tag('li'):wikitext('Range: ' .. (skill.rangemin or 0) .. '-'.. (skill.rangemax or 0))
					end
					if skill.ssco then
						ul:tag('li'):wikitext('Select Scope: ' .. enums.ESelectType[skill.ssco])
						ul:tag('li'):wikitext('Scope: ' .. (skill.scope or 0))
					end
				end
			end
		end

		for _, eff in ipairs(abilities) do
			printAbility(root, eff)
			if eff.cnds_iname then
				h.printEffect(root, eff)
			end
		end
	end
end

function h.printEffect(root, args)
	-- Stats
	if args.statusup_skill then
		h.printStatsTable(root, args.statusup_skill, args.rare)
	end

	local inames = {}
	-- Condition groups
	for i, iname in ipairs(h.getTriggerGroups(args.cnds_iname) or {}) do
		inames[iname] = inames[iname] or {}
		inames[iname].hasConditions = true
	end
	-- Buff groups
	for i, iname in ipairs(h.getBuffGroups(args.add_card_skill_buff_awake) or {}) do
		inames[iname] = inames[iname] or {}
		inames[iname].hasBuff = true
	end

	local icons = {
		['Trigger + Buff'] = {Unit={},Job={}},
		['Trigger'] = {Unit={},Job={}},
		['Buff'] = {Unit={},Job={}},
		[''] = {Unit={},Job={}},
	}

	for iname, thing in pairs(inames) do
		local triggerbuff = {}
		if thing.hasConditions then
			triggerbuff[#triggerbuff+1] = 'Trigger'
		end
		if thing.hasBuff then
			triggerbuff[#triggerbuff+1] = 'Buff'
		end
		triggerbuff = table.concat(triggerbuff, ' + ')
		local prefix = iname:sub(1,3)
		local tp = prefix == 'UN_' and 'Unit' or prefix == 'JB_' and 'Job' or ''
		local t = icons[triggerbuff][tp]
		local l = #t
		local render_icon = require('Module:Render/'..tp)._icon
		local page = mw.ext.cargo.query('Pages', '_pageName', {where = 'iname = "'..iname..'"'})[1]
		local name
		if page then
			name = page._pageName
		else
			page = query(tp..',Loc', 'value', {where='iname="'..iname..'" AND param="name" AND lang IN ("english","japanese") AND server="gl"', join = tp..'._pageName = Loc._pageName'})[1]
			if page then
				name = page.value
			else
				name = iname
			end
		end
		t[l+1] = {iname=iname, name=name, icon=render_icon{iname, size='small'}}
	end

	if args.add_card_skill_buff_awake then
		for _, triggerbuff in ipairs({'Trigger + Buff', 'Trigger', 'Buff', ''}) do
			for _, tp in ipairs({'Unit', 'Job'}) do
				local objs = icons[triggerbuff][tp]
				if #objs > 0 then
					local heading = root:tag('h4')
					heading:wikitext(tp, ' group')
					if triggerbuff ~= '' then
						heading:wikitext(' (', triggerbuff:lower(), ')')
					end
					table.sort(objs, function(a, b)
						return a.name < b.name
					end)
					for i, obj in ipairs(objs) do
						root:wikitext(obj.icon)
					end
				end
			end
		end
	elseif args.abil_iname then
		local objs = {}
		if #icons.Trigger.Unit > 0 and #icons.Trigger.Job > 0 then
			for _, unit in ipairs(icons.Trigger.Unit) do
				local jb_inames = {}
				local rows = query('Unit, Unit__jobsets, JobSet',
					'JobSet.job = job',
					{
						where = 'Unit.server = "gl" AND JobSet.server = "gl" AND Unit.iname = "'..unit.iname..'"',
						join = 'Unit._ID = Unit__jobsets._rowID, Unit__jobsets._value = JobSet.iname',

					})
				for _, row in ipairs(rows) do
					jb_inames[row.job] = true
				end
				for _, job in ipairs(icons.Trigger.Job) do
					if jb_inames[job.iname] then
						objs[#objs+1] = {unit=unit, job=job}
					end
				end
			end
			local heading = root:tag('h4')
			heading:wikitext('Unit and job restriction')
			table.sort(objs, function(a, b)
				return (a.unit.name < b.unit.name) and (a.job.name < b.job.name)
			end)
			local ul = root:tag('ul')
			for _, obj in ipairs(objs) do
				local li = ul:tag('li')
				li:wikitext(obj.unit.icon, ' + ', obj.job.icon)
			end
		elseif #icons.Trigger.Unit > 0 then
			local heading = root:tag('h4')
			heading:wikitext('Unit restriction')
			for _, obj in ipairs(icons.Trigger.Unit) do
				objs[#objs+1] = obj
			end
			table.sort(objs, function(a,b) return a.name < b.name end)
			for _, obj in ipairs(objs) do
				root:wikitext(obj.icon)
			end
		elseif #icons.Trigger.Job > 0 then
			local heading = root:tag('h4')
			heading:wikitext('Job restriction')
			for _, obj in ipairs(icons.Trigger.Job) do
				objs[#objs+1] = obj
			end
			table.sort(objs, function(a,b) return a.name < b.name end)
			for _, obj in ipairs(objs) do
				root:wikitext(obj.icon)
			end
		end
	end
end

function h.getTriggerGroups(cnds_iname)
	if not cnds_iname then return end
	-- Condition groups
	local conditions = mw.loadData('Module:Data/MasterParam/ConceptCardConditions')[cnds_iname]
	if not conditions then return end

	local t = {}
	if conditions.birth_id then
		for _, iname in ipairs(getUnitInamesByOrigins(conditions.birth_id)) do
			t[#t+1] = iname
		end
	end

	if conditions.job_group then
		for _, iname in ipairs(getOriginalJobInamesFromJobGroups(conditions.job_group)) do
			t[#t+1] = iname
		end
	end

	if conditions.sex then
		for _, iname in ipairs(getUnitInamesByGender(conditions.sex)) do
			t[#t+1] = iname
		end
	end

	if conditions.un_group then
		for _, iname in ipairs(mw.loadData('Module:Data/MasterParam/UnitGroup')[conditions.un_group].units) do
			t[#t+1] = iname
		end
	end

	if conditions.el_dark then
	end
	if conditions.el_fire then
	end
	if conditions.el_shine then
	end
	if conditions.el_thunder then
	end
	if conditions.el_water then
	end
	if conditions.el_wind then
	end
	if conditions.supported_units then
	end

	return t
end

function h.getBuffGroups(buff_iname)
	if not buff_iname then return end
	local buff = queryBuff(buff_iname)
	if not buff then return end

	local t = {}
	for i, ct_iname in ipairs(buff.custom_targets or {}) do
		local custom_target = mw.loadData('Module:Data/MasterParam/CustomTarget')[ct_iname]
		if custom_target.birth_id then
			for _, iname in ipairs(getUnitInamesByOrigins(custom_target.birth_id)) do
				t[#t+1] = iname
			end
		end

		if custom_target.concept_card_groups then
			-- TODO
		end

		if custom_target.jobs then
			for _, iname in ipairs(getOriginalJobInamesFromJobInames(custom_target.jobs)) do
				t[#t+1] = iname
			end
		end
		if custom_target.job_groups then
			for _, iname in ipairs(getOriginalJobInamesFromJobGroups(custom_target.job_groups)) do
				t[#t+1] = iname
			end				
		end

		if custom_target.sex then
			for _, iname in ipairs(getUnitInamesByGender(custom_target.sex)) do
				t[#t+1] = iname
			end
		end
		if custom_target.units then
			for _, iname in ipairs(custom_target.units) do
				t[#t+1] = iname
			end
		end
		if custom_target.unit_groups then
			for _, iname in ipairs(getUnitInamesFromUnitGroups(custom_target.unit_groups)) do
				t[#t+1] = iname
			end
		end
		if custom_target.dark then
		end
		if custom_target.fire then
		end
		if custom_target.shine then
		end
		if custom_target.thunder then
		end
		if custom_target.water then
		end
		if custom_target.wind then
		end
	end
	local un_group = buff.un_group and mw.loadData('Module:Data/MasterParam/UnitGroup')[buff.un_group]
	for _, iname in ipairs(un_group or {}) do
		t[#t+1] = iname
	end
	return t
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)

	local stats = {
		
	}
	for i=1,11 do
		if tonumber(t_buff['type'..i] or 0) > 0 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('h4'):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 tonumber(t_buff['type'..i] or 0) > 0 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('h4'):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 tonumber(t_buff['type'..i] or 0) > 0 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 tonumber(t_buff['type'..i] or 0) > 0 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 tonumber(buff['type'..i] or 0) > 0 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
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
Advertisement