2023年政策修订增补工作正在进行中,欢迎参与!
  • Moegirl.ICU:萌娘百科流亡社群 581077156(QQ),欢迎对萌娘百科运营感到失望的编辑者加入
  • Moegirl.ICU:账号认领正在试运行,有意者请参照账号认领流程

Module:战舰少女

萌娘百科,万物皆可萌的百科全书!转载请标注来源页面的网页链接,并声明引自萌娘百科。内容不可商用。
跳转到导航 跳转到搜索
Template-info.svg 模块文档  [查看] [编辑] [历史] [刷新]

综述

提供从数据列表中自动查找数据并添加格式的各种功能

基本语法: {{#invoke:战舰少女|功能名|参数1|参数2|...}}

数据储存在以下几个文件中:

模块:战舰少女:数据(注:此模块为模块:战舰少女:舰娘属性列表模块:战舰少女:装备属性列表模块:战舰少女:台词的集合,以上3个模块不再记录数据)

模块:战舰少女:敌舰属性列表

模块:战舰少女:别名 (包括立绘文件名)

其中大部分内容可以用这个程序自动生成

舰娘

显示船的名字, 默认高亮加粗并添加链接

可通过第二个参数删除部分样式 (c:高亮 , b:加粗 , l:链接)

{{#invoke:战舰少女|舰娘|列克星敦(CV-2)}}

列克星敦(CV-2)

{{#invoke:战舰少女|舰娘|胡德·改|l}}

·改

{{#invoke:战舰少女|舰娘|列克星敦(CV-2)·改|cb}}

列克星敦(CV-2)·改

舰娘属性

显示船的属性, 对于可成长属性会显示成 基本属性(属性上限) 的格式

属性名具体参见模块:战舰少女:舰娘属性列表

{{#invoke:战舰少女|舰娘属性|列克星敦(CV-2)|火力}}

0(35)

图鉴编号

{{#invoke:战舰少女|图鉴编号|列克星敦(CV-2)}}

29

稀有度

重载1: 1个参数

{{#invoke:战舰少女|稀有度|列克星敦(CV-2)·改}}

5

重载2: 2个参数 将数字以彩色显示

{{#invoke:战舰少女|稀有度|列克星敦(CV-2)|彩色}}

4

改造属性

显示船改前和改后的属性, 格式为 改前 → 改后

{{#invoke:战舰少女|改造属性|列克星敦(CV-2)|火力}}

0(35) → 0(40)

舰娘属性列表

自动生成所有特定种类舰娘的属性表格, 具体见 战舰少女/属性列表

舰娘立绘

图片大小也可以不填(太大了所以不演示了)

{{#invoke:战舰少女|舰娘立绘|列克星敦(CV-2)|150px}}

L NORMAL 29.png

大破立绘

{{#invoke:战舰少女|大破立绘|列克星敦(CV-2)|100px}}

L BROKEN 29.png

台词

{{#invoke:战舰少女|台词|<船名>|<台词种类>|<替换>}}

台词种类可以是: 自荐, 获得, 白天1, 白天2, 白天3, 夜间1, 夜间2, 夜间3, 阵型, 攻击, 夜战, 中破, 誓约

替换可以省略, 如果不省略则将台词替换为该内容

{{#invoke:战舰少女|台词|列克星敦(CV-2)·改|获得}}

休假完毕~海风真是舒爽呢~

{{#invoke:战舰少女|台词|列克星敦(CV-2)·改|获得|替换成这个}}

替换成这个

装备

{{#invoke:战舰少女|装备|BTD-1毁灭者}}

68BTD-1毁灭者.pngBTD-1毁灭者

装备列表行

生成装备数据表格的一行, 详见战舰少女/装备

装备按钮

重载1: 1个参数

{{#invoke:战舰少女|装备按钮|B-25(杜立特队)}}

B-25(杜立特队).pngB-25()

轰炸+20

重载2: 2个参数

{{#invoke:战舰少女|装备按钮|巨像|2}}

171 萤火虫.png萤火虫

对空+6
轰炸+7
对潜+3

装备反向检索舰娘

列出自带所填写装备的所有舰娘:

{{#invoke:战舰少女|自带|J国12.7厘米连装炮}}

吹雪白雪初雪深雪绫波敷波阳炎不知火黑潮雪风白露时雨村雨夕立吹雪·改白雪·改初雪·改深雪·改晓·改雷·改电·改绫波·改敷波·改自带

敌舰列表

显示6个敌舰的链接(不足6个时补空格子), 并自动计算平均航速和制空值

{{#invoke:战舰少女|敌舰列表|轻母Ξ级III型|轻母Ξ级III型|轻巡Ζ级III型|轻巡Ζ级III型|驱逐Τ级II型}}

轻母Ξ级Ⅲ型||轻母Ξ级Ⅲ型||轻巡Ζ级Ⅲ型||轻巡Ζ级Ⅲ型||驱逐Τ级Ⅱ型||||144||35||28.90

local data = mw.loadData("模块:战舰少女:特殊数据")
local enemies = mw.loadData("模块:战舰少女:敌舰属性列表")
local alias = mw.loadData("模块:战舰少女:别名")
local ships = data.ships
local equipts = data.equipts
local skills = data.skills
local tr = data.tr
local equiptDisplay = data.equiptDisplay
local byIndex = data.byIndex
local p = {}

-- Tables --
local shipTypeAbbrName = { CV='航母', CVL='轻母', AV='装母', BB='战列', BBV='航战', BC='战巡', CA='重巡', CL='轻巡', CLT='雷巡', CAV='航巡', BM='重炮', DD='驱逐', ASDG='导驱', SS='潜艇', SC='炮潜', AP='补给' }

local shipTypeFullName = {
    CV='航空母舰', CVL='轻型航空母舰', BB='战列舰', BBV='航空战列舰', BC='战列巡洋舰',
    CA='重巡洋舰', CL='轻巡洋舰', CLT='重雷装巡洋舰', CAV='航空巡洋舰', BM='浅水重炮舰', DD='驱逐舰', ASDG='导弹驱逐舰', SS='潜水艇', SC='重炮潜艇', AP='补给舰'
}

local color = { 'black', 'green', 'blue', 'purple', 'orange', 'red' }

local rangeName = { '无', '短', '中', '长', '超长' }

-- 6星字体颜色的调色板, 每行一个颜色(格式{r,g,b}), 从最左到最右均匀分布, 支持任意种颜色
local palette = {
    { 0xf3, 0xc7, 0x41 },
    { 0xe2, 0x1d, 0x3a },
    { 0xbb, 0x44, 0xb8 },
    { 0x3c, 0x7a, 0xf7 }
}

local function rainbow(str, bold)
    local n = mw.ustring.len(str)
    local m = #palette - 1

    local hasDot = false
    if mw.ustring.sub(str, n - 1, n - 1) == '·' then
        hasDot = true
        str = mw.ustring.gsub(str, '·改', '改')
        n = n - 1
    end

    local ret = ''
    local dbg = ''
    for i = 1,n do
        local p = i - 0.5
        local r = 1
        while p * m > n * r do
            r = r + 1
        end
        local l = r - 1
        local pl = n * l / m
        local pr = n * r / m
        local wl = (pr - p) / (pr - pl)
        local wr = (p - pl) / (pr - pl)
        local cr = math.floor(palette[l + 1][1] * wl + palette[r + 1][1] * wr + 0.5)
        local cg = math.floor(palette[l + 1][2] * wl + palette[r + 1][2] * wr + 0.5)
        local cb = math.floor(palette[l + 1][3] * wl + palette[r + 1][3] * wr + 0.5)
        local color = string.format('#%02x%02x%02x', cr, cg, cb)
        
        local ch = mw.ustring.sub(str, i, i)
        if hasDot and i == n then ch = "·" .. ch end
        if bold then ch = "'''" .. ch .. "'''" end
        ret = ret .. "<span style='color:" .. color .. ";'>" .. ch .. "</span>"
    end
    return ret
end

function addColor(str, rarity, bold)
    if rarity == 6 then
        return rainbow(str, bold)
    end
    if rarity < 1 then rarity = 1 end
    if bold then str = "'''" .. str .. "'''" end
    return '<span style="color:' .. color[rarity] .. ';">' .. str .. '</span>'
end

-- ## Helper functions ##

local function formatFloat(x)
    if x == 0 then return 0 end
    x = math.floor(x * 100 + 0.5) / 100
    return string.format('%.2f', x)
end

local function getImage(aliasName, index, prefix, size)
    local ret = prefix .. index .. '.png'
    if aliasName ~= nil and aliasName ~= '' then
        ret = aliasName .. '.png'
    end
    if size ~= nil then
        ret = ret .. '|' .. size
    end
    return '[[File:' .. ret .. ']]'
end

local function notContains(str, ch)
    if str == nil then return true end
    return string.find(str, ch) == nil
end

-- ## Ship functions ##

local function getBaseName(name)
    if alias.shipBaseName[name] ~= nil then
        return alias.shipBaseName[name]
    end

    name = string.gsub(name, '·改', '')
    name = string.gsub(name, '(特殊)', '')

    if mw.ustring.sub(name, 1, 2) == '航母' then return '敌航空母舰' end
    if mw.ustring.sub(name, 1, 2) == '轻母' then return '敌轻型航母' end
    if mw.ustring.sub(name, 1, 2) == '战列' then return '敌战列舰' end
    if mw.ustring.sub(name, 1, 2) == '战巡' then return '敌战列巡洋舰' end
    if mw.ustring.sub(name, 1, 2) == '旗舰' then return '敌航空战列舰' end
    if mw.ustring.sub(name, 1, 2) == '重巡' then return '敌重巡洋舰' end
    if mw.ustring.sub(name, 1, 2) == '雷巡' then return '敌重雷装巡洋舰' end
    if mw.ustring.sub(name, 1, 2) == '轻巡' then return '敌轻巡洋舰' end
    if mw.ustring.sub(name, 1, 2) == '驱逐' then return '敌驱逐舰' end
    if mw.ustring.sub(name, 1, 2) == '潜艇' then return '潜艇' end
    if mw.ustring.sub(name, 1, 2) == '补给' then return '敌补给舰' end

    return name
end

local function formatShipTitle(shipName, removeStyles, frame)
    local isBold = notContains(removeStyles, 'b')
    local hasColor = notContains(removeStyles, 'c')
    local hasLink = notContains(removeStyles, 'l')
    
    local ret = shipName
    local ship = ships[shipName]
    if ship == nil then ship = enemies[fixEnemyName(shipName)] end  -- backward compatibility

    if hasColor and ship ~= nil then
        ret = addColor(ret, ship.rarity, isBold)
    elseif isBold then
        ret = "'''" .. ret .. "'''"
    end
    if hasLink then
        ret = '[[战舰少女:' .. getBaseName(shipName) .. '|' .. ret .. ']]'
    end
    return ret
end

-- Get an attribute of a ship.
-- Return in 'BASE(MAX)' format if the attribute can grow with level or strengthen.
local function getAttr(shipName, attrName)
    local ship = ships[shipName]

    local canGrow = false
    for i,v in pairs({'火力', '装甲', '鱼雷', '对空', '回避', '对潜', '索敌'}) do
        if attrName == v then
            canGrow = true
            break
        end
    end
    if canGrow then
        local base = ship[tr['基础' .. attrName]]
        local max_ = ship[tr[attrName .. '上限']]
        if base == max_ then
            return base
        else
            return base .. '(' .. max_ .. ')'
        end

    elseif attrName == '搭载' then
        return ship.cap1 + ship.cap2 + ship.cap3 + ship.cap4

    else
        local ret = ship[tr[attrName]]
        if ret == nil then ret = '' end  -- some ships lack attributes about modification
        return ret
    end
end

-- Get a list of attributes, splited by '||' (in favor of wiki table).
local function getAttrList(shipName, attrNameList)
    local ret = ''
    for i,attrName in pairs(attrNameList) do
        ret = ret .. getAttr(shipName, attrName) .. '||'
    end
    return string.sub(ret, 1, -3)
end

local function getShipNormalImage(shipName, size)
    return getImage(alias.shipNormalImage[shipName], ships[shipName].index, 'L_NORMAL_', size)
end

local function getShipBrokenImage(shipName, size)
    return getImage(alias.shipBrokenImage[shipName], ships[shipName].index, 'L_BROKEN_', size)
end

local function getShipDialogue(header, shipName, dialogueType, replace)
    local ret = '|-\n|style="text-align:center"|' .. header .. '||'
    if replace ~= '' and replace ~= nil then
        return ret .. replace .. '\n'
    else
        if (ships[shipName] == nil) then return '\n警告:错误的船名"' .. shipName .. '"\n\n' end
        local d = ships[shipName][dialogueType]
        if d == nil or d == '' then
            return ''
        else
            return ret .. ships[shipName][dialogueType] .. '\n'
        end
    end
end

-- ## Equipment functions ##

local function formatEquiptListAttr(equiptName, attrName)
    local equipt = equipts[equiptName] or {}
    local attr = equipt[tr[attrName]]
    if attr == nil then attr = 0 end
    local ret = 'data-sort-value="' .. attr .. '"|'
    if attrName == '射程' then
        ret = ret .. rangeName[attr + 1]
    elseif attrName == '耗铝' then
        ret = attr
    elseif attr == 0 then
        ret = ret .. '&zwnj;'
    elseif attrName == '对空补正' then
        ret = ret .. attr .. '%'
    elseif attr > 0 then
        ret = ret .. attrName .. '<wbr>+' .. attr
    else
        ret = ret .. attrName .. '<wbr>' .. attr
    end
    return ret
end

local function formatEquiptButtonAttr(name, val)
    if name == '射程' then
        return name .. ':' .. rangeName[val + 1] .. '<br>'
    elseif name == '对空补正' then
        return name .. ':' .. val .. '%<br>'
    elseif name == '耗铝' then
        return ''
    elseif val > 0 then
        return name .. '+' .. val .. '<br>'
    else
        return name .. val .. '<br>'
    end
end


local function getEquiptIcon(equipt, size)
    return getImage(alias.equiptIcon[equipt.index], equipt.index, 'Equip_L_', size)
end

local function fixEquiptName(name)
    name = string.gsub(name, 'Ⅲ', 'III')
    name = string.gsub(name, 'Ⅵ', 'VI')
    name = string.gsub(name, '日本', 'J国')
    name = string.gsub(name, '德国', 'G国')
    name = string.gsub(name, '英国', 'E国')
    name = string.gsub(name, '美国', 'U国')
    name = string.gsub(name, '意大利', 'I国')
    name = string.gsub(name, '法国', 'F国')
    name = string.gsub(name, '德国', 'G国')
    name = string.gsub(name, '苏联', 'S国')
    name = string.gsub(name, '中国', 'C国')
    local ret = alias.equiptName[name]
    if ret == nil then ret = name end
    return ret
end

local function onShip(equiptName)
    local ret = ''
    for i = 1,1300 do
        local shipName = byIndex[i]
        if shipName ~= nil then
            local eq = {ships[shipName].eq1, ships[shipName].eq2, ships[shipName].eq3, ships[shipName].eq4}
            for k = 1,4 do
                if eq[k] == equiptName then
                    if i > 1000 and i < 2000 then
                        local shipBaseName = byIndex[i - 1000]
                        ret = ret .. '[[战舰少女:' .. shipBaseName .. '|' .. shipName .. ']]、'
                    else
                        ret = ret .. '[[战舰少女:' .. shipName .. '|' .. shipName .. ']]、'
                    end
                    break
                end
            end
        end
    end
    ret = string.sub(ret, 1, -4)
    if ret ~= '' and ret ~= nil then
        ret = ret .. '自带'
    end
    return ret
end

-- ## Ship ##

p['舰娘'] = function(frame)
    local shipName = frame.args[1]
    local removeStyles = frame.args[2]
    return formatShipTitle(shipName, removeStyles, frame)
end

p['属性'] = function(frame)
    local ship = ships[frame.args[1]]
    if ship == nil then return '' end
    local attr = frame.args[2]
    if ship[attr] == nil then return '' end
    return ship[attr]
end

-- {{#invoke:战舰少女|舰娘属性|船名|属性名}} -> 属性
p['舰娘属性'] = function(frame)
    local shipName = frame.args[1]
    local attrName = frame.args[2]
    return getAttr(shipName, attrName)
end

-- {{#invoke:战舰少女|图鉴编号|船名}} -> 图鉴编号
p['图鉴编号'] = function(frame)
    return ships[frame.args[1]].index
end

-- {{#invoke:战舰少女|稀有度|船名}} -> 稀有度
p['稀有度'] = function(frame)
    local shipName = frame.args[1]
    local colorful = frame.args[2]
    local r = ships[shipName].rarity
    if colorful then
        return "<span style='color:" .. color[r] .. ";'>'''" .. r .. "'''</span>"
    else
        return r
    end
end

-- {{#invoke:战舰少女|改造属性|船名|属性名}} -> "改前属性 → 改后属性"
p['改造属性'] = function(frame)
    local baseShipName = frame.args[1]
    local attrName = frame.args[2]
    local modShipName = byIndex[ships[baseShipName].index + 1000]
    local baseAttr = getAttr(baseShipName, attrName)
    local modAttr = getAttr(modShipName, attrName)
    if baseAttr == modAttr then
        return baseAttr
    else
        return baseAttr .. ' → ' .. modAttr
    end
end

-- {{#invoke:战舰少女|舰娘属性列表|舰种|属性1,属性2,...}}
p['舰娘属性列表'] = function(frame)
    local shipType = frame.args[1]
    local attrNameList = mw.text.split(frame.args[2], ',', true)

    -- table title
    ret = '|-\n!colspan=' .. (#attrNameList + 3) .. '|' .. shipTypeAbbrName[shipType] .. '属性列表\n'

    -- table header
    ret = ret .. '|-\n!图鉴<br>编号!!头像!!名称'
    for i,attrName in pairs(attrNameList) do
        ret = ret .. '!!'
        if mw.ustring.len(attrName) > 2 then  -- break long headers into two lines
            ret = ret .. mw.ustring.sub(attrName, 1, 2)
            local tmp = mw.ustring.sub(attrName, 3, -1)
            if tmp ~= '上限' then
                ret = ret .. '<br>' .. tmp
            end
        else
            ret = ret .. attrName
        end
    end
    ret = ret .. '\n'

    -- table content
    for i = 1,1300 do  -- keys of table will be sorted as string by default (11>2)
        local shipName = byIndex[i]
        if shipName ~= nil and ships[shipName].type == shipType then
            ret = ret .. '|-\n|' .. i
            ret = ret .. '||' .. getShipProfile(shipName, '150px')
            ret = ret .. '||' .. formatShipTitle(shipName)
            ret = ret .. '||' .. getAttrList(shipName, attrNameList) ..'\n'
        end
    end
    return ret
end

p['舰娘立绘'] = function(frame)
    local shipName = frame.args[1]
    local size = frame.args[2]
    return getShipNormalImage(shipName, size)
end

p['大破立绘'] = function(frame)
    local shipName = frame.args[1]
    local size = frame.args[2]
    return getShipBrokenImage(shipName, size)
end

function getShipProfile(shipName, size)
    local ret = alias.profile[shipName]
    if ret == nil then
        local tmp = ships[shipName]
        if tmp == nil then return shipName end
        ret = ships[shipName].index
    end
    ret = '[[File:Warship_Girls_icon_' .. ret .. '.png|link=战舰少女:' .. getBaseName(shipName)
    if size ~= nil and size ~= '' then ret = ret .. '|' .. size end
    return ret .. ']]'
end

p['头像'] = function(frame)
    return getShipProfile(frame.args[1], frame.args[2])
end

p['台词'] = function(frame)
    local shipName = frame.args[1]
    local dialogue = frame.args[2]
    local force = frame.args[3]
    if force ~= nil and force ~= '' then return force end
    if ships[shipName] == nil then return "none" 
    else return ships[shipName][dialogue] end
end

function skillDesc(skillName)
    local desc = skills[skillName]
    if desc == nil then return '' end
    desc = desc:gsub('_G%[_', '<span style="color:green;">')
    desc = desc:gsub('_R%[_', '<span style="color:red;">')
    desc = desc:gsub('_%]_', '</span>')
    return desc
end

p['技能描述'] = function(frame)
    local shipName = frame.args[1]
    return skillDesc(ships[shipName].skill)
end

p['技能描述2'] = function(frame)
    local shipName = frame.args[1]
    return skillDesc(ships[shipName].skill2)
end

-- ## Equipment ##

p['装备'] = function(frame)
    local name = frame.args[1]
    name = fixEquiptName(name)
    local equipt = equipts[name]
    if (equipt == nil) then return "'''" .. name .. "'''" end
    local icon = getEquiptIcon(equipt, '25px')
    local title = addColor(name, equipt.rarity, true)
    return icon .. '[[战舰少女/装备#' .. name .. '|' .. title .. ']]'
end

-- {{#invoke:战舰少女|装备列表行|装备类型|装备名|备注}}
p['装备列表行'] = function(frame)
    local equiptType = frame.args[1]
    local equiptName = frame.args[2]
    local remarks = frame.args[3]
    local onShip = onShip(equiptName)
    equiptName = fixEquiptName(equiptName)

    local equipt = equipts[equiptName] or {}
    local ret = 'id="' .. equiptName .. '"|'
    ret = ret .. (equipt.index or ' ') .. '||' .. (equipt.index and getEquiptIcon(equipt, '70px') or ' ')
    ret = ret .. '||' .. (equipt.rarity and addColor(equiptName, equipt.rarity, true) or "'''" .. equiptName .. "'''")

    for i, attrName in pairs(equiptDisplay[equiptType]) do
        ret = ret .. '||' .. formatEquiptListAttr(equiptName, attrName)
    end
    
    ret = ret .. '||'
    if remarks == '' or remarks == nil then
        ret = ret .. onShip
    elseif string.find(remarks, '<自带>') ~= nil then
        local z = string.find(remarks, '<自带>')
        remarks = string.sub(remarks, 1, z-1) .. onShip .. string.sub(remarks, z+8, -1)
        ret = ret .. remarks
    else
        ret = ret .. remarks
    end
    return ret
end

local attrOrder = { '火力', '鱼雷', '装甲', '对空', '轰炸', '索敌', '对潜', '命中', '回避', '幸运', '射程', '对空补正', '耗铝' }

p['装备按钮'] = function(frame)
    local equiptName = frame.args[1]
    if frame.args[2] ~= nil then
        equiptName = ships[frame.args[1]]['eq' .. frame.args[2]]
    end

    local equipt = equipts[equiptName]
    if equipt == nil then return equiptName end

    btn = getEquiptIcon(equipt, '25px') .. addColor(equiptName, equipt.rarity, true)
    ctnt = ''
    for i, attrName in pairs(attrOrder) do
        local attrVal = equipt[tr[attrName]]
        if attrVal ~= 0 and attrVal ~= nil then
            ctnt = ctnt .. formatEquiptButtonAttr(attrName, attrVal)
        end
    end
    if equipt['special'] ~= nil then
        ctnt = ctnt .. equipt['special']
    end
    return frame:expandTemplate{ title = 'Toggle', args = { button=btn, content=ctnt } }
end

-- ## Enemies ##

function fixEnemyName(name)
    name = name:gsub('IV', 'Ⅳ')
    name = name:gsub('V', 'Ⅴ')
    name = name:gsub('III', 'Ⅲ')
    name = name:gsub('II', 'Ⅱ')
    name = name:gsub('I', 'Ⅰ')
    return name
end

p['敌舰列表'] = function(frame)
    local colors = { 'black', 'green', 'blue', 'purple', 'orange', 'red' }
    local ret = ''
    local rec = 0
    local aa = 0
    local speed = { 0, 0, 0 }
    local n = { 0, 0, 0 }
    for i = 1,6 do
        name = frame.args[i]
        if name == nil then
            ret = ret .. '||'
        else
            name = fixEnemyName(name)
            ret = ret .. formatShipTitle(name, 'b') .. '||'
            local ship = enemies[name]
            rec = rec + ship.rec
            aa = aa + ship.aa
            speed[ship.class] = speed[ship.class] + ship.speed
            n[ship.class] = n[ship.class] + 1
        end
    end
    local s = 0
    if n[1] == 0 and n[2] == 0 then
        s = speed[3] / n[3]
    else
        s = math.min(speed[1] / n[1], speed[2] / n[2])
    end
    return ret .. rec .. '||' .. math.floor(s) .. '||' .. formatFloat(aa)
end

-- ## Other ##

-- {{#invoke:战舰少女|自带|装备名}}
p['自带'] = function(frame)
    local equiptName = frame.args[1]
    return onShip(equiptName)
end

p['彩色'] = function(frame)
    local str = frame.args[1]
    local noBold = frame.args[2]
    return rainbow(str, noBold == nil)
end

p['debug'] = function()
    local frame = { }
    frame.args = { '胡德·改' }
    return p['技能描述2'](frame)
end

return p