2023年政策修订增补工作正在进行中,欢迎参与!
Module:FGOServantSkill
跳转到导航
跳转到搜索
本模块仅用于{{FGO_持有技能}},生成Fate/Grand Order系列从者的持有技能描述。
-- Originally designed and coded by Maya (U:Maya-Maja-Maia)
local getArgs = require("Module:Arguments").getArgs
local getSkillIcon = require("Module:FGOSkillIcon").getSkillIcon
local hashObj = require("Module:HashArgs").hashObj
local upPattern = "%^"
local upString = '<span style="color:gold">▲</span>'
local getSkillValue = function (s)
if mw.ustring.sub(s, 1, 4) == 'val:' then
return nil, mw.ustring.sub(s, 5, -1)
end
local n = tonumber(s)
if n then
return n
end
local ssub = mw.ustring.sub(s, 1, -2)
n = tonumber(ssub)
if n then
return n, mw.ustring.sub(s, -1, -1)
end
if s == '∅' or s == '∅' then
return nil, '∅'
end
end
local getRoundValue = function (s)
if mw.ustring.sub(s, 1, 6) == 'round:' then
return mw.ustring.sub(s, 7, -1)
end
end
local roundTo = function (n, to)
if not tonumber(to) then return n end
local mult = 10 ^ to
return math.floor(n * mult + 0.5) / mult
end
local packSkillArgs = function (args, startIdx)
local i = startIdx
local retobj = {}
local addingobj = nil
while args[i] do
if args[i] ~= '' then
local val, suffix = getSkillValue(args[i])
if not val and not suffix then
local round = getRoundValue(args[i])
if round then
addingobj.round = round
else
if addingobj then
table.insert(retobj, addingobj)
end
addingobj = {}
addingobj.name = args[i]
end
else
table.insert(addingobj, { val = val, suffix = suffix })
end
end
i = i + 1
end
if addingobj then table.insert(retobj, addingobj) end
return retobj
end
local expandSkillArg = function (skillArg)
if #skillArg == 10 then return skillArg end
if #skillArg == 1 then return skillArg end
if #skillArg == 0 then
skillArg[1] = { suffix = '∅' }
return skillArg
end
if #skillArg ~= 2 then error('技能数值参数数量有误。应为0个、1个、2个或10个,实为' .. #skillArg .. '个') end
if skillArg[1].suffix ~= skillArg[2].suffix then
error('技能数值参数单位不匹配,其一为' .. skillArg[1].suffix .. ',另一为' .. skillArg[2].suffix)
end
local skillDiff = (skillArg[2].val - skillArg[1].val) / 10
skillArg[10] = skillArg[2]
for i = 1, 8 do
skillArg[i+1] = { val = roundTo(skillArg[1].val + skillDiff * i, skillArg.round), suffix = skillArg[1].suffix }
end
return skillArg
end
local formatSkillArg = function (val, suffix)
if not val then
return suffix
else
return val .. (suffix or '')
end
end
local getStringPrefixLevelAndStrip = function (str, prefix)
local level = 0
local stripped = str
local prefixlen = mw.ustring.len(prefix)
while mw.ustring.sub(stripped, 0, prefixlen) == prefix do
level = level + 1
stripped = mw.ustring.sub(stripped, prefixlen + 1, -1)
end
return { level = level, stripped = stripped }
end
local getStrengthenLevel = function (skillStr)
local addLevel = getStringPrefixLevelAndStrip(skillStr, '+')
local changeLevel = getStringPrefixLevelAndStrip(skillStr, '>')
local subbed
if addLevel.level > 0 then
subbed, _ = mw.ustring.gsub(addLevel.stripped, upPattern, upString)
return {
type = 'add',
level = addLevel.level,
subbed = subbed
}
end
if changeLevel.level > 0 then
subbed, _ = mw.ustring.gsub(changeLevel.stripped, upPattern, upString)
return {
type = 'change',
level = changeLevel.level,
subbed = subbed
}
end
return { type = nil, level = 0, subbed = skillStr }
end
local stackSkillArgs = function (skillArgs)
local retobj = {}
local addingobj = nil
local strengthenobj = nil
local strengthenTimes = 0
for i = 1, #skillArgs do
strengthenobj = getStrengthenLevel(skillArgs[i].name)
if strengthenobj.type ~= 'change' then
if addingobj then table.insert(retobj, addingobj) end
addingobj = {}
end
if strengthenTimes < strengthenobj.level then
strengthenTimes = strengthenobj.level
end
if addingobj and #addingobj ~= 0 then
addingobj[#addingobj].stopShow = strengthenobj.level - 1
end
skillArgs[i].name = strengthenobj.subbed
table.insert(addingobj, {
startShow = strengthenobj.level,
skillArg = skillArgs[i]
})
end
if addingobj then table.insert(retobj, addingobj) end
retobj.strengthenTimes = strengthenTimes
return retobj
end
local getUpStrings = function (num)
local retstr = ''
for i = 1, num do
retstr = retstr .. upString
end
return retstr
end
local getChargeString = function (str)
local num = tonumber(str)
if num then
return num .. '→<span style="color:red">' .. num - 1 ..
'</span>→<span style="color:red">' .. num - 2 .. '</span>'
else
return str
end
end
local generateSkillRowWithClass = function (skillArg, class, add)
local retstr = ''
local classaddstr = add or ''
if class then
classaddstr = 'class="' .. class .. '" ' .. classaddstr
end
retstr = retstr .. [[
|-]] .. classaddstr .. [[
! colspan="10" |]] .. skillArg.name .. [[
|-]] .. classaddstr
if #(skillArg) > 1 then
for j = 1, 10 do
retstr = retstr .. [[
| style="width:75px;max-width:20%]]
if j == 6 or j == 10 then
retstr = retstr .. ';color:red'
end
retstr = retstr .. '"'
if j >= 6 then
retstr = retstr .. ' class="nomobile"'
end
retstr = retstr .. ' |' .. formatSkillArg(skillArg[j].val, skillArg[j].suffix)
end
retstr = retstr .. [[
|- class="mobileonly ]] .. (class or '') .. '" ' .. (add or '')
for j = 6, 10 do
retstr = retstr .. [[
| style="width:75px;max-width:20%]]
if j == 6 or j == 10 then
retstr = retstr .. ';color:red'
end
retstr = retstr .. '" |' .. formatSkillArg(skillArg[j].val, skillArg[j].suffix)
end
else
retstr = retstr .. [[
| colspan="10" |]] .. formatSkillArg(skillArg[1].val, skillArg[1].suffix)
end
return retstr
end
local generateTable = function (args, skillArgs, frame, hash)
local iconstr = getSkillIcon(args[1])
local namezhstr = args[2]
local namejastr = args[3]
local chargestr = getChargeString(args[4])
local retstr = ''
if skillArgs.strengthenTimes ~= 0 then
local defaultTab = hash .. args["默认"]
local buttonArgs = {
'button',
['@default'] = defaultTab,
['@forceNoCancel'] = 'y',
['@radio'] = 'y'
}
local buttonSort = '@default|@forceNoCancel|@radio|'
local buttonText = ''
for i = 0, skillArgs.strengthenTimes do
if i == 0 then
buttonText = args['按钮0'] or '强化前'
elseif skillArgs.strengthenTimes == 1 then
buttonText = args['按钮1'] or '强化后'
else
buttonText = args['按钮' .. i] or ('强化后' .. i)
end
buttonArgs[hash .. i] = buttonText
buttonSort = buttonSort .. hash .. i .. '|'
if args['条件' .. i] then
retstr = retstr ..
'<span class="textToggleDisplay hidden" data-id="' .. hash .. i ..
'">' .. args['条件' .. i] .. '</span>\n'
end
end
buttonArgs['@sort'] = buttonSort .. '@sort|'
retstr = frame:callParserFunction{
name = '#invoke:切换显示',
args = buttonArgs
} .. '\n\n' .. retstr -- cannot use template directly, order preservance issues
end
retstr = retstr .. '{| class="wikitable" style="text-align:center;vertical-align:middle;line-height:1.75em;display:table;max-width:100%"'
for i = 0, skillArgs.strengthenTimes do
local switchClassStr = ''
if skillArgs.strengthenTimes ~= 0 then
switchClassStr = 'class="textToggleDisplay hidden" data-id="' .. hash .. i .. '"'
end
if args["图标" .. i] then iconstr = getSkillIcon(args["图标" .. i]) end
namezhstr = args["中文名" .. i] or namezhstr
namejastr = args["日文名" .. i] or namejastr
if args["充能时间" .. i] then chargestr = getChargeString(args["充能时间" .. i]) end
retstr = retstr .. [[
|-]] .. switchClassStr .. [[
! rowspan="2" class="nomobile" style="width:75px;max-width:10%" |]] .. iconstr .. [[
! rowspan="3" class="mobileonly" style="width:75px;max-width:20%" |]] .. iconstr .. [[
! colspan="4" class="mobileonly" style="width:300px;max-width:80%" |]] .. namezhstr .. getUpStrings(i) .. [[
! colspan="6" class="nomobile" style="width:450px;max-width:60%" |]] .. namezhstr .. getUpStrings(i) .. [[
! rowspan="2" colspan="3" class="nomobile" style="width:225px;max-width:30%" |充能时间:]] .. chargestr .. [[
|-]] .. switchClassStr .. [[
| colspan="6" lang="ja" | -{]] .. namejastr .. getUpStrings(i) .. [[}-
|-]] .. switchClassStr .. [[
! colspan="4" class="mobileonly" |充能时间:]] .. chargestr
end
for i = 1, #skillArgs do
if #(skillArgs[i]) == 1 and skillArgs[i][1].startShow == 0 then
retstr = retstr .. generateSkillRowWithClass(skillArgs[i][1].skillArg)
else
local currentAt = 1
for j = 0, skillArgs.strengthenTimes do
if skillArgs[i][currentAt].startShow <= j then
retstr = retstr .. generateSkillRowWithClass(skillArgs[i][currentAt].skillArg,
'textToggleDisplay hidden',
'data-id="' .. hash .. j .. '"')
end
if skillArgs[i][currentAt].stopShow and skillArgs[i][currentAt].stopShow <= j then
currentAt = currentAt + 1
end
end
end
end
retstr = retstr .. [[
|}]]
return retstr
end
local FGOServantSkill = {
main = function (frame)
local args = getArgs(frame, { removeBlanks = false })
-- 1. 图标 2. 中文名 3. 日文名 4. CT
-- 从5开始是技能描述
local hash = hashObj(args)
local skillArgs = packSkillArgs(args, 5)
for i = 1, #skillArgs do
skillArgs[i] = expandSkillArg(skillArgs[i])
end
skillArgs = stackSkillArgs(skillArgs)
return generateTable(args, skillArgs, frame, hash)
end
}
return FGOServantSkill