七日内新公告:全站维护公告
  • 你好~!欢迎来到萌娘百科镜像站!如需查看或编辑,请联系本站管理员注册账号。
  • 本镜像站和其他萌娘百科的镜像站无关,请注意分别。

Module:Aklevelinfo

贴贴♀百科,万娘皆可贴的百科全书!转载请标注来源页面的网页链接,并声明引自贴贴百科。内容不可商用。
跳转到导航 跳转到搜索
模块文档  [查看] [编辑] [历史] [刷新]

本模块用来生成明日方舟关卡的介绍表格。

由于模板包装({{Aklevelinfo}})已经实装,本文档不再更新。如果本模块的用法发生了变化,该包装模板的文档会继续更新。

语法

模板描述字符串

本模块采用了一种特定的描述字符串来方便地简写大量重复模板引用。模块中已经提前定义了模板头名字和一些特定参数;每一个模板实例应当用全角分号(;)或半角分号(;)分开;每一个模板的参数应当用顿号(、)或斜杠(/)分开。两种符号可以混用。

例如,在主线2-1“敌人”一行,原本描述敌人需要这样的 wikitext:

{{Akenicon|源石虫·α|B2|size=90|unit=px}}{{Akenicon|猎狗|O1|size=90|unit=px}}{{Akenicon|士兵|01|size=90|unit=px}}{{Akenicon|重装防御者|08|size=90|unit=px}}{{Akenicon|暴徒|17|size=90|unit=px}}{{Akenicon|鸡尾酒投掷者|A9|size=90|unit=px}}{{Akenicon|机动盾兵|19|size=90|unit=px}}

在模块中,使用的模板(Akenicon)已经被提前定义,同时还为每一个模板自动赋了大小参数(size);这些内容便可移除。再将参数分隔符(管道符,|)替换成顿号或斜杠(此处用顿号)、每个模板实例之间用分号隔开(此处用全角),得到以下描述字符串:

源石虫·α、B2;猎狗、O1;士兵、01;重装防御者、08;暴徒、17;鸡尾酒投掷者、A9;机动盾兵、19

只要给模块提供这个字符串就可以了。

因为技术原因,此语法不允许描述字符串以实例分隔符(即任意类型的分号)结尾:这种时候,解析器会以为最后一个模板引用是空引用(无参数)。敬请注意。

模块结构

本模块只有一个外部函数:主函数(main)。

主函数没有固定的参数数量。以下列出所有可能的参数。参数别名可以混用(中文和英文参数名可以交叉),但是若多个别名被同时使用,靠前的别名更优先。

