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