◆少前百科是非盈利性、非官方的少女前线维基百科。 ◆如果您发现某些内容错误/空缺,请勇于修正/添加!参与进来其实很容易!点这里 加入少前百科。 ◆有任何意见、建议、纠错,欢迎在 GFwiki:反馈与建议 提出和讨论。编辑事务讨论QQ群:597764980,微博@GFwiki少前百科 ◆To foreigners,You can use twitter to contact us. |
“模块:Gun info”的版本间的差异
小 |
(拆分data表) |
||
(未显示同一用户的84个中间版本) | |||
第1行: | 第1行: | ||
local p = {} | local p = {} | ||
local args = {} | local args = {} | ||
− | local | + | local super |
local gundata | local gundata | ||
− | local data = mw.loadData('Module:Gun info/data') | + | local mid |
− | local | + | local data |
− | local guntype = { {'手枪', '冲锋枪', '步枪', '突击步枪', '机枪', '霰弹枪'}, | + | local bdata = {} |
+ | local etdata = mw.loadData('Module:Equip info/type data') | ||
+ | local odata = mw.loadData('Module:Gun info/obtain data') | ||
+ | local skindata = mw.loadData('Module:Gun info/skin data') | ||
+ | local guntype = { {'手枪', '冲锋枪', '步枪', '突击步枪', '机枪', '霰弹枪', [0] = '所有枪种'}, | ||
{'HG', 'SMG', 'RF', 'AR', 'MG', 'SG'} } | {'HG', 'SMG', 'RF', 'AR', 'MG', 'SG'} } | ||
− | local | + | local attrs = {'伤害', '射速', '命中', '回避', '暴击率', '技能冷却速度', '', '护甲'} |
− | local | + | local bonuses = {'pow', 'hit', 'dodge', 'speed', 'rate', 'critical_harm_rate', |
− | local | + | 'critical_percent', 'armor_piercing', 'armor', 'night_view_percent', 'bullet_number_up'} |
− | {{ | + | local cardstyles = '' |
− | + | ||
− | + | local function makeCard(d, f, p) | |
− | + | local cats = {'配件', '弹匣', '人形'} | |
− | {{ | + | local typeinfo = etdata[d.etype] |
+ | local desc = d.desc | ||
+ | local dollar = (mw.ustring.find(desc, '$', 1, true)) | ||
+ | if mw.ustring.sub(desc, dollar-4, dollar-1) == '<hr>' then | ||
+ | desc = mw.ustring.gsub(desc, '%$', '') | ||
+ | else desc = mw.ustring.gsub(desc, '%$', '<hr>') end | ||
+ | for i = #bonuses, 1, -1 do | ||
+ | local v = bonuses[i] | ||
+ | if d[v] ~= nil and mw.ustring.find(desc, v) ~= nil then | ||
+ | local rpl = d[v][2] | ||
+ | if d.bonus_type ~= nil and d.bonus_type[v] ~= nil then | ||
+ | rpl = math.floor(rpl*(1+d.bonus_type[v]/1000)) end | ||
+ | desc = mw.ustring.gsub(desc, v, string.format('span>%d</span', rpl)) | ||
+ | end | ||
+ | end | ||
+ | return f:expandTemplate{title = '装备/card', args = { | ||
+ | ['类型图标'] = typeinfo.code, | ||
+ | ['星级'] = d.rank, | ||
+ | ['代号'] = d.code, | ||
+ | ['页面'] = p ~= nil and d.altname or d.name, | ||
+ | ['名称'] = d.name, | ||
+ | ['类别'] = cats[typeinfo.category], | ||
+ | ['类型'] = typeinfo.name, | ||
+ | ['描述'] = mw.ustring.gsub(desc, '<%%>', '<span>%</span>') | ||
+ | }} | ||
+ | end | ||
+ | |||
+ | local function putEquipments() | ||
+ | local root = super:tag('div'):attr('id', 'equip-container') | ||
+ | local function copy(t) | ||
+ | local ret = {} | ||
+ | for i, v in ipairs(t) do ret[i] = v end | ||
+ | return ret | ||
+ | end | ||
+ | |||
+ | local equips = { | ||
+ | {{1, 4, 13, 16}, {2, 6}, {3,10}}, | ||
+ | {{3, 9, 10}, {2, 6}, {1, 1, 2, 3, 4, 13}}, | ||
+ | {{2, 5}, {1, 1, 2, 3, 13}, {3, 15}}, | ||
+ | {{1, 1, 2, 3, 4, 13}, {2, 8}, {3, 9, 10}}, | ||
+ | {{2, 5, 17}, {1, 1, 2, 3, 16}, {3, 14, 21}}, | ||
+ | {{3, 11}, {2, 7}, {1, 1, 2, 3, 4, 22}} | ||
+ | } | ||
+ | local defaults = equips[gundata.guntype] | ||
+ | local catnames = {'配件', '弹匣', '人形'} | ||
+ | root:newline():wikitext('=== 装备 ==='):newline() | ||
+ | local edata = {} | ||
+ | for i = 1,3 do edata[i] = gundata['equip' .. tostring(i)] and | ||
+ | copy(gundata['equip' .. tostring(i)]) or defaults[i] end | ||
+ | local equipTable = root:tag('table') | ||
+ | for i = 1,3 do | ||
+ | local tr = equipTable:tag('tr') | ||
+ | for j = 1,3 do | ||
+ | local td = tr:tag('td') | ||
+ | if i == 1 then td:wikitext( | ||
+ | '[[File:Equip_cat_' .. tostring(edata[j][1]) .. '.png|link=]]') | ||
+ | elseif i == 2 then td:wikitext(catnames[edata[j][1]]) | ||
+ | else | ||
+ | local etypes = {} | ||
+ | for k = 2,#(edata[j]) do etypes[k-1] = etdata[edata[j][k]].name end | ||
+ | td:wikitext('可装备', table.concat(etypes, '/')) | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | local ex = gundata.exclusives | ||
+ | if ex[1] then | ||
+ | local frame = mw.getCurrentFrame() | ||
+ | cardstyles = frame:extensionTag{ | ||
+ | name = 'templatestyles', args = { src = '模板:装备/card.css' } | ||
+ | } | ||
+ | local eqdata = mw.loadData('Module:Equip info/data') | ||
+ | local exTable = root:tag('table'):tag('tr') | ||
+ | local cols = {} | ||
+ | for i = 1,3 do cols[#cols+1] = exTable:tag('td') end | ||
+ | for _,v in ipairs(ex) do | ||
+ | local e = eqdata[v] | ||
+ | cols[etdata[e.etype].category]:wikitext(makeCard(e, frame)) | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | |||
+ | local function serveSkillInfo(order, ismod) | ||
+ | local root = mw.html.create() | ||
+ | local id = (ismod and moddata or gundata)['skill' .. order] | ||
+ | local group = math.floor(id/1e5) == 1 and '1' or 'other' | ||
+ | if not bdata[group] then | ||
+ | bdata[group] = mw.loadData('Module:Battle skill config/data ' .. group) | ||
+ | end | ||
+ | skilldata = bdata[group][id] | ||
+ | local skill = root:tag('table'):attr{ class = 'skill-table', | ||
+ | ['data-cd'] = skilldata.cd_time, | ||
+ | ['data-cd-start'] = skilldata.start_cd_time }:addClass('skill' .. order) | ||
+ | if skilldata.vals then skill:attr('data-val', skilldata.vals) end | ||
+ | local signature = skill:tag('tr'):attr('class', 'skill-signature') | ||
+ | local icon = signature:tag('td') | ||
+ | icon:attr('rowspan', 2) | ||
+ | :wikitext('[[File:IconSkill ' .. skilldata.code .. '.png|48px|link=]]') | ||
+ | local skillname = signature:tag('td') | ||
+ | skillname:wikitext(skilldata.name) | ||
+ | if order == '2' then skillname:tag('span'):wikitext('改型2解锁') | ||
+ | elseif ismod then skillname:tag('span'):wikitext('改型1强化') | ||
+ | end | ||
+ | local lvcd = skill:tag('tr'):tag('td'):attr('class', 'skill-lvcd') | ||
+ | lvcd:tag('span'):wikitext('等级10') | ||
+ | lvcd:wikitext('前置冷却<span></span>秒/冷却时间<span></span>秒') | ||
+ | skill:tag('tr'):tag('td'):attr{class = 'lv-control', colspan = 2} | ||
+ | local desc = skill:tag('tr'):tag('td'):attr('colspan', 2) | ||
+ | if skilldata.desc then | ||
+ | local descstr = string.gsub(skilldata.desc, '{}', '<span class="skill"></span>') | ||
+ | descstr = string.gsub(descstr, '\n', '<br>') | ||
+ | desc:wikitext(descstr) | ||
+ | else for i, v in ipairs(skilldata.full_desc) do | ||
+ | desc:tag('p'):wikitext((string.gsub(v, '\n', '<br>'))) end | ||
+ | end | ||
+ | return tostring(root) | ||
+ | end | ||
+ | |||
+ | local function putSkills() | ||
+ | local root = super:tag('div'):attr('id', 'skill-container') | ||
+ | root:newline():wikitext('=== 技能 ==='):newline() | ||
+ | root:wikitext(serveSkillInfo('1')) | ||
+ | if gundata['mod'] then | ||
+ | root:wikitext(serveSkillInfo('1', true)) | ||
+ | root:wikitext(serveSkillInfo('2', true)) | ||
+ | end | ||
+ | end | ||
+ | |||
+ | local function addChibi() | ||
+ | local root = mw.html.create() | ||
+ | root:newline():wikitext('== 战斗形象 =='):newline() | ||
+ | local div = root:tag('div'):addClass('dollSpineBox') | ||
+ | local argTable = {'ChibiCostumeSwitcher', target = 'TDollChibiAnimation'} | ||
+ | local guncode = string.gsub(gundata.code, ' ', '_') | ||
+ | if moddata then argTable['costumes.mod'] = '心智升级' end | ||
+ | for _, v in ipairs(gundata.skins) do | ||
+ | local skin = skindata[v] | ||
+ | if skin then | ||
+ | local skincode = guncode .. '_' .. tostring(v) | ||
+ | argTable['costumes.' .. skincode] = skin.name | ||
+ | end | ||
+ | end | ||
+ | local frame = mw.getCurrentFrame() | ||
+ | div:wikitext(frame:callParserFunction('#widget', argTable)) | ||
+ | div:tag('div'):addClass('tdoll_chibi'):attr{ id = 'TDollChibiAnimation', | ||
+ | ['data-tdoll-id'] = guncode } | ||
+ | return tostring(root) | ||
+ | end | ||
local function addImages() | local function addImages() | ||
− | root:wikitext('== 人形外观 ==') | + | local root = super:tag('div'):attr('id', 'image-container') |
− | + | root:newline():wikitext('== 人形外观 =='):newline() | |
local guncode = string.gsub(gundata.code, ' ', '_') | local guncode = string.gsub(gundata.code, ' ', '_') | ||
− | local | + | local classdata = mw.loadData('Module:Gun info/skinclass_data') |
− | local | + | local control = root:tag('div'):attr('id', 'unit-showcase-control') |
− | local menu = | + | control:tag('div'):attr('id', 'unit-image-selected') |
− | + | :tag('div'):wikitext('初始形象'):done():tag('div') | |
− | + | local menu = control:tag('ul'):attr('id', 'unit-image-selector'):css('display', 'none') | |
+ | control:tag('div'):attr('id', 'state-toggle'):done() | ||
+ | :tag('div'):attr('id', 'live2d-toggle') | ||
menu:tag('li'):attr('data-skincode', guncode):wikitext('初始形象') | menu:tag('li'):attr('data-skincode', guncode):wikitext('初始形象') | ||
if moddata then | if moddata then | ||
local moditem = menu:tag('li') | local moditem = menu:tag('li') | ||
− | :attr('data-skincode', guncode .. 'Mod | + | :attr('data-skincode', guncode .. 'Mod') |
local l2dmod = {[55] = 1, [56] = 1, [57] = 1, [65] = 1, [101] = 1, | local l2dmod = {[55] = 1, [56] = 1, [57] = 1, [65] = 1, [101] = 1, | ||
[103] = 1, [122] = 1, [143] = 1} | [103] = 1, [122] = 1, [143] = 1} | ||
− | if l2dmod[gundata.id] then moditem:addClass('live2d1') end | + | if l2dmod[gundata.id] then |
+ | moditem:addClass('live2d1'):wikitext( | ||
+ | '<div></div><div><span>心智升级</span></div><div class="live2d1"></div>') | ||
+ | else moditem:wikitext('心智升级') | ||
+ | end | ||
end | end | ||
for _, v in ipairs(gundata.skins) do | for _, v in ipairs(gundata.skins) do | ||
− | skin = skindata[v] | + | local skin = skindata[v] |
if skin then | if skin then | ||
local skincode = guncode .. '_' .. tostring(v) | local skincode = guncode .. '_' .. tostring(v) | ||
− | local item = menu:tag('li') | + | local skinclass = classdata[skin.class_id] |
− | item:tag('span'):wikitext(skin.name) | + | local item = menu:tag('li'):attr('data-skincode', skincode) |
− | + | local tdiv = item:tag('div') | |
− | local skintype = skin['type'] | + | if skinclass then tdiv:addClass('theme' .. tostring(skinclass.theme_type)) end |
− | + | local scdiv = item:tag('div') | |
− | if skintype ~= | + | scdiv:tag('span'):wikitext(skin.name) |
− | item:addClass('live2d' .. | + | if skinclass then scdiv:tag('span'):wikitext(skinclass.name) end |
+ | local ldiv = item:tag('div') | ||
+ | local skintype = tostring(skin['type']) | ||
+ | if skintype ~= 'nil' then | ||
+ | item:addClass('live2d' .. skintype) | ||
+ | ldiv:addClass('live2d' .. skintype) | ||
end | end | ||
end | end | ||
end | end | ||
− | showcase:tag('div'):attr('id', 'live2d-control'):cssText('display:none' | + | local showcase = root:tag('div'):attr('id', 'unit-image-showcase') |
− | + | showcase:tag('div'):attr('id', 'unit-image-display') | |
+ | :done():tag('div'):attr('id', 'live2d-control'):cssText('display:none') | ||
end | end | ||
第57行: | 第219行: | ||
effect_poses[i] = 3*(2 - (v - 1)%5) + math.floor((v - 1)/5) - 2 + self_pos | effect_poses[i] = 3*(2 - (v - 1)%5) + math.floor((v - 1)/5) - 2 + self_pos | ||
end | end | ||
+ | table.sort(effect_poses) | ||
return self_pos, effect_poses | return self_pos, effect_poses | ||
end | end | ||
− | local function makeEffectTable(self_pos, effect_poses) | + | local function concatEffects(anames, avals, coeff) |
− | local effect_table = | + | local effects = {} |
+ | for i = 1, #anames do | ||
+ | local sign = avals[i] > 0 and '+' or '' | ||
+ | table.insert(effects, string.format('%s<span class="effect-%s">%s%d%%</span>', | ||
+ | anames[i], | ||
+ | sign == '+' and 'positive' or 'negative', | ||
+ | sign, math.floor(avals[i]*coeff))) | ||
+ | end | ||
+ | return table.concat(effects, ' ') | ||
+ | end | ||
+ | |||
+ | local function makeEffectTable(self_pos, effect_poses, target, effect, parent) | ||
+ | local effect_table = parent:tag('table'):addClass('effect-table'):tag('tr') | ||
+ | local effect_grid = effect_table:tag('td'):tag('table'):addClass('effect-grid') | ||
local index = 1 | local index = 1 | ||
for i = 0, 2 do | for i = 0, 2 do | ||
− | local tr = | + | local tr = effect_grid:tag('tr') |
for j = 1, 3 do | for j = 1, 3 do | ||
local td = tr:tag('td') | local td = tr:tag('td') | ||
第72行: | 第248行: | ||
elseif i*3 + j == self_pos then | elseif i*3 + j == self_pos then | ||
td:addClass('self-cell') | td:addClass('self-cell') | ||
− | |||
end | end | ||
end | end | ||
end | end | ||
+ | local effect_text = effect_table:tag('td') | ||
+ | effect_text:wikitext('<span class="effect-caption">影响格效果</span><br>') | ||
+ | local targets = {} | ||
+ | for _, v in ipairs(target) do targets[#targets+1] = guntype[1][v] end | ||
+ | effect_text:wikitext(string.format('对%s有效', table.concat(targets, '、'))) | ||
+ | local anames, avals = {}, {} | ||
+ | for i,v in ipairs(effect) do | ||
+ | if i%2 == 1 then table.insert(anames, attrs[v]) | ||
+ | else table.insert(avals, v) end | ||
+ | end | ||
+ | effect_text:wikitext('<br>') | ||
+ | effect_text:wikitext(concatEffects(anames, avals, 1)) | ||
+ | if gundata.guntype == 1 then for i = 1.25, 2, 0.25 do | ||
+ | effect_text:wikitext('<br>') | ||
+ | effect_text:wikitext(concatEffects(anames, avals, i)) end end | ||
+ | end | ||
+ | |||
+ | local function r2fs(r) | ||
+ | local f = math.floor(1500/r) | ||
+ | return f, string.format('%.2g', f/30) | ||
+ | end | ||
+ | |||
+ | local function r2fsMG(r) | ||
+ | local f = math.floor((4 + 200/r)*30) | ||
+ | return f, string.format('%.2g', f/30) | ||
+ | end | ||
+ | |||
+ | local function r2fsSG(r) | ||
+ | local f = math.floor(65 + 15*r) | ||
+ | return f, string.format('%.2g', f/30) | ||
+ | end | ||
+ | |||
+ | local function popup(frame, content) | ||
+ | return frame:expandTemplate{title = 'Popup', args = { | ||
+ | ['内容'] = content | ||
+ | }} | ||
end | end | ||
local function addCombatInfo() | local function addCombatInfo() | ||
− | root:wikitext('== 战斗数据 ==') | + | local root = super:tag('div'):attr('id', 'stat-container') |
− | + | local gtype = gundata.guntype | |
+ | local speeds = {15,12,7,10,4,6} | ||
+ | local typeDefaults = { | ||
+ | crit = {20, 5, 40, 20, 5, 40}, | ||
+ | max_rate = {120, 120, 120, 120, 1000, 60} | ||
+ | } | ||
+ | local targets = {{0}, {4}, {1}, {2}, {6}, {5}} | ||
+ | root:newline():wikitext('== 战斗数据 =='):newline() | ||
local ratios = { gundata.life, gundata.power, gundata.rate, | local ratios = { gundata.life, gundata.power, gundata.rate, | ||
− | gundata.hit, gundata.dodge } | + | gundata.hit, gundata.dodge, gundata.armor or 0, gundata.rec } |
− | local | + | local attrdataset = root:tag('div'):attr{ |
− | id = 'attr- | + | id = 'attr-dataset', |
+ | ['data-type'] = gtype, | ||
['data-growing'] = table.concat(ratios, ','), | ['data-growing'] = table.concat(ratios, ','), | ||
['data-growth'] = gundata.growth | ['data-growth'] = gundata.growth | ||
} | } | ||
− | |||
− | |||
− | |||
− | |||
if moddata then | if moddata then | ||
− | + | ratios = { moddata.life, moddata.power, moddata.rate, | |
− | moddata.hit, moddata.dodge } | + | moddata.hit, moddata.dodge, moddata.armor or 0, moddata.rec } |
− | + | attrdataset:attr{ | |
['data-growing-mod'] = table.concat(ratios, ','), | ['data-growing-mod'] = table.concat(ratios, ','), | ||
['data-growth-mod'] = moddata.growth | ['data-growth-mod'] = moddata.growth | ||
} | } | ||
+ | end | ||
+ | local attrtable = root:tag('div'):attr('id', 'attr-table') | ||
+ | attrtable:newline():wikitext([[ | ||
+ | {| | ||
+ | |+生命 | ||
+ | |- | ||
+ | !×1!!×2!!×3!!×4!!×5 | ||
+ | |-id="hp-tr" | ||
+ | | || || || || | ||
+ | |}]]):newline() | ||
+ | attrtable:wikitext[[ | ||
+ | {| | ||
+ | ! id="pow" | 伤害 | ||
+ | | id="pow-td" | | ||
+ | |- | ||
+ | ! id="hit" | 命中 | ||
+ | | id="hit-td" | | ||
+ | |- | ||
+ | ! id="dodge" | 回避 | ||
+ | | id="dodge-td" | | ||
+ | |- | ||
+ | ! id="rate" | 射速 | ||
+ | | id="rate-td" | | ||
+ | |- | ||
+ | ! id="armor" | 护甲 | ||
+ | | id="armor-td" | | ||
+ | |- | ||
+ | ! id="growth" | 成长 | ||
+ | | id="growth-td" | | ||
+ | |}]] | ||
+ | attrtable:newline() | ||
+ | local ctable = attrtable:tag('table') | ||
+ | local consts = { | ||
+ | {'critpow', '暴伤'}, | ||
+ | {'crit', '暴击'}, | ||
+ | {'speed', '移速'}, | ||
+ | {'max_rate', '射速上限'}, | ||
+ | {'ap', '穿甲'}, | ||
+ | {'rec', '修复'} | ||
+ | } | ||
+ | local constVals = { | ||
+ | 150, | ||
+ | gundata.crit or typeDefaults.crit[gtype], | ||
+ | speeds[gtype], | ||
+ | gundata.max_rate or typeDefaults.max_rate[gtype], | ||
+ | 15, | ||
+ | gundata.rec | ||
+ | } | ||
+ | local f = mw.getCurrentFrame() | ||
+ | for i = 1, 6 do | ||
+ | local tr = ctable:tag('tr') | ||
+ | tr:tag('th'):attr('id', consts[i][1]):wikitext(consts[i][2]) | ||
+ | local td = tr:tag('td') | ||
+ | if i == 2 or i == 4 then | ||
+ | td:attr{ | ||
+ | ['data-attr'] = constVals[i], | ||
+ | ['data-mod'] = moddata and moddata[consts[i][1]] or constVals[i] | ||
+ | } | ||
+ | end | ||
+ | td:wikitext(constVals[i], i < 3 and '%' or '') | ||
+ | if i == 4 and gtype ~= 5 then | ||
+ | local action, func = gtype ~= 5 and '攻击', r2fs or '换弹', r2fsMG | ||
+ | local fmt = action .. '间隔%d帧(%s秒)' | ||
+ | td:wikitext(popup(f, string.format(fmt, func(constVals[4])))) | ||
+ | if moddata then | ||
+ | td:wikitext(popup(f, string.format(fmt, func(moddata.max_rate or constVals[4])))) | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | if gtype > 4 then | ||
+ | local tr = ctable:tag('tr') | ||
+ | tr:tag('th'):attr('id', 'round'):wikitext('弹量') | ||
+ | local td = tr:tag('td'):attr{ | ||
+ | ['data-attr'] = gundata.round, | ||
+ | ['data-mod'] = moddata and moddata.round or gundata.round | ||
+ | } | ||
+ | td:wikitext(gundata.round) | ||
+ | if gtype == 6 then | ||
+ | local fmt = '换弹间隔%d帧(%s秒)' | ||
+ | td:wikitext(popup(f, string.format(fmt, r2fsSG(gundata.round)))) | ||
+ | if moddata then | ||
+ | td:wikitext(popup(f, string.format(fmt, r2fsSG(moddata.round or gundata.round)))) | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | local self_pos, effect_poses = getGridPositions(gundata.grid_center or 13, gundata.grid_pos) | ||
+ | local container = moddata and root:tag('div'):attr('id', 'effects') or root | ||
+ | makeEffectTable(self_pos, effect_poses, gundata.effect_target or targets[gtype], gundata.effect, container) | ||
+ | if moddata then | ||
self_pos, effect_poses = getGridPositions(moddata.grid_center or 13, moddata.grid_pos) | self_pos, effect_poses = getGridPositions(moddata.grid_center or 13, moddata.grid_pos) | ||
− | makeEffectTable(self_pos, effect_poses) | + | makeEffectTable(self_pos, effect_poses, moddata.effect_target or targets[gtype], moddata.effect, container) |
end | end | ||
end | end | ||
local function addInfobox() | local function addInfobox() | ||
− | + | local root = mw.html.create('div'):addClass('dollinfo') | |
− | + | local modrank = {'', '4', '4', '5', '6'} | |
− | + | local orgdata = mw.loadData('Module:Gun info/org data') | |
− | + | local org, org2 = orgdata[math.floor(gundata.org/100)], orgdata[gundata.org] | |
− | + | local stars, rank = '', gundata.rank | |
− | + | local isextra = mid > 1000 | |
− | + | local weapon = guntype[1][gundata.guntype] | |
− | + | if isextra then stars = '<span>★</span> EXTRA' else | |
− | + | for i = 1, rank do stars = stars .. '<span>★</span>' end | |
− | + | if moddata then for i = rank+1, modrank[rank] do | |
− | + | stars = '<span>☆</span>' .. stars end end end | |
− | + | local obtains = {} | |
+ | for _, v in ipairs(gundata.obtain) do obtains[#obtains+1] = odata[v] end | ||
+ | if gundata.obtain[1] == 1 or gundata.obtain[1] == 2 then | ||
+ | obtains[#obtains+1] = '制造用时:' .. mw.getContentLanguage() | ||
+ | :formatDuration(gundata.produce_time) | ||
+ | end | ||
+ | root:wikitext(string.format([=[ | ||
+ | <div id="dollnum">NO.%d</div><div id="dollrar">%s</div> | ||
+ | <div id="dollwph">%s武器</div><div id="dollwpd">[[File:图标-%s.png|link=]]%s</div> | ||
+ | <div id="dollpic"><div>[[File:Icon_No.%d%s.png|link=]]</div></div> | ||
+ | <div id="dollilh">形象设计</div><div id="dollild">%s</div> | ||
+ | <div id="dollcvh">配音</div><div id="dollcvd">%s</div> | ||
+ | <div id="dolldph">部门</div><div id="dolldpd">%s</div> | ||
+ | <div id="dollobh">入编渠道</div><div id="dollobd">%s</div> | ||
+ | <div id="dollinh">介绍</div><div id="dollind">%s</div>]=], | ||
+ | mid, stars, | ||
+ | isextra and '' or '烙印', weapon, isextra and weapon or (args['武器'] or gundata.name), | ||
+ | mid, moddata and '_Mod' or '', | ||
+ | gundata.illu or '不明', gundata.cv or '不明', | ||
+ | org and string.format('[[内部一览/%s|%s]]-%s', org, org, org2) or '无', | ||
+ | table.concat(obtains, '<br>'), args['介绍'] or '')) | ||
+ | return tostring(root) | ||
end | end | ||
local function _gunInfo() | local function _gunInfo() | ||
− | + | mid = tonumber(args[1]) | |
+ | if mid < 1000 then | ||
+ | data = mw.loadData('Module:Gun info/data_' .. tostring(math.floor((mid - 1)/100))) | ||
+ | else | ||
+ | data = mw.loadData('Module:Gun info/data extra') | ||
+ | end | ||
+ | gundata = data[mid] | ||
if gundata == nil then | if gundata == nil then | ||
return '<p style="color:red">未找到编号对应的战术人形信息,请检查编号是否正确及' .. | return '<p style="color:red">未找到编号对应的战术人形信息,请检查编号是否正确及' .. | ||
'<a href="/w/Module:Gun_info/data">Module:Gun info/data</a>的数据是否为最新。</p>' | '<a href="/w/Module:Gun_info/data">Module:Gun info/data</a>的数据是否为最新。</p>' | ||
end | end | ||
− | + | if gundata['mod'] == 1 then | |
− | root = mw.html.create() | + | local moddataOrig = mw.loadData('Module:Gun info/data mod')[tonumber(args[1])+20000] |
− | + | moddata = {} | |
− | + | for k,v in pairs(moddataOrig) do moddata[k] = v end | |
+ | for k,v in pairs(gundata) do moddata[k] = moddata[k] or v end | ||
+ | end | ||
+ | local root = mw.html.create() | ||
+ | root:wikitext(addInfobox()) | ||
+ | super = root:tag('div'):attr('id', 'doll-container') | ||
+ | addImages() | ||
addCombatInfo() | addCombatInfo() | ||
− | + | putSkills() | |
+ | putEquipments() | ||
+ | root:wikitext(addChibi()) | ||
local templatestyles = mw.getCurrentFrame():extensionTag{ | local templatestyles = mw.getCurrentFrame():extensionTag{ | ||
name = 'templatestyles', args = { src = '模板:战术人形信息/styles.css' } | name = 'templatestyles', args = { src = '模板:战术人形信息/styles.css' } | ||
} | } | ||
− | return templatestyles .. tostring(root) | + | return cardstyles .. templatestyles .. tostring(root) |
end | end | ||
2024年4月23日 (二) 16:52的版本
模块:Gun info及其子页面是一组主要用于存放和展示战术人形相关信息的模块,其各个部分的作用见下文。
组成部分
控制代码
- 主页面,实现模板:战术人形信息
- 模块:Gun info/index输出人形数据列表,供战术人形图鉴使用
- 模块:Gun info/new输出最近30天实装的人形,供首页/新增人形展示用
数据
- 人形数据
- 模块:Gun info/data存放未心智升级的普通战术人形的数据
- 模块:Gun info/data extra存放特典人形的数据
- 模块:Gun info/data mod存放战术人形心智升级后与原来不同的数据
- 模块:Gun info/ex data从人形数据中单独挑出的人形名称和专属装备编号数据,替代完整的人形数据被装备页面模板请求,以减少请求的数据体积(见模块:Equip info)
- 模块:Gun info/obtain data存放获取方式的数据,也包括装备、妖精等游戏内容的获取方式
- 模块:Gun info/org data存放战术人形和融合势力在格里芬所属部门的数据
- 模块:Gun info/skin data存放人形装扮的数据
- 模块:Gun info/skinclass data存放装扮主题的数据
local p = {} local args = {} local super local gundata local mid local data local bdata = {} local etdata = mw.loadData('Module:Equip info/type data') local odata = mw.loadData('Module:Gun info/obtain data') local skindata = mw.loadData('Module:Gun info/skin data') local guntype = { {'手枪', '冲锋枪', '步枪', '突击步枪', '机枪', '霰弹枪', [0] = '所有枪种'}, {'HG', 'SMG', 'RF', 'AR', 'MG', 'SG'} } local attrs = {'伤害', '射速', '命中', '回避', '暴击率', '技能冷却速度', '', '护甲'} local bonuses = {'pow', 'hit', 'dodge', 'speed', 'rate', 'critical_harm_rate', 'critical_percent', 'armor_piercing', 'armor', 'night_view_percent', 'bullet_number_up'} local cardstyles = '' local function makeCard(d, f, p) local cats = {'配件', '弹匣', '人形'} local typeinfo = etdata[d.etype] local desc = d.desc local dollar = (mw.ustring.find(desc, '$', 1, true)) if mw.ustring.sub(desc, dollar-4, dollar-1) == '<hr>' then desc = mw.ustring.gsub(desc, '%$', '') else desc = mw.ustring.gsub(desc, '%$', '<hr>') end for i = #bonuses, 1, -1 do local v = bonuses[i] if d[v] ~= nil and mw.ustring.find(desc, v) ~= nil then local rpl = d[v][2] if d.bonus_type ~= nil and d.bonus_type[v] ~= nil then rpl = math.floor(rpl*(1+d.bonus_type[v]/1000)) end desc = mw.ustring.gsub(desc, v, string.format('span>%d</span', rpl)) end end return f:expandTemplate{title = '装备/card', args = { ['类型图标'] = typeinfo.code, ['星级'] = d.rank, ['代号'] = d.code, ['页面'] = p ~= nil and d.altname or d.name, ['名称'] = d.name, ['类别'] = cats[typeinfo.category], ['类型'] = typeinfo.name, ['描述'] = mw.ustring.gsub(desc, '<%%>', '<span>%</span>') }} end local function putEquipments() local root = super:tag('div'):attr('id', 'equip-container') local function copy(t) local ret = {} for i, v in ipairs(t) do ret[i] = v end return ret end local equips = { {{1, 4, 13, 16}, {2, 6}, {3,10}}, {{3, 9, 10}, {2, 6}, {1, 1, 2, 3, 4, 13}}, {{2, 5}, {1, 1, 2, 3, 13}, {3, 15}}, {{1, 1, 2, 3, 4, 13}, {2, 8}, {3, 9, 10}}, {{2, 5, 17}, {1, 1, 2, 3, 16}, {3, 14, 21}}, {{3, 11}, {2, 7}, {1, 1, 2, 3, 4, 22}} } local defaults = equips[gundata.guntype] local catnames = {'配件', '弹匣', '人形'} root:newline():wikitext('=== 装备 ==='):newline() local edata = {} for i = 1,3 do edata[i] = gundata['equip' .. tostring(i)] and copy(gundata['equip' .. tostring(i)]) or defaults[i] end local equipTable = root:tag('table') for i = 1,3 do local tr = equipTable:tag('tr') for j = 1,3 do local td = tr:tag('td') if i == 1 then td:wikitext( '[[File:Equip_cat_' .. tostring(edata[j][1]) .. '.png|link=]]') elseif i == 2 then td:wikitext(catnames[edata[j][1]]) else local etypes = {} for k = 2,#(edata[j]) do etypes[k-1] = etdata[edata[j][k]].name end td:wikitext('可装备', table.concat(etypes, '/')) end end end local ex = gundata.exclusives if ex[1] then local frame = mw.getCurrentFrame() cardstyles = frame:extensionTag{ name = 'templatestyles', args = { src = '模板:装备/card.css' } } local eqdata = mw.loadData('Module:Equip info/data') local exTable = root:tag('table'):tag('tr') local cols = {} for i = 1,3 do cols[#cols+1] = exTable:tag('td') end for _,v in ipairs(ex) do local e = eqdata[v] cols[etdata[e.etype].category]:wikitext(makeCard(e, frame)) end end end local function serveSkillInfo(order, ismod) local root = mw.html.create() local id = (ismod and moddata or gundata)['skill' .. order] local group = math.floor(id/1e5) == 1 and '1' or 'other' if not bdata[group] then bdata[group] = mw.loadData('Module:Battle skill config/data ' .. group) end skilldata = bdata[group][id] local skill = root:tag('table'):attr{ class = 'skill-table', ['data-cd'] = skilldata.cd_time, ['data-cd-start'] = skilldata.start_cd_time }:addClass('skill' .. order) if skilldata.vals then skill:attr('data-val', skilldata.vals) end local signature = skill:tag('tr'):attr('class', 'skill-signature') local icon = signature:tag('td') icon:attr('rowspan', 2) :wikitext('[[File:IconSkill ' .. skilldata.code .. '.png|48px|link=]]') local skillname = signature:tag('td') skillname:wikitext(skilldata.name) if order == '2' then skillname:tag('span'):wikitext('改型2解锁') elseif ismod then skillname:tag('span'):wikitext('改型1强化') end local lvcd = skill:tag('tr'):tag('td'):attr('class', 'skill-lvcd') lvcd:tag('span'):wikitext('等级10') lvcd:wikitext('前置冷却<span></span>秒/冷却时间<span></span>秒') skill:tag('tr'):tag('td'):attr{class = 'lv-control', colspan = 2} local desc = skill:tag('tr'):tag('td'):attr('colspan', 2) if skilldata.desc then local descstr = string.gsub(skilldata.desc, '{}', '<span class="skill"></span>') descstr = string.gsub(descstr, '\n', '<br>') desc:wikitext(descstr) else for i, v in ipairs(skilldata.full_desc) do desc:tag('p'):wikitext((string.gsub(v, '\n', '<br>'))) end end return tostring(root) end local function putSkills() local root = super:tag('div'):attr('id', 'skill-container') root:newline():wikitext('=== 技能 ==='):newline() root:wikitext(serveSkillInfo('1')) if gundata['mod'] then root:wikitext(serveSkillInfo('1', true)) root:wikitext(serveSkillInfo('2', true)) end end local function addChibi() local root = mw.html.create() root:newline():wikitext('== 战斗形象 =='):newline() local div = root:tag('div'):addClass('dollSpineBox') local argTable = {'ChibiCostumeSwitcher', target = 'TDollChibiAnimation'} local guncode = string.gsub(gundata.code, ' ', '_') if moddata then argTable['costumes.mod'] = '心智升级' end for _, v in ipairs(gundata.skins) do local skin = skindata[v] if skin then local skincode = guncode .. '_' .. tostring(v) argTable['costumes.' .. skincode] = skin.name end end local frame = mw.getCurrentFrame() div:wikitext(frame:callParserFunction('#widget', argTable)) div:tag('div'):addClass('tdoll_chibi'):attr{ id = 'TDollChibiAnimation', ['data-tdoll-id'] = guncode } return tostring(root) end local function addImages() local root = super:tag('div'):attr('id', 'image-container') root:newline():wikitext('== 人形外观 =='):newline() local guncode = string.gsub(gundata.code, ' ', '_') local classdata = mw.loadData('Module:Gun info/skinclass_data') local control = root:tag('div'):attr('id', 'unit-showcase-control') control:tag('div'):attr('id', 'unit-image-selected') :tag('div'):wikitext('初始形象'):done():tag('div') local menu = control:tag('ul'):attr('id', 'unit-image-selector'):css('display', 'none') control:tag('div'):attr('id', 'state-toggle'):done() :tag('div'):attr('id', 'live2d-toggle') menu:tag('li'):attr('data-skincode', guncode):wikitext('初始形象') if moddata then local moditem = menu:tag('li') :attr('data-skincode', guncode .. 'Mod') local l2dmod = {[55] = 1, [56] = 1, [57] = 1, [65] = 1, [101] = 1, [103] = 1, [122] = 1, [143] = 1} if l2dmod[gundata.id] then moditem:addClass('live2d1'):wikitext( '<div></div><div><span>心智升级</span></div><div class="live2d1"></div>') else moditem:wikitext('心智升级') end end for _, v in ipairs(gundata.skins) do local skin = skindata[v] if skin then local skincode = guncode .. '_' .. tostring(v) local skinclass = classdata[skin.class_id] local item = menu:tag('li'):attr('data-skincode', skincode) local tdiv = item:tag('div') if skinclass then tdiv:addClass('theme' .. tostring(skinclass.theme_type)) end local scdiv = item:tag('div') scdiv:tag('span'):wikitext(skin.name) if skinclass then scdiv:tag('span'):wikitext(skinclass.name) end local ldiv = item:tag('div') local skintype = tostring(skin['type']) if skintype ~= 'nil' then item:addClass('live2d' .. skintype) ldiv:addClass('live2d' .. skintype) end end end local showcase = root:tag('div'):attr('id', 'unit-image-showcase') showcase:tag('div'):attr('id', 'unit-image-display') :done():tag('div'):attr('id', 'live2d-control'):cssText('display:none') end local function getGridPositions(center, pos) local self_pos = 4 - math.floor(center / 5) + 3 * (center % 5 - 2) local effect_poses = {} for i, v in ipairs(pos) do effect_poses[i] = 3*(2 - (v - 1)%5) + math.floor((v - 1)/5) - 2 + self_pos end table.sort(effect_poses) return self_pos, effect_poses end local function concatEffects(anames, avals, coeff) local effects = {} for i = 1, #anames do local sign = avals[i] > 0 and '+' or '' table.insert(effects, string.format('%s<span class="effect-%s">%s%d%%</span>', anames[i], sign == '+' and 'positive' or 'negative', sign, math.floor(avals[i]*coeff))) end return table.concat(effects, ' ') end local function makeEffectTable(self_pos, effect_poses, target, effect, parent) local effect_table = parent:tag('table'):addClass('effect-table'):tag('tr') local effect_grid = effect_table:tag('td'):tag('table'):addClass('effect-grid') local index = 1 for i = 0, 2 do local tr = effect_grid:tag('tr') for j = 1, 3 do local td = tr:tag('td') if i*3 + j == effect_poses[index] then td:addClass('effect-cell') index = index + 1 elseif i*3 + j == self_pos then td:addClass('self-cell') end end end local effect_text = effect_table:tag('td') effect_text:wikitext('<span class="effect-caption">影响格效果</span><br>') local targets = {} for _, v in ipairs(target) do targets[#targets+1] = guntype[1][v] end effect_text:wikitext(string.format('对%s有效', table.concat(targets, '、'))) local anames, avals = {}, {} for i,v in ipairs(effect) do if i%2 == 1 then table.insert(anames, attrs[v]) else table.insert(avals, v) end end effect_text:wikitext('<br>') effect_text:wikitext(concatEffects(anames, avals, 1)) if gundata.guntype == 1 then for i = 1.25, 2, 0.25 do effect_text:wikitext('<br>') effect_text:wikitext(concatEffects(anames, avals, i)) end end end local function r2fs(r) local f = math.floor(1500/r) return f, string.format('%.2g', f/30) end local function r2fsMG(r) local f = math.floor((4 + 200/r)*30) return f, string.format('%.2g', f/30) end local function r2fsSG(r) local f = math.floor(65 + 15*r) return f, string.format('%.2g', f/30) end local function popup(frame, content) return frame:expandTemplate{title = 'Popup', args = { ['内容'] = content }} end local function addCombatInfo() local root = super:tag('div'):attr('id', 'stat-container') local gtype = gundata.guntype local speeds = {15,12,7,10,4,6} local typeDefaults = { crit = {20, 5, 40, 20, 5, 40}, max_rate = {120, 120, 120, 120, 1000, 60} } local targets = {{0}, {4}, {1}, {2}, {6}, {5}} root:newline():wikitext('== 战斗数据 =='):newline() local ratios = { gundata.life, gundata.power, gundata.rate, gundata.hit, gundata.dodge, gundata.armor or 0, gundata.rec } local attrdataset = root:tag('div'):attr{ id = 'attr-dataset', ['data-type'] = gtype, ['data-growing'] = table.concat(ratios, ','), ['data-growth'] = gundata.growth } if moddata then ratios = { moddata.life, moddata.power, moddata.rate, moddata.hit, moddata.dodge, moddata.armor or 0, moddata.rec } attrdataset:attr{ ['data-growing-mod'] = table.concat(ratios, ','), ['data-growth-mod'] = moddata.growth } end local attrtable = root:tag('div'):attr('id', 'attr-table') attrtable:newline():wikitext([[ {| |+生命 |- !×1!!×2!!×3!!×4!!×5 |-id="hp-tr" | || || || || |}]]):newline() attrtable:wikitext[[ {| ! id="pow" | 伤害 | id="pow-td" | |- ! id="hit" | 命中 | id="hit-td" | |- ! id="dodge" | 回避 | id="dodge-td" | |- ! id="rate" | 射速 | id="rate-td" | |- ! id="armor" | 护甲 | id="armor-td" | |- ! id="growth" | 成长 | id="growth-td" | |}]] attrtable:newline() local ctable = attrtable:tag('table') local consts = { {'critpow', '暴伤'}, {'crit', '暴击'}, {'speed', '移速'}, {'max_rate', '射速上限'}, {'ap', '穿甲'}, {'rec', '修复'} } local constVals = { 150, gundata.crit or typeDefaults.crit[gtype], speeds[gtype], gundata.max_rate or typeDefaults.max_rate[gtype], 15, gundata.rec } local f = mw.getCurrentFrame() for i = 1, 6 do local tr = ctable:tag('tr') tr:tag('th'):attr('id', consts[i][1]):wikitext(consts[i][2]) local td = tr:tag('td') if i == 2 or i == 4 then td:attr{ ['data-attr'] = constVals[i], ['data-mod'] = moddata and moddata[consts[i][1]] or constVals[i] } end td:wikitext(constVals[i], i < 3 and '%' or '') if i == 4 and gtype ~= 5 then local action, func = gtype ~= 5 and '攻击', r2fs or '换弹', r2fsMG local fmt = action .. '间隔%d帧(%s秒)' td:wikitext(popup(f, string.format(fmt, func(constVals[4])))) if moddata then td:wikitext(popup(f, string.format(fmt, func(moddata.max_rate or constVals[4])))) end end end if gtype > 4 then local tr = ctable:tag('tr') tr:tag('th'):attr('id', 'round'):wikitext('弹量') local td = tr:tag('td'):attr{ ['data-attr'] = gundata.round, ['data-mod'] = moddata and moddata.round or gundata.round } td:wikitext(gundata.round) if gtype == 6 then local fmt = '换弹间隔%d帧(%s秒)' td:wikitext(popup(f, string.format(fmt, r2fsSG(gundata.round)))) if moddata then td:wikitext(popup(f, string.format(fmt, r2fsSG(moddata.round or gundata.round)))) end end end local self_pos, effect_poses = getGridPositions(gundata.grid_center or 13, gundata.grid_pos) local container = moddata and root:tag('div'):attr('id', 'effects') or root makeEffectTable(self_pos, effect_poses, gundata.effect_target or targets[gtype], gundata.effect, container) if moddata then self_pos, effect_poses = getGridPositions(moddata.grid_center or 13, moddata.grid_pos) makeEffectTable(self_pos, effect_poses, moddata.effect_target or targets[gtype], moddata.effect, container) end end local function addInfobox() local root = mw.html.create('div'):addClass('dollinfo') local modrank = {'', '4', '4', '5', '6'} local orgdata = mw.loadData('Module:Gun info/org data') local org, org2 = orgdata[math.floor(gundata.org/100)], orgdata[gundata.org] local stars, rank = '', gundata.rank local isextra = mid > 1000 local weapon = guntype[1][gundata.guntype] if isextra then stars = '<span>★</span> EXTRA' else for i = 1, rank do stars = stars .. '<span>★</span>' end if moddata then for i = rank+1, modrank[rank] do stars = '<span>☆</span>' .. stars end end end local obtains = {} for _, v in ipairs(gundata.obtain) do obtains[#obtains+1] = odata[v] end if gundata.obtain[1] == 1 or gundata.obtain[1] == 2 then obtains[#obtains+1] = '制造用时:' .. mw.getContentLanguage() :formatDuration(gundata.produce_time) end root:wikitext(string.format([=[ <div id="dollnum">NO.%d</div><div id="dollrar">%s</div> <div id="dollwph">%s武器</div><div id="dollwpd">[[File:图标-%s.png|link=]]%s</div> <div id="dollpic"><div>[[File:Icon_No.%d%s.png|link=]]</div></div> <div id="dollilh">形象设计</div><div id="dollild">%s</div> <div id="dollcvh">配音</div><div id="dollcvd">%s</div> <div id="dolldph">部门</div><div id="dolldpd">%s</div> <div id="dollobh">入编渠道</div><div id="dollobd">%s</div> <div id="dollinh">介绍</div><div id="dollind">%s</div>]=], mid, stars, isextra and '' or '烙印', weapon, isextra and weapon or (args['武器'] or gundata.name), mid, moddata and '_Mod' or '', gundata.illu or '不明', gundata.cv or '不明', org and string.format('[[内部一览/%s|%s]]-%s', org, org, org2) or '无', table.concat(obtains, '<br>'), args['介绍'] or '')) return tostring(root) end local function _gunInfo() mid = tonumber(args[1]) if mid < 1000 then data = mw.loadData('Module:Gun info/data_' .. tostring(math.floor((mid - 1)/100))) else data = mw.loadData('Module:Gun info/data extra') end gundata = data[mid] if gundata == nil then return '<p style="color:red">未找到编号对应的战术人形信息,请检查编号是否正确及' .. '<a href="/w/Module:Gun_info/data">Module:Gun info/data</a>的数据是否为最新。</p>' end if gundata['mod'] == 1 then local moddataOrig = mw.loadData('Module:Gun info/data mod')[tonumber(args[1])+20000] moddata = {} for k,v in pairs(moddataOrig) do moddata[k] = v end for k,v in pairs(gundata) do moddata[k] = moddata[k] or v end end local root = mw.html.create() root:wikitext(addInfobox()) super = root:tag('div'):attr('id', 'doll-container') addImages() addCombatInfo() putSkills() putEquipments() root:wikitext(addChibi()) local templatestyles = mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = '模板:战术人形信息/styles.css' } } return cardstyles .. templatestyles .. tostring(root) end function p.gunInfo(frame) if frame == mw.getCurrentFrame() then args = frame:getParent().args else args = frame end return _gunInfo() end return p