-- This is the canary version of M:Akopbasics. New versions are tested here before copy-paste -- deployment to M:Akopbasics. -- This Module should never be called in T:明日方舟干员 save for preview tests. Deployment tests -- should use T:明日方舟干员/canary instead. -- Long-term TODO: modulize T:Tabs and T:雷达图; clear this module of HTML generation -- Crappy code originally by U:公的驱逐舰 (One-Six) of Moegirlpedia. Released under CC BY 4.0. -- Gotta praise the Crocc. local p = {} local getArgs = require ( 'Module:Arguments' ).getArgs local getSabunArray = require ( 'Module:Aksabun' )._getSabunArray local akMatData = require ( 'Module:明日方舟材料' )._skill local genOpComplex = require ( 'Module:Akopbasics/canary/genwikitext' ).genOpComplex local wrapperArray = { 'Template:明日方舟干员', 'Template:明日方舟干员/canary', 'Template:沙盒' } -- F: is string empty? local function isEmpty( s ) return (s == nil or s == '') end -- F: get arguments, alias-aware. Aliases towards the front of the array have priority. 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 -- F: same as getArgFromAlias, but will also ignore empty strings. Default return is still nil, check compatibility. local function getNonEmptyArgs ( args, argsAliasArray, defaultReturn ) for i = 1, #argsAliasArray do if ( not isEmpty( args[argsAliasArray[i]] ) ) then return args[argsAliasArray[i]] end end return defaultReturn end -- F: generate parameter array from string; insert a common string for each instance local function parseArray ( s, ins ) -- When input string is entirely empty, return empty array. if ( isEmpty(s) ) then return {} end -- if common string is empty, make damn sure it's empty, not nil if ( isEmpty(ins) ) then ins = '' end local parsedArray = {} -- \239\188\155 是UTF-8全角分号(";") for temp in (s:gsub("\239\188\155",";"):gsub("[;]?%s*$",";") ):gmatch("([^;]*);%s*") do local tempArray = {} -- \227\128\129 是UTF-8顿号("、") for w in (temp:gsub("\227\128\129","\\"):gsub("[\\]?%s*$","\\")..ins):gmatch("([^\\]*)\\%s*") do tempArray[#tempArray+1] = w end parsedArray[#parsedArray+1] = tempArray end return parsedArray end -- F: generate datatable for genOpComplex. local function genData ( frame, args, opType ) local d = {} -- expected components d.name = getArgFromAlias ( args, { "name", "中文名" } ) -- MUST BE PROVIDED BY USER d.dataName = getArgFromAlias ( args, { "data-name", "数据名" }, d.name ) d.rarity = getArgFromAlias ( args, { "rarity", "稀有度" }, '' ) d.rarity = tonumber( d.rarity ) or #d.rarity/3 d.profession = getArgFromAlias ( args, { "profession","职业" } ) d.placementTag = getArgFromAlias ( args, { "placement-tag","位置标签","站位" } ) if isEmpty(d.placementTag) then if d.profession == "狙击" or d.profession == "术师" or d.profession == "医疗" or d.profession == "辅助" then placementTag = '远程位' elseif d.profession == "先锋" or d.profession == "近卫" or d.profession == "重装" then d.placementTag = "近战位" end end -- the radarPPS monstrosity local radarText = { "物理强度", "战场机动", "生理耐受", "战术规划", "战斗技巧", "源石<br />技艺<br />适应性" } local radarTextOffset = {"-32px","-24px"} local radarNumText = {} local radarNum = {} local radarLookup = { [""] = 0, ["N/A"] = 0, ["---"] = 0, ["缺陷"] = 20, ["普通"] = 40, ["标准"] = 60, ["优良"] = 80, ["卓越"] = 100 } local isRobot = ( string.lower( opType or '' ) == "robot" ) if isRobot then radarText = { "最高速度", "爬坡能力", "制动性能", "通过性", "续航", "结构<br />稳定性" } radarTextOffset = {"-24px","-10px"} radarNumText[1] = getNonEmptyArgs ( args, { "radar-text1","雷达图文字1", "最高速度"},"---" ):gsub("([Kk][Mm]/[Hh])?$","km/h") local speed = radarNumText[1]:gsub("[^0-9%.]*","" ) speed = tonumber( speed ~= '' and speed or 0 ) radarNum[1] = tonumber( getNonEmptyArgs ( args, { "radar-num1","雷达图数值1", "最高速度数值"} ) ) or math.log(speed+1)*12.47+speed radarNumText[6] = getNonEmptyArgs ( args, { "radar-text6","雷达图文字6","结构稳定性" },"---" ) radarNum[6] = tonumber( getNonEmptyArgs ( args, { "radar-num"..6,"雷达图数值"..6, "结构稳定性数值"} ) ) or radarLookup[radarNumText[6]] else radarNumText[1] = getNonEmptyArgs ( args, { "radar-text1","雷达图文字1", "物理强度"},"---" ) radarNum[1] = tonumber( getNonEmptyArgs ( args, { "radar-num1","雷达图数值1", "物理强度数值"} ) ) or radarLookup[radarNumText[1]] radarNumText[6] = getNonEmptyArgs ( args, { "radar-text6","雷达图文字6","源石技艺适应性" },"---" ) radarNum[6] = tonumber( getNonEmptyArgs ( args, { "radar-num6","雷达图数值6","源石技艺适应性数值"} ) ) or radarLookup[radarNumText[6]] end for i = 2, 5 do radarNumText[i] = getNonEmptyArgs ( args, { "radar-text"..i,"雷达图文字"..i,radarText[i] },"---" ) radarNum[i] = tonumber( getNonEmptyArgs ( args, { "radar-num"..i,"雷达图数值"..i, radarText[i].."数值"} ) ) or radarLookup[radarNumText[i]] end local radarString = '{{雷达图|size=100' radarString = radarString .. '|text1=<span class="aoc-radar-cat-text" style="display:inline-block;position:absolute;width:60px;left:-12px;font-size:14px;">'..radarText[1]..'</span>' radarString = radarString .. '|var1='..radarNum[1] radarString = radarString .. '|num1=<span style="display:inline-block;position:absolute;text-align: center;width:max-content;left:6px;top:12px;transform:translateX(-50%);background-color:rgba(255,255,255,0.3);border-radius:5px;font-size:14px;">'..radarNumText[1]..'</span>' radarString = radarString .. '|text2=<span class="aoc-radar-cat-text" style="display:inline-block;position:absolute;width:30px;left:-30px;top:-10px;font-size:14px;">'..radarText[2]..'</span>' radarString = radarString .. '|var2='..radarNum[2] radarString = radarString .. '|num2=<span style="display:inline-block;position:absolute;text-align: center;width:30px;left:-35px;top:5px;background-color:rgba(255,255,255,0.3);border-radius:5px;font-size:14px;">'..radarNumText[2]..'</span>' radarString = radarString .. '|text3=<span class="aoc-radar-cat-text" style="display:inline-block;position:absolute;width:30px;left:-30px;top:-32px;font-size:14px;">'..radarText[3]..'</span>' radarString = radarString .. '|var3='..radarNum[3] radarString = radarString .. '|num3=<span style="display:inline-block;position:absolute;width:30px;left:-35px;top:-27px;background-color:rgba(255,255,255,0.3);border-radius:5px;font-size:14px;">'..radarNumText[3]..'</span>' radarString = radarString .. '|text4=<span class="aoc-radar-cat-text" style="display:inline-block;position:absolute;text-align: center;width:60px;left:-12px;top:-20px;font-size:14px;">'..radarText[4]..'</span>' radarString = radarString .. '|var4='..radarNum[4] radarString = radarString .. '|num4=<span style="display:inline-block;position:absolute;text-align: center;width:30px;left:-7px;top:-35px;background-color:rgba(255,255,255,0.3);border-radius:5px;font-size:14px;">'..radarNumText[4]..'</span>' radarString = radarString .. '|text5=<span class="aoc-radar-cat-text" style="display:inline-block;position:absolute;width:30px;top:'..radarTextOffset[1]..';font-size:14px;">'..radarText[5]..'</span>' radarString = radarString .. '|var5='..radarNum[5] radarString = radarString .. '|num5=<span style="display:inline-block;position:absolute;text-align: center;width:30px;left:5px;top:-27px;background-color:rgba(255,255,255,0.3);border-radius:5px;font-size:14px;">'..radarNumText[5]..'</span>' radarString = radarString .. '|text6=<span class="aoc-radar-cat-text" style="display:inline-block;position:absolute;width:45px;left:-15px;top:'..radarTextOffset[2]..';text-align:center;font-size:14px;">'..radarText[6]..'</span>' radarString = radarString .. '|var6='..radarNum[6] radarString = radarString .. '|num6=<span style="display:inline-block;position:absolute;text-align: center;width:30px;left:5px;top:5px;background-color:rgba(255,255,255,0.3);border-radius:5px;font-size:14px;">'..radarNumText[6]..'</span>' radarString = radarString .. '|color=#999|bgcolor=#333|ftcolor=#000|numcolor=white|num=}}' d.radarPPS = frame:preprocess( radarString ) radarString = nil radarText = nil radarTextOffset = nil radarNumText = nil radarNum = nil radarLookup = nil -- optional components d.categoryArray = {} d.enName = getArgFromAlias ( args, { "en-name", "英文名" } ) d.subProfession = getArgFromAlias ( args, { "sub-profession", "branch", "分支", "characterbranch" } ) d.operatorModule = getArgFromAlias ( args, { "operatorModule", "模组", "characterequipt" } ) d.altOpOverride = getArgFromAlias ( args, { "alt-op-override", "spcharacter", "异格任务" } ) d.spIllustrator = getNonEmptyArgs ( args, { "spIllustrator", "multi-illustrator", "特殊画师", "多位画师" }, nil ) if d.spIllustrator == nil then d.illustrator = parseArray ( getNonEmptyArgs ( args, { "illustrator", "illust", "画师" } ) ) mw.logObject(d.illustrator) if isEmpty ( d.illustrator[1] ) then d.illustrator = nil d.spIllustrator = '无资料' else local i = 1 while not isEmpty ( d.illustrator[i] ) do if d.illustrator[i][3] == "FORCENOLINK" then d.illustrator[i][3] = nil d.illustrator[i]["nolink"] = true end i=i+1 end end end d.spcv = getNonEmptyArgs ( args, { "spcv", "multi-cv", "特殊配音", "多位配音" }, nil ) if d.spcv == nil then d.cv = parseArray ( getNonEmptyArgs ( args, { "cv","配音" } ) ) mw.logObject(d.cv) if isEmpty ( d.cv[1] ) then d.cv = nil d.spcv = '无资料' else -- add CV name(s) into category array. TODO: remove category processing local i = 1 while not isEmpty ( d.cv[i] ) do if d.cv[i][3] == "FORCENOLINK" then d.cv[i][3] = nil d.cv[i]["nolink"] = true end d.categoryArray[#d.categoryArray+1] = d.cv[i][1] i = i + 1 end end end -- tachie array local tachieInfo = { getNonEmptyArgs( args, { "e0name", "初始名" }, "初始"), getNonEmptyArgs( args, { "e0img", "初始图" }, '明日方舟立绘_' .. d.name .. '_1.png' ), getNonEmptyArgs( args, { "e1name", "精一名", "精1名" }, "精英一"), getNonEmptyArgs( args, { "e1img", "精一图", "精1图" }, '明日方舟立绘_' .. d.name .. '_1+.png' ), getNonEmptyArgs( args, { "e2name", "精二名", "精2名" }, "精英二"), getNonEmptyArgs( args, { "e2img", "精二图", "精2图" }, '明日方舟立绘_' .. d.name .. '_2.png' ) } d.tachieArray = {} -- All operators have E0 state and E0 tachie's. Generate unless explicitly disabled. if tachieInfo[1] ~= "FORCENOTAB" then d.tachieArray[#d.tachieArray+1] = { label = tachieInfo[1], file = tachieInfo[2] } end -- Amiya is the only operator right now that possesses E1 tachie; treat as special case, generate unless explicitly disabled. if d.name == '阿米娅' and tachieInfo[3] ~= "FORCENOTAB" then d.tachieArray[#d.tachieArray+1] = { label = tachieInfo[3], file = tachieInfo[4] } end -- All 4star+ operators have E2 states and E2 tachie's. Generate unless explicitly disabled. if d.rarity > 3 and tachieInfo[5] ~= "FORCENOTAB" then d.tachieArray[#d.tachieArray+1] = { label = tachieInfo[5], file = tachieInfo[6] } end tachieInfo = nil -- skins. local skinArray = parseArray ( getArgFromAlias ( args, { "skins","skin","时装","服装" } ) ) for i = 1, #skinArray do -- if no explicit skin filename is provided, generate filename according to naming customs. if isEmpty(skinArray[i][2]) then skinArray[i][2] = '明日方舟立绘_'..d.name..'_skin'..i..'.png' end -- attach skin array. d.tachieArray[#d.tachieArray+1] = { label = skinArray[i][1], file = skinArray[i][2] } end skinArray = nil -- sabun's. TODO: offload work to new M:Aksabun (WIP) d.sabunArray = {} local sabunType = getArgFromAlias ( args, { "sabun-type","差分类型","sabun-type1","差分类型1" } ) local sabunCode = getArgFromAlias ( args, { "sabun-code","差分代号","sabun-code1","差分代号1" } ) local manualSabun = getArgFromAlias ( args, { "manual-sabun1","手动差分1" } ) i = 1 while ( ( not isEmpty( sabunCode ) ) or ( not isEmpty( manualSabun ) ) ) do sabunType = ( sabunType == 'npc' or sabunType == 'avg_npc' ) and 'avg_npc' or 'char' d.sabunArray[#d.sabunArray+1] = getSabunArray ( frame, { verbose = manualSabun, ["suffix-list"] = getArgFromAlias ( args, { "sabun-suffix"..i, "差分后缀"..i } ), ["sabun-type"] = sabunType, ["sabun-code"] = sabunCode, separator = getArgFromAlias ( args, { "sabun-sep"..i, "差分分隔"..i } ), first = getArgFromAlias ( args, { "sabun-f"..i, "差分首"..i } ), last = getArgFromAlias ( args, { "sabun-l"..i, "差分末"..i } ), omit = getArgFromAlias ( args, { "sabun-omit"..i, "差分忽略"..i } ) } ) i = i + 1 sabunType = getArgFromAlias ( args, { ("sabun-type"..i),("差分类型"..i) } ) sabunCode = getArgFromAlias ( args, { ("sabun-code"..i),("差分代号"..i) } ) manualSabun = getArgFromAlias ( args, { "manual-sabun"..i,"手动差分"..i } ) end sabunType = nil sabunCode = nil manualSabun = nil -- other tachie. This includes lone AVG tachie's, tachie of related sub-characters/objects (e.g. summons, pets...), etc. d.otherTachie = parseArray ( getArgFromAlias ( args, { "other-tachie","其他立绘" } ) ) for i = 1, #d.otherTachie do d.otherTachie[i] = d.otherTachie[i][1] end d.faction = getNonEmptyArgs ( args, { "faction","势力" }, "罗德岛" ) d.factionImgPath = frame:callParserFunction('filepath:Aklogo_'..d.faction..'.png') -- main game data. d.data = { maxHealth = getNonEmptyArgs ( args, { "max-health","生命上限" }, '暂无数据' ), attack = getNonEmptyArgs ( args, { "attack","atk","攻击" }, '暂无数据' ), defense = getNonEmptyArgs ( args, { "defense","def","防御" }, '暂无数据' ), artsResistance = getNonEmptyArgs ( args, { "arts-resist","法术抗性" }, '暂无数据' ), redeploy = getNonEmptyArgs ( args, { "redeploy","再部署" }, '暂无数据' ), cost = getNonEmptyArgs ( args, { "cost","部署费用" }, '暂无数据' ), block = getNonEmptyArgs ( args, { "block","阻挡数" }, '暂无数据' ), attackInterval = getNonEmptyArgs ( args, { "atk-int","攻击速度" }, '暂无数据' ) } -- range. Must use Akrange-compatible descrpition strings. d.rangeArray = { { label = 'E0', rangeString = getArgFromAlias ( args, { "E0range","初始范围" } ) } } if not isEmpty(getArgFromAlias ( args, { "E1range","精一范围","精1范围" } )) then d.rangeArray[#d.rangeArray+1] = { label = 'E1', rangeString = getArgFromAlias ( args, { "E1range","精一范围","精1范围" } ) } end if not isEmpty(getArgFromAlias ( args, { "E2range","精二范围","精2范围" } )) then d.rangeArray[#d.rangeArray+1] = { label = 'E2', rangeString = getArgFromAlias ( args, { "E2range","精二范围","精2范围" } ) } end if not isEmpty(getArgFromAlias ( args, { "modulerange","模组范围","模组范围" } )) then d.rangeArray[#d.rangeArray+1] = { label = '模组', rangeString = getArgFromAlias ( args, { "modulerange","模组范围","模组范围" } ) } end -- potential buffs. d.potentialBuffArray = {} -- get raw potential. if it actually exists, then make Lookup table. local rawPotential = getArgFromAlias ( args, { "potential","潜能" } ) if rawPotential then local potentialNameLookup = { ["n/a"] = false, ["false"] = false, [""] = false, [" "] = false, ["nil"] = false, ["生命上限"] = "生命", ["生命"] = "生命", ["health"] = "生命", ["hp"] = "生命", ["攻击力"] = "攻击", ["攻击"] = "攻击", ["attack"] = "攻击", ["atk"] = "攻击", ["防御力"] = "防御", ["防御"] = "防御", ["defense"] = "防御", ["def"] = "生命", ["法术抗性"] = "法抗", ["法抗"] = "法抗", ["arts-resist"] = "法抗", ["ar"] = "法抗", ["再部署时间"]="再部署",["再部署"]="再部署", ["redeploy"]="再部署", ["部署费用"] = "费用", ["费用"] = "费用", ["cost"] = "费用", ["阻挡数"] = "阻挡", ["阻挡"] = "阻挡", ["block"] = "阻挡", ["攻击速度"] = "攻速", ["攻速"] = "攻速", ["atk-int"]= "攻速", ["天赋"] = "天赋", ["talent"] = "天赋", ["第一天赋"] ="天赋一", ["天赋一"]="天赋一", ["talent1"]= "天赋一", ["第二天赋"] ="天赋二", ["天赋二"]="天赋二", ["talent2"]= "天赋二" } -- parse raw potential. d.orderedPotentialBuffArray = {} -- \239\188\155 是UTF-8全角分号(";") i = 1 for item in (rawPotential:gsub("\239\188\155",";"):gsub("[;]?%s*$",";") ):gmatch("([^;]*);%s*") do -- \227\128\129 是UTF-8顿号("、") local tempArray = {} for w in (item:gsub("\227\128\129","\\"):gsub("[\\]?%s*$","\\")):gmatch("([^\\]*)\\%s*") do tempArray[#tempArray+1] = string.lower( w ) end d.orderedPotentialBuffArray[i] = {} d.orderedPotentialBuffArray[i][1] = potentialNameLookup[ tostring ( tempArray[1] ) ] if d.orderedPotentialBuffArray[i][1] then d.orderedPotentialBuffArray[i][2] = tempArray[2] -- remove "秒" and non-number-nor-sign characters local temp = tempArray[2]:gsub('\xe7\xa7\x92$',''):gsub('[^%d+-]','') temp = tonumber( temp ) if temp then d.potentialBuffArray[ d.orderedPotentialBuffArray[i][1] ] = ( d.potentialBuffArray[ d.orderedPotentialBuffArray[i][1] ] or 0 ) + temp end end i = i + 1 end -- if provided potential buff is less then 5, fill the rest with emtpy array while i <= 5 do d.orderedPotentialBuffArray[i] = {} i = i + 1 end rawPotential = nil -- provide plus sign for k,v in pairs(d.potentialBuffArray) do if v > 0 then d.potentialBuffArray[k] = '+'..v end end end -- tag-characteristic-talent d.tags = getArgFromAlias ( args, { "tags","标签" }, '' ) d.characteristic = getNonEmptyArgs ( args, { "characteristic","特性" }, '暂无资料' ) d.talent = getArgFromAlias ( args, { "talent","天赋"}, '' ) if d.talent == '' then local talentComponent = getNonEmptyArgs ( args, { "talent1","天赋1"} ) if talentComponent ~= nil then d.talent = talentComponent talentComponent = getNonEmptyArgs ( args, { "talent2","天赋2"} ) i = 2 while talentComponent do d.talent = d.talent .. '<hr />' .. talentComponent i = i + 1 talentComponent = getNonEmptyArgs ( args, { "talent"..i,"天赋1"..i} ) end else d.talent = '暂无资料' end end d.talent = d.talent:gsub('%<%/talent%>','</span>'):gsub('%<talent%>','<span class="talentblock">') -- rouge stuff local rogueOnlyRaw = string.lower ( getArgFromAlias ( args, { 'rogue-only', '肉鸽限定' }, '' ) ) d.isRogueOnly = ( rogueOnlyRaw == "true" or rogueOnlyRaw == "yes" or rogueOnlyRaw == "是" or rogueOnlyRaw == "was" or rogueOnlyRaw == "曾" ) d.wasRogueOnly = ( rogueOnlyRaw == "was" or rogueOnlyRaw == "曾" ) rogueOnlyRaw = nil d.rogueEvents = getNonEmptyArgs ( args, { 'rogue-events', 'rogue-event', '肉鸽活动' } ) -- skills and related material consumptions d.skillArray = {} d.skillArray.useSwitch = string.lower( getArgFromAlias ( args, { 'skill-switch', '技能切换' }, '' ) ) d.skillArray.useSwitch = not ( d.skillArray.useSwitch == "false" or d.skillArray.useSwitch == "no" or d.skillArray.useSwitch == "否" ) d.skillArray.useItem = string.lower( getArgFromAlias ( args, { 'display-item', '显示材料' }, '' ) ) d.skillArray.useItem = not ( d.skillArray.useItem == "false" or d.skillArray.useItem == "no" or d.skillArray.useItem == "否" ) local possibleSkillDesp = getArgFromAlias ( args, { "sk1", "技能1", "技能一" } ) local i = 1 local skillLookup = { '一', '二', '三', '' } -- need an extra item so skillLookup[i+1] after the last item is exhausted wouldn't throw err while possibleSkillDesp ~= nil and i <= #skillLookup - 1 do local tabString = ( d.skillArray.useItem and d.rarity >= 4 ) and frame:preprocess( "{{tabs|color=black aoc-skill-masterTabs|DefaultTab=1|AutoWidth=yes" ..'|bt1=专精一|tab1=[[File:明日方舟技能专精 1.png|50px|link=]]' .. akMatData ( frame, { d.dataName, 'v'..i..'7' } ) ..'|bt2=专精二|tab2=[[File:明日方舟技能专精 2.png|50px|link=]]' .. akMatData ( frame, { d.dataName, 'v'..i..'8' } ) ..'|bt3=专精三|tab3=[[File:明日方舟技能专精 3.png|50px|link=]]' .. akMatData ( frame, { d.dataName, 'v'..i..'9' } )..'}}' ) or '' d.skillArray[i] = { skillName = getArgFromAlias ( args, { ('sk'..i..'name'), ('技能'..i..'名称'), ('技能'..skillLookup[i]..'名称') } ), activation = getArgFromAlias ( args, { "sk"..i.."a", "技能"..i.."触发", "技能"..skillLookup[i].."触发" }, ''), skillPoint = getArgFromAlias ( args, { "sk"..i.."sp", "技能"..i.."技力", "技能"..skillLookup[i].."技力" }, ''), description = possibleSkillDesp, masterTabsPPS = tabString } d.skillArray[i].icon = getArgFromAlias ( args, { "skill"..i.."icon", "技能"..i.."图", "技能"..skillLookup[i].."图", "技能"..i.."补", "技能"..skillLookup[i].."补" }, '明日方舟技能_'..(d.skillArray[i].skillName or '')..'.png' ) i = i + 1 possibleSkillDesp = getArgFromAlias ( args, { "sk"..i, "技能"..i, "技能"..skillLookup[i] } ) end d.skillArray.switchPPS = frame:expandTemplate { title = '明日方舟技能条', ["args"] = { [1]='#style' } } -- '<templatestyles src="Template:明日方舟技能条/style.css" />' if d.rarity >= 4 then -- don't know why the and-or shorthand doesn't work d.skillArray.switchPPS = d.skillArray.switchPPS .. frame:expandTemplate { title = '明日方舟技能条', ["args"] = { [1]='#skill2' } } else d.skillArray.switchPPS = d.skillArray.switchPPS .. frame:expandTemplate { title = '明日方舟技能条', ["args"] = { [1]='#skill1' } } end -- base skills. d.baseSkillArray = {} i = 1 local baseSkDesp = getArgFromAlias ( args, { "bsk"..i, "后勤"..i } ) while baseSkDesp do d.baseSkillArray[#d.baseSkillArray+1] = { icon = getArgFromAlias ( args, { "bsk-icon"..i, "后勤"..i.."图标" } ), description = baseSkDesp } i = i + 1 baseSkDesp = getArgFromAlias ( args, { "bsk"..i, "后勤"..i } ) end --if not in article space, destroy category array if frame:preprocess('{{NAMESPACENUMBER}}') ~= '0' then d.categoryArray = nil end return d end function p.main ( frame ) local args = getArgs ( frame, { wrappers = wrapperArray } ) return p._exposed ( frame, args, "normal" ) end function p.robot ( frame ) local args = getArgs ( frame, { wrappers = wrapperArray } ) return p._exposed ( frame, args, "robot" ) end function p.exposed ( frame ) local args = getArgs ( frame, { wrappers = wrapperArray } ) return p._exposed ( frame, args, args["op-type"] ) end function p._exposed ( frame, args, opType ) return genOpComplex ( frame, genData ( frame, args, opType ) ) end return p