参数 说明 类型 默认值
表格 ID id 整个表格的HTML ID。同时可以作为跳转锚点。 选填 参数“关卡代码”的值
表格 class class 整个表格的CSS class。 选填 无
关卡代码 level-code关卡代码代码 本关卡的代码(如1-1、DM-6等)。若本参数为空则不会生成表格标题。 建议 无
关卡名称 level关卡 本关卡的名称。若本参数为空则不会生成表格标题。 建议 无
开放时间 time开放时间时间 本关卡开放的时间,用于限时开启的活动关卡。时间格式应满足#time的格式,包含年、月、日、时、分。使用模板描述字符串:将开始和结束时间视为一对模板参数;如果因复刻有多个开启时间,视每对开启时间为一个模板。 选填 无
关卡消耗 cost消耗 进行本关卡需要消耗的资源。如果消耗理智,可以直接填入数字;否则,使用模板描述字符串:模板为{{Akmat}},已赋大小参数。 选填 0
部署上限 max-dep部署上限 本关卡的干员部署上限。应当是一个数字。 建议 无
固定编队 preset固定编队编队 本关卡的固定编队,用于阵容不可替换的关卡。使用模板描述字符串:模板为{{Akcharinfo}},已赋大小参数。 选填 无
自动部署干员 autodeploy自动部署 本关卡的自动部署干员,用于有由系统自动部署或者提前部署之干员的关卡。使用模板描述字符串:模板为{{Akcharinfo}},已赋大小参数。 选填 无
推荐平均等级 rec-lvl推荐等级 本关卡的推荐平均等级。应当是诸如“LV.15”、“精英1 LV.30”这样的字符串。 选填 无
敌方情报 enemy敌人 本关卡的敌方情报。使用模板描述字符串:模板为{{Akenicon}},已赋大小参数。 建议 无
特殊机制 sp-mech特殊机制 本关卡的特殊机制(诸如障碍物、地雷等我方召唤物,弩箭等敌方召唤物,和其他地图特性)。应当是字符串;建议用如同&lt;障碍物&gt;(效果如<障碍物>)的方法标识机制名称,并且在不同机制间用<br />换行。 选填 无
附加信息 add-info附加信息 本关卡的附加信息。如果本关卡有一些特殊的细节不便视为“机制”,可以以字符串形式填在这里。 选填 无
首次掉落 fd首次掉落 本关卡的首次掉落数据。使用模板描述字符串:模板为{{Akitem}},已赋大小参数。 建议 无
常规掉落 nd常规掉落 本关卡的常规掉落数据。使用模板描述字符串:模板为{{Akitem}},已赋大小参数。 选填 无
额外掉落 ed额外掉落 本关卡的额外掉落数据。使用模板描述字符串:模板为{{Akitem}},已赋大小参数。 选填 无
特殊掉落 sd特殊掉落 本关卡的特殊掉落数据。使用模板描述字符串:模板为{{Akitem}},已赋大小参数。 选填 无
特殊掉落𝑛 sd𝑛 特殊掉落𝑛 本关卡的特殊掉落数据,𝑛 ⩾ 2;参数名如同sd2、特殊掉落4等。用于复刻活动的特殊掉落数据不同的关卡;𝑛代表第几次开放。使用模板描述字符串:模板为{{Akitem}},已赋大小参数。 选填 无
突袭附加条件 hard-limit突袭附加条件突袭限制 本关卡的突袭附加条件。应当是字符串。 选填 无
突袭解锁条件 hard-unlock突袭解锁条件突袭解锁 本关卡的突袭解锁条件。应当是字符串。 选填 无
突袭首次掉落 hfd突袭首次掉落突袭掉落 本关卡的突袭首次掉落。使用模板描述字符串:模板为{{Akitem}},已赋大小参数。 选填 无
无敌人图鉴 no-enemy-data无敌人图鉴无敌人资料 用于不能查看敌人图鉴的关卡。为本参数赋值true、t、yes、y、是(全部忽略大小写)的时候,模块会忽略“敌方情报”参数,并强制显示“当前关卡无法查看敌人图鉴”;其他赋值全部无效果。 选填 无

任何参数都可以省略或者留空;此时除非该参数有默认值,否则其在表格中对应的那一行(若有)就会被省略。

模块骨干

{{#invoke:Aklevelinfo|main
|id=
|class=
|level=
|level-code=
|time=
|cost=
|max-dep=
|rec-lvl=
|enemy=
|sp-mech=
|add-info=
|fd=
|nd=
|ed=
|sd=
|hard-limit=
|hard-unlock=
|hfd=
}}

或

{{#invoke:Aklevelinfo|main
|id=
|class=
|关卡=
|关卡代码=
|开放时间=
|消耗=
|部署上限=
|推荐等级=
|特殊机制=
|附加信息=
|敌人=
|首次掉落=
|常规掉落=
|额外掉落=
|特殊掉落=
|突袭附加条件=
|突袭解锁条件=
|突袭首次掉落=
}}

示例

{{#invoke:Aklevelinfo|main
|class=mw-collapsible mw-collapsed
|level=火山制造
|level-code=OF-1
|time=201908271600/201909100359;202008111600/202008200359;202108091600/202108180359
|cost=8
|max-dep=8
|rec-lvl=LV.15
|enemy=源石虫、B1;源石虫·β、B3;酸液源石虫、B4
|fd=fur、萨卡兹摇滚海报、dt=首次掉落;mat、至纯源石、dt=三星获得
|nd=mat、至纯源石、dt=三星获得
|ed=mat、至纯源石、dt=三星获得
|sd=mat、汐斯塔的黑曜石、num=8;mat、黑曜石节门票、num=2
|sd2=mat、汐斯塔的黑曜石、num=10;mat、黑曜石节门票、num=2
|sd3=mat、汐斯塔的黑曜石、num=8;mat、黑曜石节门票、num=2
|hard-limit=禁止部署近战干员
|hfd=mat、至纯源石、dt=三星获得、num=2
}}

