本模块仅用于{{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