-- 本模块为个人测试用 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='轻巡', CAV='航巡', BM='重炮', DD='驱逐', ASDG='导驱', SS='潜艇', SC='炮潜', AP='补给' } local shipTypeFullName = { CV='航空母舰', CVL='轻型航空母舰', BB='战列舰', BBV='航空战列舰', BC='战列巡洋舰', CA='重巡洋舰', CL='轻巡洋舰', 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 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] 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 .. '‌' 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 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] local ret = 'id="' .. equiptName .. '"|' ret = ret .. equipt['index'] .. '||' .. getEquiptIcon(equipt, '70px') ret = ret .. '||' .. addColor(equiptName, equipt.rarity, true) 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 p['彩色'] = function(frame) local str = frame.args[1] local noBold = frame.args[2] return rainbow(str, noBold == nil) end p['自带'] = function(frame) local equiptName = frame.args[1] return onShip(equiptName) end p['debug'] = function() local frame = { } frame.args = { '胡德·改' } return p['技能描述2'](frame) end return p