会输出

OF-1 火山制造
开放时间
【首次】
2019/08/27 16:00
至
2019/09/10 03:59
【复刻】
2020/08/11 16:00
至
2020/08/20 03:59
【复刻】
2021/08/09 16:00
至
2021/08/18 03:59
消耗理智
理智
8
部署上限8人
推荐平均等级LV.15
敌方情报
源石虫
源石虫
B1
源石虫·β
源石虫·β
B3
酸液源石虫
酸液源石虫
B4
首次掉落
家具
萨卡兹摇滚海报
首次掉落
至纯源石三星获得
常规掉落
至纯源石三星获得
特殊掉落
汐斯塔的黑曜石
8
黑曜石节门票
2
汐斯塔的黑曜石
10
黑曜石节门票
2
汐斯塔的黑曜石
8
黑曜石节门票
2
额外掉落
(小概率掉落)
至纯源石三星获得
突袭附加条件禁止部署近战干员
突袭首次掉落
至纯源石
2
三星获得
磨难险地附加条件禁止部署近战干员
磨难险地首次掉落
至纯源石
2
三星获得
磨难险地敌方情报
源石虫
源石虫
B1
源石虫·β
源石虫·β
B3
酸液源石虫
酸液源石虫
B4
{{#invoke:Aklevelinfo|main
|class=mw-collapsible mw-collapsed
|关卡=水上滑梯
|代码=OF-F1
|time=
|消耗=黑曜石节门票、num=6
|部署上限=8
|推荐等级=LV.15
|自动部署=安德切尔、0、攻击力强化·α型、1、20、0、false
|固定编队=安洁莉娜、2、秘杖·反重力模式、9、20、0、false;史都华德、0、强力击·α型、1、20、0、false;杰西卡、0、强力击·β型、1、20、0、false;芬、0、冲锋号令·α型、1、20、0、false; 翎羽、0、迅捷打击·α型、1、20、0、false;炎熔、0、战术咏唱·α型、1、20、0、false; 黑角、0、、0、20、0、false
|敌人=源石虫、B1;源石虫·β、B3;酸液源石虫、B4
|首次掉落=fur、萨卡兹摇滚海报、dt=首次掉落;mat、至纯源石、dt=三星获得
|常规掉落=mat、至纯源石、dt=三星获得
|额外掉落=mat、至纯源石、dt=三星获得
|特殊掉落=mat、汐斯塔的黑曜石、num=8;mat、黑曜石节门票、num=2
|突袭附加条件=禁止部署近战干员
|突袭掉落=mat、至纯源石、dt=三星获得、num=2
}}

会输出

OF-F1 水上滑梯
消耗
黑曜石节门票
6
部署上限8人
自动部署干员
L V201
固定编队
L V20
L V201
L V201
L V201
L V201
L V201
L V20
推荐平均等级LV.15
敌方情报
源石虫
源石虫
B1
源石虫·β
源石虫·β
B3
酸液源石虫
酸液源石虫
B4
首次掉落
家具
萨卡兹摇滚海报
首次掉落
至纯源石三星获得
常规掉落
至纯源石三星获得
特殊掉落
汐斯塔的黑曜石
8
黑曜石节门票
2
额外掉落
(小概率掉落)
至纯源石三星获得
突袭附加条件禁止部署近战干员
突袭首次掉落
至纯源石
2
三星获得
-- This is to automate level description table generation for Arknights.
-- Crappy code originally by U:公的驱逐舰 (One-Six) of Moegirlpedia.
-- Gotta praise the Crocc. 
local getArgs = require('Module:Arguments').getArgs
local Akcharinfo = require('Module:Akcharinfo')._main

