模块:Driver
来自乐园数据管理室
此模块的文档可以在模块:Driver/doc创建
local p = {}
local QueryHelper = require("Module:Xb2QueryHelper")
local html = require("Module:Html")
local BdatEnums = require("Module:BdatEnums")
function parseArtsDataPerLevel(Arts, level)
-- 是否为普通攻击
local isNormal = Arts.Normal
if isNormal then
level = 1
end
-- 按技能等级取值
local DmgMgn = Arts["DmgMgn" .. level]
local Enhance =
Arts["Enhance" .. level] > 0 and QueryHelper.getEnhance(Arts["Enhance" .. level]).RenderedCaption or ""
local Recast = Arts["Recast" .. level]
local hitNum, hit, ReActText
if Arts.ArtsType == 11 then -- 类型 格挡
DmgMgn = tostring(DmgMgn / 30) .. "秒"
else
hitNum = 0 -- 判定数
local HitFrm = {} -- 判定帧
for i = 1, 16 do
table.insert(HitFrm, Arts["HitFrm" .. i])
if Arts["HitFrm" .. i] > 0 then
hitNum = hitNum + 1
end
end
local DmgRt = {}
local DmgRtTotal = 0
for i = 1, 16 do
local potencyRatio = Arts["DmgRt" .. i]
if potencyRatio == 255 then
potencyRatio = -1
end
table.insert(DmgRt, potencyRatio)
if potencyRatio > 0 then
DmgRtTotal = DmgRtTotal + potencyRatio
end
end
local ReAct, ReActDict = {}, {}
for i = 1, 16 do
local ReActStr = Arts["ReAct" .. i] > 0 and BdatEnums.ReActType[Arts["ReAct" .. i]] or ""
table.insert(ReAct, ReActStr)
ReActDict[Arts["ReAct" .. i]] = ReActStr
end
ReActDict[0] = nil
ReActText = {}
for _, v in pairs(ReActDict) do
table.insert(ReActText, v)
end
ReActText = table.concat(ReActText, " ")
hit = {}
local DmgTotal = 0
for i = 1, 16 do
local dmgPerHit = 0
if DmgRtTotal > 0 then -- DmgRt 总和大于0时,每hit伤害按 DmgRt 分割
if DmgRt[i] > 0 then
dmgPerHit = DmgMgn * DmgRt[i] / DmgRtTotal
end
else -- DmgRtTotal 为 0,每hit伤害按hit数平分
if HitFrm[i] > 0 and DmgRt[i] == 0 then -- HitFrame存在且DmgRt不为-1
dmgPerHit = DmgMgn / hitNum
end
end
if HitFrm[i] > 0 or dmgPerHit > 0 or #ReAct[i] > 0 then
local dmg = tonumber(mw.ustring.format("%.2f", dmgPerHit))
table.insert(
hit,
{
HitTime = tonumber(mw.ustring.format("%.2f", HitFrm[i] / 30)),
Dmg = dmg > 0 and dmg or "",
ReAct = ReAct[i]
}
)
DmgTotal = DmgTotal + dmgPerHit
end
end
end
return {
Level = not isNormal and level or nil,
DmgMgn = DmgMgn,
Recast = Recast,
Enhance = Enhance,
HitNum = hitNum,
PerHits = hit,
ReActText = ReActText or ""
}
end
function p.getDataByDriverId(DriverId)
local DriverData = QueryHelper.getDr(DriverId)
DriverData.Arts = QueryHelper.getArtsDrListByDriver(DriverId)
DriverData.Skill = QueryHelper.getSkillDrList(DriverId)
return DriverData
end
function p.getArtsByDriverIdAndWpnType(driverId, WpnType)
return QueryHelper.getArtsDrListByDriverAndWpnType(driverId, WpnType)
end
function parseArtsDr(Arts)
local ArtsType = BdatEnums.ArtsType[Arts.ArtsType]
local RangeTypeText = Arts.ArtsType == 3 and "" or BdatEnums.ArtsRangeType[Arts.RangeType]
local ArtsBuff = Arts.ArtsBuff > 0 and BdatEnums.ArtsBuff[Arts.ArtsBuff] or ""
local ArtsDeBuff = Arts.ArtsDeBuff > 0 and QueryHelper.getBuff(Arts.ArtsDeBuff).NameText or ""
local Target = BdatEnums.ArtsTarget[Arts.Target]
local PerLevel = {}
if Arts.Normal then
table.insert(PerLevel, parseArtsDataPerLevel(Arts))
else
for i = 1, 6 do -- 武技六段强化
table.insert(PerLevel, parseArtsDataPerLevel(Arts, i))
end
end
local ReleaseLv
local NeedWP
if not Arts.Normal then
ReleaseLv = {}
NeedWP = {}
for level = 1, 5 do
table.insert(ReleaseLv, Arts["ReleaseLv" .. level])
table.insert(NeedWP, Arts["NeedWP" .. level])
end
end
return {
ID = Arts.row_id,
Name = Arts.Name == 0 and "" or Arts.NameText,
DebugName = Arts.DebugName,
Caption = Arts.Caption,
CaptionText = Arts.CaptionText or "",
CondCapText = Arts.CondCapText,
TalentCapText = Arts.TalentCapText,
DriverId = Arts.Driver,
WpnType = Arts.WpnType,
ActNo = Arts.ActNo,
IrType = Arts.IrType,
ActSpeed = Arts.ActSpeed .. "%",
ArtsType = ArtsType,
ArtsBuff = ArtsBuff,
ArtsDeBuff = ArtsDeBuff,
Target = Target,
Distance = Arts.Distance,
RangeType = Arts.RangeType,
RangeTypeText = RangeTypeText,
Radius = Arts.Radius,
Length = Arts.Length,
Hate = Arts.Hate,
HitRevise = Arts.HitRevise .. "%",
CriRevise = Arts.CriRevise .. "%",
Normal = Arts.Normal,
SArmor1 = Arts.SArmor1,
SArmor2 = Arts.SArmor2,
PerLevel = PerLevel,
ReleaseLv = ReleaseLv,
NeedWP = NeedWP
}
end
local IrArtsType = {
[0] = {label = "VanguardArts", name = "攻击者武技"},
[1] = {label = "RearGuardArts", name = "支援者武技"},
[2] = {label = "TalentArt", name = "天赋武技"},
[3] = {label = "SwitchArt", name = "切换武技"}
}
function p.formatArtsData(ArtsDataTable)
local WpnArts = {}
for _, ArtsRow in ipairs(ArtsDataTable) do
local ArtsData = parseArtsDr(ArtsRow)
WpnArts[ArtsRow.WpnType] = WpnArts[ArtsRow.WpnType] or {}
if ArtsRow.Normal then
-- 自动攻击
WpnArts[ArtsRow.WpnType].NormalAttack = WpnArts[ArtsRow.WpnType].NormalAttack or {}
-- 将lv1的属性合并到根属性
for k, v in pairs(ArtsData.PerLevel[1]) do
ArtsData[k] = v
end
ArtsData.PerLevel = nil
-- 展开判断表
ArtsData.HitText =
ArtsData.PerHits and
html.wikitable(
{
{scope = "HitTime", label = "秒"},
{scope = "Dmg", label = "伤害倍率"}
},
ArtsData.PerHits,
{class = "borderless-table"}
) or
""
table.insert(WpnArts[ArtsRow.WpnType].NormalAttack, ArtsData)
else
-- 御刃者武技
if ArtsData.DriverId < 17 then
WpnArts[ArtsRow.WpnType].DriverArts = WpnArts[ArtsRow.WpnType].DriverArts or {}
else
for i = 0, 3 do
WpnArts[ArtsRow.WpnType][IrArtsType[i].label] = WpnArts[ArtsRow.WpnType][IrArtsType[i].label] or {}
end
end
-- 数据处理
if ArtsData.RangeType == 2 or ArtsData.RangeType == 3 then
-- 前后方的方形判定范围,增加LengthWidth属性
ArtsData.LengthWidth = ArtsData.Length .. " x " .. ArtsData.Radius
ArtsData.Radius = nil
elseif ArtsData.RangeType == 0 then
ArtsData.Radius = nil
end
-- 按等级复制table
for level = 1, 6 do
local perLevelData = {}
-- 把当前lv的属性拷贝到新对象
for k, v in pairs(ArtsData.PerLevel[level]) do
perLevelData[k] = v
end
-- 定义ArtsData上需要拷贝的字段
local propertyList = {
"ActNo",
"ActSpeed",
"ArtsBuff",
"ArtsDeBuff",
"ArtsType",
"Caption",
"CaptionText",
"CriRevise",
"DebugName",
"Distance",
"DriverId",
"Hate",
"HitRevise",
"ID",
"Length",
"Name",
"Normal",
"Radius",
"RangeType",
"RangeTypeText",
"SArmor1",
"SArmor2",
"Target",
"WpnType"
}
for _, property in ipairs(propertyList) do
perLevelData[property] = ArtsData[property]
end
perLevelData.ReleaseLv = ArtsData.ReleaseLv[level]
perLevelData.NeedWP = ArtsData.NeedWP[level]
-- 展开hit表
perLevelData.HitText =
perLevelData.PerHits and
html.wikitable(
{
{scope = "HitTime", label = "秒"},
{scope = "Dmg", label = "伤害倍率"},
{scope = "ReAct", label = "特效"}
},
perLevelData.PerHits,
{class = "borderless-table"}
) or
""
if ArtsData.DriverId < 17 then
WpnArts[ArtsRow.WpnType].DriverArts[level] = WpnArts[ArtsRow.WpnType].DriverArts[level] or {}
table.insert(WpnArts[ArtsRow.WpnType].DriverArts[level], perLevelData)
else
if ArtsData.IrType == 0 then
WpnArts[ArtsRow.WpnType].VanguardArts[level] = WpnArts[ArtsRow.WpnType].VanguardArts[level] or {}
table.insert(WpnArts[ArtsRow.WpnType].VanguardArts[level], perLevelData)
elseif ArtsData.IrType == 1 then
WpnArts[ArtsRow.WpnType].RearGuardArts[level] = WpnArts[ArtsRow.WpnType].RearGuardArts[level] or {}
table.insert(WpnArts[ArtsRow.WpnType].RearGuardArts[level], perLevelData)
elseif ArtsData.IrType == 2 then
WpnArts[ArtsRow.WpnType].SwitchArt[level] = WpnArts[ArtsRow.WpnType].SwitchArt[level] or {}
table.insert(WpnArts[ArtsRow.WpnType].SwitchArt[level], perLevelData)
elseif ArtsData.IrType == 3 then
WpnArts[ArtsRow.WpnType].TalentArt[level] = WpnArts[ArtsRow.WpnType].TalentArt[level] or {}
table.insert(WpnArts[ArtsRow.WpnType].TalentArt[level], perLevelData)
end
end
end
end
end
return WpnArts
end
function p.outputArtsSection(WpnArts, WpnId)
local out = ""
out = out .. html.h4("自动攻击")
out =
out ..
mw.ustring.format(
[[
<table class="wikitable">
<tr>
<th>类型</th>
<th>攻击距离</th>
<th>仇恨</th>
<th>伤害倍率</th>
<th>攻击次数</th>
</tr>
<tr>
<td rowspan="3">%s</td>
<td rowspan="3">%s</td>
<td rowspan="3">%s</td>
<td>%s</td>
<td>%s</td>
</tr>
<tr>
<td>%s</td>
<td>%s</td>
</tr>
<tr>
<td>%s</td>
<td>%s</td>
</tr>
</table>
]],
WpnArts[WpnId].NormalAttack[1].ArtsType,
WpnArts[WpnId].NormalAttack[1].Distance,
WpnArts[WpnId].NormalAttack[1].Hate,
WpnArts[WpnId].NormalAttack[1].DmgMgn,
#WpnArts[WpnId].NormalAttack[1].PerHits,
WpnArts[WpnId].NormalAttack[2].DmgMgn,
#WpnArts[WpnId].NormalAttack[2].PerHits,
WpnArts[WpnId].NormalAttack[3].DmgMgn,
#WpnArts[WpnId].NormalAttack[3].PerHits
)
if WpnArts[WpnId].DriverArts and #WpnArts[WpnId].DriverArts > 0 then -- DriverArts属性存在,表示本篇御刃者
out = out .. html.h4("御刃者武技")
out = out .. '<div class="xbxbtabs arts">'
for lv, perLevelData in ipairs(WpnArts[WpnId].DriverArts) do
local tabslabel = "Lv" .. lv
local tabsname = WpnId .. tabslabel
out =
out ..
'<div data-name="' ..
tabsname ..
'" data-label="' ..
tabslabel ..
'" >' ..
html.wikitable(
{
{
scope = "Name",
label = "名称"
},
{
scope = "ArtsType",
label = "类型"
},
{
scope = "RangeTypeText",
label = "范围"
},
{
scope = "Distance",
label = "目标距离"
},
{
scope = "DmgMgn",
label = "倍率"
},
{
scope = "Recast",
label = "填充量"
},
{
scope = "Hate",
label = "仇恨"
},
{
scope = "ReActText",
label = "反应动作"
},
{
scope = "Enhance",
label = "特效"
}
},
perLevelData,
{
width = "100%",
expandRow = {
{scope = "Radius", label = "判定半径"},
{scope = "LengthWidth", label = "判定范围"},
{scope = "HitRevise", label = "命中修正"},
{scope = "CriRevise", label = "暴击修正"},
{scope = "ArtsBuff", label = "技能使用中状态"},
{scope = "ArtsDeBuff", label = "减益效果"},
{scope = "ReleaseLv", label = "习得等级"},
{scope = "NeedWP", label = "升级WP"},
{scope = "HitText", label = "技能判定"}
},
expandRowKey = "ID"
}
) ..
"</div>"
end
out = out .. "</div>"
else -- 黄金国角色
for i = 0, 3 do
out = out .. html.h4(IrArtsType[i].name)
out = out .. '<div class="xbxbtabs arts">'
for lv, perLevelData in ipairs(WpnArts[WpnId][IrArtsType[i].label]) do
local tabslabel = "Lv" .. lv
local tabsname = WpnId .. tabslabel
out =
out ..
'<div data-name="' ..
tabsname ..
'" data-label="' ..
tabslabel ..
'" >' ..
html.wikitable(
{
{
scope = "Name",
label = "名称"
},
{
scope = "ArtsType",
label = "类型"
},
{
scope = "RangeTypeText",
label = "范围"
},
{
scope = "Distance",
label = "目标距离"
},
{
scope = "DmgMgn",
label = "倍率"
},
{
scope = "Recast",
label = "填充量"
},
{
scope = "Hate",
label = "仇恨"
},
{
scope = "ReActText",
label = "反应动作"
},
{
scope = "Enhance",
label = "特效"
}
},
perLevelData,
{
width = "100%",
expandRow = {
{scope = "Radius", label = "判定半径"},
{scope = "LengthWidth", label = "判定范围"},
{scope = "HitRevise", label = "命中修正"},
{scope = "CriRevise", label = "暴击修正"},
{scope = "ArtsBuff", label = "技能使用中状态"},
{scope = "ArtsDeBuff", label = "减益效果"},
{scope = "ReleaseLv", label = "习得等级"},
{scope = "NeedWP", label = "升级WP"},
{scope = "HitText", label = "技能判定"}
},
expandRowKey = "ID"
}
) ..
"</div>"
end
out = out .. "</div>"
end
end
return out
end
function p.main(frame)
local currentTitle = mw.title.getCurrentTitle()
local ira = false
if "黄金之国" == mw.ustring.sub(tostring(currentTitle), 1, 4) then
ira = true
end
local data = p.getDataByDriverId(frame.args[1])
local out = ""
-- flex
out = out .. '<div style="display:flex;flex-wrap:wrap-reverse;justify-content:space-between;">'
out = out .. "<div>"
-- 能力表
out =
out ..
mw.ustring.format(
[[
<table class="wikitable">
<tr>
<th>能力值</th>
<th>Lv1</th>
<th>Lv99</th>
</tr>
<tr>
<td>HP</td>
<td>%s</td>
<td>%s</td>
</tr>
<tr>
<td>力量</td>
<td>%s</td>
<td>%s</td>
</tr>
<tr>
<td>以太力</td>
<td>%s</td>
<td>%s</td>
</tr>
<tr>
<td>灵巧</td>
<td>%s</td>
<td>%s</td>
</tr>
<tr>
<td>敏捷</td>
<td>%s</td>
<td>%s</td>
</tr>
<tr>
<td>运气</td>
<td>%s</td>
<td>%s</td>
</tr>
</table>
]],
data.HpMaxLv1,
data.HpMaxLv99,
data.StrengthLv1,
data.StrengthLv99,
data.PowEtherLv1,
data.PowEtherLv99,
data.DexLv1,
data.DexLv99,
data.AgilityLv1,
data.AgilityLv99,
data.LuckLv1,
data.LuckLv99
)
-- 收纳包
out =
out ..
mw.ustring.format(
[[
<table class="wikitable">
<tr>
<th colspan="3">喜好的收纳包道具</th>
</tr>
<tr>
<td>喜欢的分类</td>
<td>%s</td>
<td>%s</td>
</tr>
<tr>
<td>喜欢的道具</td>
<td>%s</td>
<td>%s</td>
</tr>
</table>
]],
data.FavoriteCategory1Text,
data.FavoriteCategory2Text,
"[[" .. (ira and "黄金之国物品:" or "物品:") .. data.FavoriteItem1Text .. "|" .. data.FavoriteItem1Text .. "]]",
"[[" .. (ira and "黄金之国物品:" or "物品:") .. data.FavoriteItem2Text .. "|" .. data.FavoriteItem2Text .. "]]"
)
out = out .. "</div>"
-- 立绘
local images = {}
for i, v in ipairs(frame.args) do
images[i] = v
end
if #images > 1 then
if #images > 2 then
out = out .. '<div class="xbxbtabs" style="display: none;">'
for i = 1, #images / 2 do
local tabslabel = images[i * 2]
local filename = images[i * 2 + 1]
out =
out ..
'<div data-label="' ..
tabslabel .. '" data-name="' .. filename .. '">[[文件:' .. filename .. "|none|x400px]]</div>"
end
out = out .. "</div>"
else
out = out .. "[[文件:" .. images[2] .. "|none|x400px]]"
end
end
-- 闭合flex
out = out .. "</div>"
if data.Skill then
out = out .. html.h2("牵绊圆环")
local OvertAffinity, HiddenAffinity = {}, {}
for _, skillrow in ipairs(data.Skill) do
skillrow.EnhanceText = skillrow.Enhance.RenderedCaption
if skillrow.Round == 1 then
table.insert(OvertAffinity, skillrow)
elseif skillrow.Round == 2 then
table.insert(HiddenAffinity, skillrow)
end
end
out = out .. html.h3("表象牵绊")
out =
out ..
html.wikitable(
{
{
scope = "NameText",
label = "名称"
},
{
scope = "EnhanceText",
label = "效果"
},
{
scope = "NeedSp",
label = "升级所需SP"
}
},
OvertAffinity
)
out = out .. html.h3("内心牵绊")
out =
out ..
html.wikitable(
{
{
scope = "NameText",
label = "名称"
},
{
scope = "EnhanceText",
label = "效果"
},
{
scope = "NeedSp",
label = "升级所需SP"
}
},
HiddenAffinity
)
end
local WpnArts = p.formatArtsData(data.Arts)
-- mw.log(mw.text.jsonEncode(WpnArts, mw.text.JSON_PRETTY))
out = out .. html.h2("武技")
for _, Wpn in ipairs(data.WpnType) do
local WpnId = Wpn.row_id
out = out .. html.h3("[[" .. Wpn.Name .. "]]")
out = out .. p.outputArtsSection(WpnArts, WpnId)
end
return out
end
return p