-- This module isolate M:Akopbasic's HTML-generating contents. It accepts an data table as input. -- It should not be called directly – it won't work; it should only be called by M:Akopbaics or M:Akopbasics/canary. -- Crappy code originally by U:公的驱逐舰 (One-Six) of Moegirlpedia. Released under CC BY 4.0. -- update: I shall claim this release as R1.2.0! It's the second merge from the /canary branch. -- As /canary contains no work from other editors, -- this particular version (oldid=5743831) should be safely released under CC BY 4.0 again. -- Thank you to everyone who kept this module alive through 2021. -- Gotta praise the Crocc. --[[ Input requirement. The input datatable d must contain: name dataName rarity = int placementTag radarPPS = preproccessed {{雷达图}} It may (and likely should) contain: categoryArray enName illustrator spIllustrator cv spcv tachieArray = { { label = string, file = string(filename) }, ... } sabunArray = { { string(filename), ... }, ... } otherTachie = { string(filename), ... } faction factionImgPath = preprocessed image path data = { maxHealth, attack, defense, artsResistance, redeploy, cost, block, attackInterval } profession subProfession rangeArray = { { label, rangeString }, ... } tags characteristic talent isRogueOnly = boolean wasRogueOnly = boolean rogueEvents skillArray = { useSwitch = boolean, useItem = boolean, switchPPS = preprocessed {{明日方舟技能条|#style}}{{明日方舟技能条|#skill*#*}}, { icon, skillname, activation, skillPoint, description, masterTabsPPS = preprocessed, tabbed M:明日方舟材料) }, ... } baseSkillArray = { { icon, description }, ... } orderedPotentialBuffArray = { { indexName, data } ... } -- see ./.. for accepted inputs potentialBuffArray = { indexName=data, ... } operatorModule altOpOverride ]]-- local p = {} local getArgs = require ( 'Module:Arguments' ).getArgs local akrange = require ( 'Module:Akrange' ) local akMatData = require ( 'Module:明日方舟材料' )._skill local wrapperArray = { 'Template:沙盒' } -- F: is string empty? local function isEmpty( s ) return (s == nil or s == '') end local function getArgFromAlias ( args, argsAliasArray, defaultReturn ) for i = 1, #argsAliasArray do if ( args[argsAliasArray[i]] ~= nil ) then return args[argsAliasArray[i]] end end return defaultReturn end --[[local function textColorPreprocess ( s ) if isEmpty( s ) then return s end return s:gsub('%<%/text%>','</span>'):gsub('%<trusttext%>','<span class=trusttext>'):gsub('%<(text)%>','<span style=color:') end--]] -- F: generate div.akopbasics. function p.genOpComplex ( frame, d ) local outputString = '<div class="akopbasics" style="max-width: min(1150px, calc(100% - 300px));text-size-adjust: none;-webkit-text-size-adjust: none;-moz-text-size-adjust: none;"><div class="aoc-scroll-wrapper><div class="ak-operator-complex">' -- START aoc-main-tabs-container outputString = outputString .. '<div class="aoc-main-tabs-container" style="position:static;">' .. '<div class="Tabs" data-label-side="top" data-label-color-side-reverse="yes" data-divider-size="0" data-default-tab="1" data-label-color="#EEE" data-text-border-color="transparent" data-text-padding="0" data-label-background-color="#444" data-text-background-color="transparent">' local i = 1 while d.tachieArray[i] ~= nil do outputString = outputString .. '<div class="Tab"><div class="TabLabelText aoc-e-lvl-label">' .. d.tachieArray[i].label ..'</div><div class="TabContentText">[[File:'..d.tachieArray[i].file ..'|x700px]]</div></div>' i = i + 1 end i = 1 while d.sabunArray[i] ~= nil do -- TODO: d.sabunArray[i][1] throws nil error, so d.sabunArray[1] DNE outputString = outputString .. '<div class="Tab"><div class="TabLabelText">表情差分'..( i ~= 1 and tostring(i) or '' )..'</div><div class="TabContentText sabun-tabs">' .. '<div class="Tabs" data-label-side="top" data-label-color-side-reverse="yes" data-divider-size="0" data-default-tab="1" data-label-color="#DDD" data-text-border-color="transparent" data-text-padding="0" data-label-background-color="#555" data-text-background-color="transparent">' for j = 1, #d.sabunArray[i] do outputString = outputString .. '<div class="Tab"><div class="TabLabelText">#'..j..'</div><div class="TabContentText">[[File:'..d.sabunArray[i][j]..'|x666px]]</div></div>' end outputString = outputString .. '</div></div></div>' i = i + 1 end if (#d.otherTachie ~= 0) then outputString = outputString .. '<div class="Tab"><div class="TabLabelText">其他立绘</div><div class="TabContentText sabun-tabs">' .. '<div class="Tabs" data-label-side="top" data-label-color-side-reverse="yes" data-divider-size="0" data-default-tab="1" data-label-color="#DDD" data-text-border-color="transparent" data-text-padding="0" data-label-background-color="#555" data-text-background-color="transparent">' for i = 1, #d.otherTachie do outputString = outputString .. '<div class="Tab"><div class="TabLabelText">#'..i..'</div><div class="TabContentText">[[File:'..d.otherTachie[i]..'|x532px]]</div></div>' end outputString = outputString .. '</div></div></div>' end outputString = outputString .. '</div></div>' -- END aoc-main-tabs-container -- START aoc-faction-logo outputString = outputString .. '<div class="aoc-faction-logo aoc-noselect">' .. '<img src="' .. d.factionImgPath .. '" /><div style="display:none !important;">[[File:Aklogo_'..(d.faction or '罗德岛')..'.png|link=]]</div>' .. '</div>' -- END aoc-faction-logo -- START aoc-left-bottom-box outputString = outputString .. '<div class="aoc-left-bottom-box">' -- START aoc-data outputString = outputString .. '<div class="aoc-data aoc-fullwidth-only" style="width:-moz-fit-content;width:fit-content;">' local dataString = '' dataString = dataString ..'<div>生命上限</div><div>'..(d.data.maxHealth and( d.data.maxHealth .. ( d.potentialBuffArray["生命"] and ( ' <span class=orangetext title="潜能加成">('..d.potentialBuffArray["生命"]..')</span>' ) or '') ) or '暂无数据') ..'</div><div>攻击</div><div>'..(d.data.attack and ( d.data.attack .. ( d.potentialBuffArray["攻击"] and ( ' <span class=orangetext title="潜能加成">('..d.potentialBuffArray["攻击"]..')</span>' ) or '') ) or '暂无数据') ..'</div><div>防御</div><div>'..(d.data.defense and ( d.data.defense .. ( d.potentialBuffArray["防御"] and ( ' <span class=orangetext title="潜能加成">('..d.potentialBuffArray["防御"]..')</span>' ) or '') ) or '暂无数据') ..'</div><div>法术抗性</div><div>'..(d.data.artsResistance and ( d.data.artsResistance .. ( d.potentialBuffArray["法抗"] and ( ' <span class=orangetext title="潜能加成">('..d.potentialBuffArray["法抗"]..')</span>' ) or '') ) or '暂无数据') ..'</div>' ..'<div>再部署</div><div>'..(d.data.redeploy and ( d.data.redeploy .. ( d.potentialBuffArray["再部署"] and ( ' <span class=orangetext title="潜能加成">('..d.potentialBuffArray["再部署"]..'秒)</span>' ) or '') ) or '暂无数据') ..'</div><div>部署费用</div><div>'..(d.data.cost and ( d.data.cost .. ( d.potentialBuffArray["费用"] and ( ' <span class=orangetext title="潜能加成">('..d.potentialBuffArray["费用"]..')</span>' ) or '') ) or '暂无数据') ..'</div><div>阻挡数</div><div>'..(d.data.block and ( d.data.block .. ( d.potentialBuffArray["阻挡"] and ( ' <span class=orangetext title="潜能加成">('..d.potentialBuffArray["阻挡"]..')</span>' ) or '') ) or '暂无数据') ..'</div><div>攻击速度</div><div>'..(d.data.attackInterval and ( d.data.attackInterval .. ( d.potentialBuffArray["攻速"] and ( ' <span class=orangetext title="潜能加成">('..d.potentialBuffArray["攻速"]..')</span>' ) or '') ) or '暂无数据') ..'</div>' outputString = outputString .. dataString .. '</div>' -- END aoc-data -- START aoc-names outputString = outputString .. '<div class="aoc-names">' .. '<div class="aoc-whitestyles aoc-stars">' .. string.rep( '<span style="transform:rotate(16deg);display:inline-block;">★</span>', d.rarity ) .. '</div>' .. '<div class="aoc-whitestyles aoc-name-en">' .. ( d.enName or '' ) .. '</div>' .. '<div class="aoc-whitestyles aoc-name-zh">'..d.name..'</div>' -- illustrator data .. '<div class="aoc-artist">画师:' if d.spIllustrator ~= nil then outputString = outputString .. d.spIllustrator else local i = 1 while not isEmpty ( d.illustrator[i] ) do outputString = outputString .. (i > 1 and ' / ' or '' ) .. ( d.illustrator[i]["nolink"] and d.illustrator[i][1] or ( '[[' .. d.illustrator[i][1] .. (d.illustrator[i][3] and ('|'..d.illustrator[i][3]) or '') .. ']]' ) ) .. ( isEmpty( d.illustrator[i][2] ) and '' or ('<sup>'..d.illustrator[i][2]..'</sup>') ) i = i + 1 end end -- cv data outputString = outputString .. '</div><div class="aoc-cv">配音:' if d.spcv ~= nil then outputString = outputString .. d.spcv else local i = 1 while not isEmpty ( d.cv[i] ) do outputString = outputString .. (i > 1 and ' / ' or '' ) .. ( d.cv[i]["nolink"] and d.cv[i][1] or ( '[[' .. d.cv[i][1] .. (d.cv[i][3] and ('|'..d.cv[i][3]) or '') .. ']]' ) ) .. ( isEmpty( d.cv[i][2] ) and '' or ('<sup>'..d.cv[i][2]..'</sup>') ) i = i + 1 end end outputString = outputString .. '</div>' .. '</div>' -- END aoc-names -- START aoc-prl outputString = outputString .. '<div class="aoc-prl">' .. '<div class="aoc-professions">' .. '<div class="aoc-profession aoc-noselect">' -- if no profession, load a placeholder .. ( d.profession and ('[[File:明日方舟职业 '..d.profession..'.png|50px|'..d.profession..'|alt='..d.profession..'图标|link=]]') or ( '<div role="img" alt="未知" style="' .. 'font-weight:bold;font-size:3em;' .. 'background:linear-gradient(to bottom, #FFF, #888);' .. 'background-clip:text;-webkit-background-clip:text;' .. 'color:transparent;height:50px;' .. 'text-shadow: none;line-height: 1.1em;">' .. '?</div>' ) ) .. '</div><div class="aoc-subprofession">' -- if no sub-profession, load a placeholder .. ( d.subProfession and ( '[[File:明日方舟职业_分支_'..d.subProfession..'.png|40px|link=|alt='..d.subProfession..'图标]]'..'<span style="vertical-align:middle;">'..d.subProfession..'</span>' ) or ( '<div role="img" alt="未知" class="aoc-noselect" style="display:inline-block;font-weight:bold;font-size:1.5em;width:20px;height:20px;text-shadow: none;>?</div>无分支数据' ) ) .. '</div></div>' .. '<div class="aoc-range" >' -- if more than one range datum, use and build tabs if #d.rangeArray > 1 then i = 1 outputString = outputString .. '<div class="Tabs" data-label-side="top" data-label-color-side-reverse="yes" data-divider-size="0" data-default-tab="1" data-label-border-color="transparent" data-label-color="#EEE" data-text-border-color="transparent" data-text-padding="0" data-label-background-color="#444" data-text-background-color="transparent">' while i <= #d.rangeArray do outputString = outputString .. '<div class="Tab"><div class="TabLabelText aoc-e-lvl-label">'..d.rangeArray[i].label..'</div><div class="TabContentText">'..akrange._main( { d.rangeArray[i].rangeString, color="#FFF" } )..'</div></div>' i = i + 1 end outputString = outputString .. '</div>' -- if no range data, load a placeholder elseif isEmpty( d.rangeArray[1].rangeString ) then outputString = outputString .. '<div role="img" alt="未知" class="aoc-noselect" style="font-weight:bold;font-size:3em;height:1em;text-shadow: none; line-height: .8em;">?</div>' -- else there is only one: build directly else outputString = outputString .. akrange._main( { d.rangeArray[1].rangeString, color="#FFF" } ) end outputString = outputString .. '<div class="aoc-prl-labels">攻击范围</div>' .. '</div>' .. '<div class="aoc-location-label">'..(d.placementTag or '')..'</div>' .. '<div class="aoc-other-labels">'..(d.tags or '')..'</div>' .. '</div>' -- END aoc-prl outputString = outputString .. '</div>' -- END aoc-left-bottom-box -- START aoc-radar-container outputString = outputString .. '<div class="aoc-radar-container aoc-fullwidth-only">' .. d.radarPPS .. '</div>' -- END aoc-radar-container -- START aoc-bottom-right-box outputString = outputString .. '<div class="aoc-bottomright-box aoc-fullwidth-only">' local showPotentialBox = not ( d.orderedPotentialBuffArray == nil or ( d.isRouge and not d.wasRouge ) or d.noPotential ) local potentialString = '' if showPotentialBox then potentialString = '<div class="aoc-comp-title">潜能提升</div>' for i = 1, 5 do potentialString = potentialString .. '<div class="aoc-potential-item' .. ( d.orderedPotentialBuffArray[i][1] and '' or ' aoc-pot-item-na' ) .. '">' .. '<div>[[File:明日方舟潜能_' .. i .. '.png|25px|link=|潜能'..i..']]</div><div' .. ( d.orderedPotentialBuffArray[i][1] and ('>'..d.orderedPotentialBuffArray[i][1]..'<br /><span class=orangetext>'..d.orderedPotentialBuffArray[i][2]..(d.orderedPotentialBuffArray[i][1]=='再部署' and '秒' or ''))..'</span>' or ' style="padding-top: calc(9.5px - 0.5em);">N/A' ) .. '</div></div>' end end local charaString = '<div class="aoc-comp-title">特性</div><div>' .. ( d.characteristic or "暂无数据" ) .. '</div>' local talentString = '<div class="aoc-comp-title">天赋</div><div>'.. ( d.talent or "暂无数据" ) .. '</div>' outputString = outputString .. ( showPotentialBox and ( '<div class="aoc-potential">' .. potentialString .. '</div>' ) or '' ) .. '<div class="aoc-characteristic">' .. charaString .. '</div><div class="aoc-talent">' .. talentString.. '</div></div>' -- END aoc-bottomright-box -- END main AOC div outputString = outputString .. '</div></div>' -- START mobile-specific div outputString = outputString .. '<div class="aoc-mobile-alt">' .. '<div class="aoc-data">' .. dataString .. '</div>' .. '<div class="aoc-radar-container"><div class="aoc-radar-outer" style="width:-moz-fit-content;width:fit-content;">' .. d.radarPPS .. '</div></div>' .. charaString .. talentString .. '</div>' -- END mobile-specific div -- bottom table outputString = outputString .. '<table class="wikitable" style="background:#f9f9f9;">' if d.isRogueOnly then outputString = outputString .. '<tr><th colspan="2">Rogue-like Only<br />' .. '<span style="font-weight:normal; font-size:.8em;">该干员' .. ( d.wasRogueOnly and '曾' or '' ) .. '仅在' .. ( d.rogueEvents or '部分集成战略活动' ) .. '中可用' .. ( d.skillArray[1] ~= nil and ',其可用技能等级固定为<span style="color:blue;">7级</span>(进阶前)或<span style="color:blue;">专精三</span>(进阶后)' or '' ) .. '。</span></th></tr>' end if d.skillArray[1] ~= nil then local skillString = '<tr><th colspan=2>技能' .. ( d.skillArray.useSwitch and '<br /><span style="font-weight:normal;font-size:.8em;">默认显示技能等级<span style="color:blue;">7级</span>时的数据。用下方的按钮可以选择不同的技能等级。</span>' or '' ) .. '</th></tr>' .. ( d.skillArray.useSwitch and ( '<tr><th colspan=2>'..d.skillArray.switchPPS..'</th></tr>' ) or '' ) .. '<tr><td colspan=2><div class="aoc-skill-container">' for i = 1, #d.skillArray do skillString = skillString .. '<div class="aoc-skill"><div class="aoc-skill-img-name">' .. ( d.skillArray[i].icon and ( '[[File:' .. d.skillArray[i].icon .. '|80px|技能图标-'..(d.skillArray[i].skillName or ('技能'..i))..'|link=]]' ) or '' ) .. '<div class="aoc-skill-name" style="width:-moz-fit-content;width:fit-content;">' .. ( d.skillArray[i].skillName or '' ) .. '</div>' .. '</div><div class="aoc-skill-activ-sp"><div class="aoc-skill-activation">' .. ( d.skillArray[i].activation or '' ) .. '</div><div class="aoc-skill-sp">' .. ( d.skillArray[i].skillPoint or '' ) .. '</div></div><div class="aoc-skill-desc">' .. ( d.skillArray[i].description or '' ) .. '</div>' .. ( d.skillArray.useItem and d.skillArray[i].masterTabsPPS or '' ) -- aoc-skill-masterTabs .. '</div>' end skillString = skillString .. '</td></tr>' if d.skillArray.useItem then skillString = skillString .. "<tr><th colspan=2>需要材料</th></tr>" .. "<tr><td colspan=2>" .. '技能等级1→2:' .. akMatData( frame, { d.dataName, 'v1' } ) .. '<br/>' .. '技能等级2→3:' .. akMatData( frame, { d.dataName, 'v2' } ) .. '<br/>' .. '技能等级3→4:' .. akMatData( frame, { d.dataName, 'v3' } ) .. '</td></tr>' .. '<tr><td style="width:50px;text-align:center">[[File:精英1+ 图标.png|50px|alt=精英一图标|link=]]</td><td> 晋升材料:'.. akMatData( frame, { d.dataName, 'v10' } ) .. '</td></tr>' .. '<tr><td colspan=2>' .. '技能等级4→5:' .. akMatData( frame, { d.dataName, 'v4' } ) .. '<br/>' .. '技能等级5→6:' .. akMatData( frame, { d.dataName, 'v5' } ) .. '<br/>' .. '技能等级6→7:' .. akMatData( frame, { d.dataName, 'v6' } ) .. '</td></tr>' .. '<tr><td style="width:50px;text-align:center">[[File:精英2 图标.png|50px|alt=精英二图标|link=]]</td><td> '..( d.rarity >= 4 and '晋升材料:'..akMatData( frame, { d.dataName, 'v20' } ) or '该干员尚未得到精英二阶段的晋升。' )..'</td></tr>' if not isEmpty(d.altOpOverride) then skillString = skillString .. "<tr><th colspan=2>异格任务</th></tr>" skillString = skillString ..'<tr><td>解锁条件</td><td>拥有干员[[明日方舟:'.. d.altOpOverride .. '|'..d.altOpOverride..']]</td></tr>' skillString = skillString .. '<tr><td style="width:80px;">提升至精英阶段1等级1</td><td>'.. akMatData( frame, { d.dataName, 'v11' } ) .. '<br/></tr>' if #d.name > #d.altOpOverride then skillString = skillString .. '<tr><td style="width:80px;">提升至精英阶段2等级1</td><td>'.. akMatData( frame, { d.dataName, 'v21' } ) .. '</td></tr>' elseif d.rarity == 3 then skillString = skillString .. '<tr><td style="width:80px;">提升至精英阶段1等级55</td><td>'.. akMatData( frame, { d.dataName, 'v21' } ) .. '</td></tr>' elseif d.rarity == 4 then skillString = skillString .. '<tr><td style="width:80px;">提升至精英阶段1等级60</td><td>'.. akMatData( frame, { d.dataName, 'v21' } ) .. '</td></tr>' elseif d.rarity == 5 then skillString = skillString .. '<tr><td style="width:80px;">提升至精英阶段1等级70</td><td>'.. akMatData( frame, { d.dataName, 'v21' } ) .. '</td></tr>' elseif d.rarity == 6 then skillString = skillString .. '<tr><td style="width:80px;">提升至精英阶段1等级80</td><td>'.. akMatData( frame, { d.dataName, 'v21' } ) .. '</td></tr>' end end end outputString = outputString .. skillString else outputString = outputString .. '<tr><th colspan=2 style="text-align:center;font-style:italic;">该干员暂无技能。</th></tr>' end if d.baseSkillArray[1] ~= nil then local baseSkillString = '<tr><th colspan=2>后勤</th></tr>' for i = 1, #d.baseSkillArray do baseSkillString = baseSkillString .. '<tr><td style="width:50px;background:gray;text-align:center">'..( d.baseSkillArray[i].icon and ('[[File:'..d.baseSkillArray[i].icon..'|30px|后勤技能'..i..'图标|link=]]') or '' )..'</td><td>'..d.baseSkillArray[i].description..'</td></tr>' end outputString = outputString .. baseSkillString else outputString = outputString .. '<tr><th colspan=2 style="text-align:center;font-style:italic;">该干员暂无后勤技能。</th></tr>' end -- END bottom table outputString = outputString .. '</table></div>' i = 1 while d.categoryArray and d.categoryArray[i] do outputString = outputString .. '[[Category:'..d.categoryArray[i]..']]' i = i + 1 end return outputString end return p