local p = {}

-- 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 )
	for i = 1, table.getn(argsAliasArray) do
		if ( args[argsAliasArray[i]] ~= nil ) then
			return args[argsAliasArray[i]]
		end
	end
	return nil
end

-- F: generate raw wikitext of repeated template calls from parameter array
local function repeatedTempWT ( tempName, paraArray )
	local outputStr = ""
	for i = 1, #paraArray do
		outputStr = outputStr.."{{"..tempName
		for j = 1, #paraArray[i] do
			outputStr = outputStr.."|"..paraArray[i][j]
		end
		outputStr = outputStr.."}}"
	end
	return outputStr
end
-- F: generate repeated module calls from parameter array
local function repeatedModuleWT ( frame, moduleFunc, paraArray )
	outputStr = ""
	for i = 1, #paraArray do
		outputStr = outputStr .. moduleFunc ( frame, paraArray[i] )
	end
	return outputStr
end

-- F: generate parameter array from string; insert a common string for each instance
local function parseArray ( s, ins, forModule )
	-- 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
	if ( forModule ~= true ) then
		forModule = false
	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
			if forModule and (string.match( w, "^[^=]*=.*$" )) then
				tempArray[ string.match( w, "^([^=]*)=" ) ] = string.match( w, "^[^=]*=(.*)$" )
			else
				table.insert(tempArray, w)
			end
		end
	   	table.insert(parsedArray, tempArray) 
	end
	return parsedArray
end

-- WIP. TODO: check for total cell width, autocollapse nonexistant cells to the left
local function  buildDropCells ( frame, args, datas, argsNameArray, timeArraySize )
	local returnString = '<th'..(datas.thStyle and (' style='..datas.thStyle) or '')..'>'..datas.head..'</th><td>'
	local ri1 = getArgFromAlias( args, argsNameArray )
	if timeArraySize <= 1 then
		returnString = isEmpty(ri1) and '' or ( returnString .. frame:preprocess( repeatedTempWT( datas.template, parseArray(ri1, datas.ins) ) ) .. '</td>' )
	else
		local dataArray = { { ri1 } }
		for i = 1, timeArraySize do
			
		end
	end
	return returnString
end

-- make standard th cell
local function thCell ( colspan, str1, str2, style )
	return '<th '
		.. ( colspan > 1 and ( 'colspan' .. colspan ) or '' )
		.. 'style="min-width:'..( (#str1/9) + 0.2 )..'em;'
		.. ( style or '' )
		.. '"><span style="white-space:nowrap;">' .. str1.. '</span>'
		.. ( str2 and ( '<wbr /><span style="white-space:nowrap;">' .. str2.. '</span>' ) or '' )
		.. '</th>'
end

-- main: generate and output the level description table. 
-- Support arbitrary numbers of event reruns, but we will eventually run out of screen space; may need a outer scrollable shell.
function p.main ( frame )
	local args = getArgs(frame, {
	wrappers = {
			'Template:Aklevelinfo',
			'Template:沙盒'
		}
	})
	return p._main ( frame, args )
end
function p._main ( frame, args )
-- build access time row first, as it impact styling of the rest of the table (colspan count). 
	local timeArray = parseArray( getArgFromAlias( args, { "time", "开放时间", "时间" } ))
	local timeStr = '<tr>' .. thCell( 1, '开放', '时间' )
	-- td head for trivial rows.
	local defaultMainCell = "<td>"
	-- if time array is empty (check by if first instance exist), do not generate time array.
	if ( timeArray[1] == nil ) then
		timeStr = ''
	elseif ( #timeArray > 1 ) then
		-- trivial row colspan.
		defaultMainCell = "<td colspan="..#timeArray..">"
		for i = 1, #timeArray do
			timeStr = timeStr .. '<td><div style="display:grid"><div style="grid-area:1/1/2/2;white-space:nowrap;">'
				.. ( isEmpty(timeArray[i][3]) and (i == 1 and '【首次】' or '【复刻】') or'【'.. timeArray[i][3]..'】' )
				.. '</div><div style="grid-area:1/2/2/3">'
				.. frame:callParserFunction( "#time:Y/m/d H:i", timeArray[i][1] )
				.. '</div><div style="grid-area:2/1/3/2; text-align:center;">至</div><div style="grid-area:2/2/3/3">'
				.. ( isEmpty(timeArray[i][2]) and '现在' or frame:callParserFunction( "#time:Y/m/d H:i", timeArray[i][2] ) )
				.. '</div></div></td>'
		end
		timeStr = timeStr .. '</tr>'
	else
		timeStr = timeStr .. '<td>' 
			.. frame:callParserFunction( "#time:Y/m/d H:i", timeArray[1][1] )
			.. ' 至 '
			.. ( isEmpty(timeArray[1][2]) and '现在' or frame:callParserFunction( "#time:Y/m/d H:i", timeArray[1][2] ) )
			.. "</td></tr>"
	end
-- Get level code and level name, and build the title.
	local levelCode = getArgFromAlias( args, { "level-code", "关卡代码", "代码" } )
	local level =getArgFromAlias( args, { "level", "关卡" } )
	local titleStr = isEmpty(level) and '' or ( 
		'<tr><th colspan=' .. ( #timeArray < 1 and '2' or ( #timeArray + 1 ) ) .. '>'
		.. ( levelCode and ( levelCode .. ' ' ) or '' )
		.. level
		.. "</th></tr>" )
	-- keeping level code for id use; keeping #timeArray for some colspan use
	level = nil
	local timeArraySize = #timeArray
	timeArray = nil
-- end time and title.
-- cost. If empty, say sanity cost 0; elseif number, use as sanity; else parse array and use repeatedTempWT.
	local costToEnmStr = ""
	local cost = getArgFromAlias( args, { "cost", "消耗" } );
	if ( cost == nil ) then
		cost = ""
	end
	if (isEmpty(cost) ) then
		costToEnmStr = costToEnmStr .. '<tr>' .. thCell( 1, '消耗', '理智' ) .. defaultMainCell .. frame:expandTemplate{ title = 'Akitem', args = { "mat", "理智", num="0", size="60"} } .. "</td></tr>"
	elseif ( cost:gsub("%d+","APREDEFINEDSTRING") == "APREDEFINEDSTRING" ) then
		costToEnmStr = costToEnmStr .. '<tr>' .. thCell( 1, '消耗', '理智' ) .. defaultMainCell .. frame:expandTemplate{ title = 'Akitem', args = { "mat", "理智", num=cost, size="60"} } .. "</td></tr>"
	else
		costToEnmStr = costToEnmStr .. '<tr>' .. thCell( 1, '消耗', '' ) .. defaultMainCell .. frame:preprocess( repeatedTempWT( "Akmat", parseArray( cost, "size=60/") ) ) .. "</td></tr>"
	end
	cost = nil
-- up to five trivial rows. 
-- Team preset, auto-deployment, and enemy row requires repeatedTempWT.
	local maxDeployment = getArgFromAlias( args, { "max-dep", "部署上限" } )
	local presetArray = parseArray( getArgFromAlias( args, { "preset", "固定编队", "编队" } ), "size=90/", true )
	local recAvgLvl = getArgFromAlias( args, { "rec-lvl", "推荐等级" } )
	local autodeployedArray = parseArray( getArgFromAlias( args, { "autodeploy", "自动部署" } ), "size=90/", true )
	local noEnemyData = string.lower ( getArgFromAlias( args, { "no-enemy-data", "无敌人图鉴", "无敌人资料" } ) or '' )
	noEnemyData = ( noEnemyData == "true" or noEnemyData == "yes" or noEnemyData == "t" or noEnemyData == "y" or noEnemyData == "是" )
	local enemyParaArray = parseArray( getArgFromAlias( args, { "enemy", "敌人" } ), "size=90/" )
	if ( not isEmpty(maxDeployment) ) then
		costToEnmStr = costToEnmStr .. '<tr>' .. thCell( 1, '部署', '上限' ) .. defaultMainCell .. maxDeployment .. "人</td></tr>"
	end
	if ( autodeployedArray[1] ~= nil ) then
		costToEnmStr = costToEnmStr .. '<tr><th style="min-width:3.2em;" title="关卡开始时和/或进行中由系统部署的干员,通常不可由玩家手动撤退">自动部<wbr />署干员</th>' .. defaultMainCell .. repeatedModuleWT( frame, Akcharinfo, autodeployedArray ) .. "</td></tr>"
	end
	if ( presetArray[1] ~= nil ) then
		costToEnmStr = costToEnmStr .. '<tr><th style="min-width:2.2em;" title="关卡提供的固定编队,玩家不可更改">固定<wbr />编队</th>' .. defaultMainCell
			.. ( ( presetArray[1][1] == nil and ( presetArray[1] == '空' or string.lower(presetArray[1]) == 'empty' ) ) and
				'<span style="display:inline-block; margin:1em 0; font-style:italic;">该关卡固定编队为空且不可更换</span>' or
				( repeatedModuleWT( frame, Akcharinfo, presetArray ) )
			) .. "</td></tr>"
	end
	if ( not isEmpty(recAvgLvl) ) then
		costToEnmStr = costToEnmStr .. '<tr>' .. thCell( 1, '推荐平', '均等级' ) .. defaultMainCell .. recAvgLvl .. "</td></tr>"
	end
	if ( noEnemyData or enemyParaArray[1] ~= nil ) then
		costToEnmStr = costToEnmStr .. '<tr>' .. thCell( 1, '敌方', '情报' ) .. defaultMainCell
			.. ( noEnemydata and
				'<span style="display:inline-block; margin:1em 0; font-style:italic;">该关卡无法查看敌人图鉴</span>' or
				frame:preprocess( repeatedTempWT( "Akenicon", enemyParaArray ) )
			) .. "</td></tr>"
	end
	maxDeployment = nil
	recAvgLvl = nil
	noEnemyData = nil
	enemyParaArray = nil
	-- Additional info, including special mechanism and "additional info"
	local spMech = getArgFromAlias( args, { "sp-mech", "特殊机制" } )
	local addInfo = getArgFromAlias( args, { "add-info", "附加信息" } )
	if ( not isEmpty(spMech) ) then
		costToEnmStr = costToEnmStr .. '<tr>' .. thCell( 1, '特殊', '机制' ) .. defaultMainCell .. spMech .. "</td></tr>"
	end
	if ( not isEmpty(addInfo) ) then
		costToEnmStr = costToEnmStr .. '<tr>' .. thCell( 1, '附加', '信息' ) .. defaultMainCell .. addInfo .. "</td></tr>"
	end
	spMech = nil
	addInfo = nil
	-- item drops. fd, nd, and ed are trivial and requires repeatedTempWT; sd requires checking.
	local firstDropParaArray = parseArray( getArgFromAlias( args, { "fd", "首次掉落" } ), "size=60/" )
	local normalDropParaArray = parseArray( getArgFromAlias( args, { "nd", "常规掉落" } ), "size=60/" )
	local extraDropParaArray = parseArray( getArgFromAlias( args, { "ed", "额外掉落" } ), "size=60/" )
	local dropStr = ""
	if ( firstDropParaArray[1] ~= nil ) then
		dropStr = dropStr .. '<tr>' .. thCell( 1, '首次', '掉落' ) .. defaultMainCell .. frame:preprocess( repeatedTempWT( "Akitem", firstDropParaArray ) ) .. "</td></tr>"
	end
	if ( normalDropParaArray[1] ~= nil ) then
		dropStr = dropStr .. '<tr>' .. thCell( 1, '常规', '掉落' ) .. defaultMainCell .. frame:preprocess( repeatedTempWT( "Akitem", normalDropParaArray ) ) .. "</td></tr>"
	end
	-- display sd's up to timeArraySize.
	local sd = getArgFromAlias( args, { "sd", "特殊掉落" } )
	if ( timeArraySize > 1 ) then
		local sdStr = '<tr>' .. thCell( 1, '特殊', '掉落' ) .. '<td>'
		local sdStrIsEmpty = true
		if ( not isEmpty(sd) ) then
			sdStr = sdStr .. frame:preprocess( repeatedTempWT( "Akitem", parseArray(sd, "size=60/") ) )
			sdStrIsEmpty = false
		end
		sdStr = sdStr .. "</td>"
		for i = 2, timeArraySize do
			sdStr = sdStr .. '<td>'
			local sdi = getArgFromAlias( args, { "sd"..i, "特殊掉落"..i } )
			if ( not isEmpty(sdi) ) then
				sdStr = sdStr .. frame:preprocess( repeatedTempWT( "Akitem", parseArray(sdi, "size=60/") ) )
				sdStrIsEmpty = false
			end
			sdStr = sdStr .. "</td>"
		end
		sdStr = sdStr .. "</tr>"
		if ( not sdStrIsEmpty ) then
			dropStr = dropStr .. sdStr
		end
	elseif ( not isEmpty(sd) ) then
		dropStr = dropStr .. '<tr>' .. thCell( 1, '特殊', '掉落' ) .. defaultMainCell .. frame:preprocess( repeatedTempWT( "Akitem", parseArray(sd, "size=60/") ) ) .. "</td></tr>"
	end
	sd = nil
	-- extra drop.
	if ( extraDropParaArray[1] ~= nil ) then
		dropStr = dropStr .. '<tr><th style="min-width:2.2em;">额外<wbr />掉落<br /><span style="font-size:75%;white-space:nowrap;">(小概率掉落)</span></th>' .. defaultMainCell .. frame:preprocess( repeatedTempWT( "Akitem", extraDropParaArray ) ) .. "</td></tr>"
	end
	firstDropParaArray = nil
	normalDropParaArray = nil
	extraDropParaArray = nil
	-- easy mode texts. All trivial for now. 
	local easyLimit = getArgFromAlias( args, { "easy-limit", "剧情体验附加条件", "剧情体验限制" } )
	local easyUnlock = getArgFromAlias( args, { "easy-unlock", "剧情体验解锁条件", "剧情体验解锁" } )
	local easyFirstDropParaArray = parseArray( getArgFromAlias( args, { "剧情体验", "剧情体验首次掉落"} ), "size=60/" )
	local easyStr = ""
	if ( not isEmpty(easyLimit) ) then
		easyStr = easyStr .. '<tr>' .. thCell( 1, '剧情体验', '附加条件' ) .. defaultMainCell .. easyLimit .. "</td></tr>"
	end
	if ( not isEmpty(easyUnlock) ) then
		easyStr = easyStr .. '<tr>' .. thCell( 1, '剧情体验', '解锁条件') .. defaultMainCell .. easyUnlock .. "</td></tr>"
	end
	if ( easyFirstDropParaArray[1] ~= nil ) then
		easyStr = easyStr .. '<tr>' .. thCell( 1, '剧情体验', '首次掉落' ) .. defaultMainCell .. frame:preprocess( repeatedTempWT( "Akitem", easyFirstDropParaArray ) ) .. "</td></tr>"
	end
	-- hard mode texts. All trivial for now. 
	local hardLimit = getArgFromAlias( args, { "hard-limit", "突袭附加条件", "突袭限制" } )
	local hardUnlock = getArgFromAlias( args, { "hard-unlock", "突袭解锁条件", "突袭解锁" } )
	local hardFirstDropParaArray = parseArray( getArgFromAlias( args, { "hfd", "突袭首次掉落", "突袭掉落" } ), "size=60/" )
	local hardStr = ""
	if ( not isEmpty(hardLimit) ) then
		hardStr = hardStr .. '<tr>' .. thCell( 1, '突袭附', '加条件', 'background-color:#300;color:#f00;' ) .. defaultMainCell:gsub(">$",' style="background-color:#400;color:#fff;">') .. hardLimit .. "</td></tr>"
	end
	if ( not isEmpty(hardUnlock) ) then
		hardStr = hardStr .. '<tr>' .. thCell( 1, '突袭解', '锁条件', 'background-color:#300;color:#f00;' ) .. defaultMainCell:gsub(">$",' style="background-color:#400;color:#fff;">') .. hardUnlock .. "</td></tr>"
	end
	if ( hardFirstDropParaArray[1] ~= nil ) then
		hardStr = hardStr .. '<tr>' .. thCell( 1, '突袭首', '次掉落', 'background-color:#300;color:#f00;' ) .. defaultMainCell:gsub(">$",' style="background-color:#400;color:#fff;">') .. frame:preprocess( repeatedTempWT( "Akitem", hardFirstDropParaArray ) ) .. "</td></tr>"
	end
	-- hard mode in mainline texts. All trivial for now. 
	local hardLimit1 = getArgFromAlias( args, { "hard-limit", "磨难险地附加条件", "磨难险地限制" } )
	local hardUnlock1 = getArgFromAlias( args, { "hard-unlock", "磨难险地解锁条件", "磨难险地解锁" } )
	local hardFirstDropParaArray1 = parseArray( getArgFromAlias( args, { "hfd", "磨难险地首次掉落"} ), "size=60/" )
	local hardenemyParaArray = parseArray( getArgFromAlias( args, { "enemy", "磨难险地敌人" } ), "size=90/" )
	local hardStr1 = ""
	if ( not isEmpty(hardLimit1) ) then
		hardStr1 = hardStr1 .. '<tr>' .. thCell( 1, '磨难险地', '附加条件', 'background-color:#300;color:#f00;' ) .. defaultMainCell:gsub(">$",' style="background-color:#400;color:#fff;">') .. hardLimit1 .. "</td></tr>"
	end
	if ( not isEmpty(hardUnlock1) ) then
		hardStr1 = hardStr1 .. '<tr>' .. thCell( 1, '磨难险地', '解锁条件', 'background-color:#300;color:#f00;' ) .. defaultMainCell:gsub(">$",' style="background-color:#400;color:#fff;">') .. hardUnlock1 .. "</td></tr>"
	end
	if ( hardFirstDropParaArray1[1] ~= nil ) then
		hardStr1 = hardStr1 .. '<tr>' .. thCell( 1, '磨难险地', '首次掉落', 'background-color:#300;color:#f00;' ) .. defaultMainCell:gsub(">$",' style="background-color:#400;color:#fff;">') .. frame:preprocess( repeatedTempWT( "Akitem", hardFirstDropParaArray1 ) ) .. "</td></tr>"
	end
	if ( hardenemyParaArray[1] ~= nil ) then
		hardStr1 = hardStr1 .. '<tr>' .. thCell( 1, '磨难险地', '敌方情报', 'background-color:#300;color:#f00;'  ) .. defaultMainCell:gsub(">$",' style="background-color:#400;color:#fff;">')
			.. ( 
				frame:preprocess( repeatedTempWT( "Akenicon", hardenemyParaArray ) )
			) .. "</td></tr>"
	end
	
	-- return final table string. get class and id if defined.
	local tableId = isEmpty(args["id"]) and ( isEmpty(levelCode) and '' or ( '\32id="'..levelCode..'"' ) ) or ( '\32id="'..args["id"]..'"' )
	local tableClass = isEmpty(args["class"]) and '' or ( '\32'..args["class"] )
	local tableStyle = isEmpty(args["style"]) and '' or ( '\32style="'..args["style"]..'"' )
	return '<table'..tableId..' class="wikitable'..tableClass..'"'..tableStyle..'>' .. titleStr .. timeStr .. costToEnmStr .. dropStr .. easyStr .. hardStr .. hardStr1 .. '</table>'
end

-- F: generated parsed (preprocessed) repeated template calls. May be useful for other processes.
function p.repeatedTemp ( frame )
	return frame:preprocess( repeatedTempWT( frame.args[1], parseArray(frame.args[2]) ) )
end

return p