- Welcome to the Kancolle Wiki!
- If you have any questions regarding site content, account registration, etc., please visit the KanColle Wiki Discord
Difference between revisions of "Module:Sandbox/Combat"
Jump to navigation
Jump to search
m |
m |
||
Line 216: | Line 216: | ||
self.ammo = ship.ammo or 1 | self.ammo = ship.ammo or 1 | ||
return self | return self | ||
+ | |||
+ | end | ||
+ | |||
+ | -- * Table utils. | ||
+ | |||
+ | local format = require('Module:StringInterpolation').format | ||
+ | local Formatting = require('Module:Formatting') | ||
+ | local StatIcons = require('Module:StatIcons') | ||
+ | local Ship = require('Module:Ship') | ||
+ | |||
+ | local equipment = { | ||
+ | DD = { | ||
+ | main = { | ||
+ | { firepower = 3, rank = 10, k = 1 }, | ||
+ | { firepower = 3, rank = 10, k = 1 }, | ||
+ | }, | ||
+ | torpedo = { | ||
+ | -- Quint/53 | ||
+ | { torpedo = 12, rank = 10, k = 1 }, | ||
+ | { torpedo = 12, rank = 10, k = 1 }, | ||
+ | { torpedo = 12, rank = 10, k = 1 }, | ||
+ | }, | ||
+ | }, | ||
+ | CL = { | ||
+ | -- 20.3 #3 | ||
+ | main = { | ||
+ | { firepower = 10, rank = 10, k = 1 }, | ||
+ | { firepower = 10, rank = 10, k = 1 }, | ||
+ | }, | ||
+ | torpedo = { | ||
+ | { torpedo = 12, rank = 10, k = 1 }, | ||
+ | { torpedo = 12, rank = 10, k = 1 }, | ||
+ | { torpedo = 12, rank = 10, k = 1 }, | ||
+ | }, | ||
+ | }, | ||
+ | CLT = { | ||
+ | main = { | ||
+ | -- OTO | ||
+ | { firepower = 8, rank = 10, k = 1 }, | ||
+ | { firepower = 8, rank = 10, k = 1 }, | ||
+ | -- Hyouteki | ||
+ | { torpedo = 12 }, | ||
+ | }, | ||
+ | torpedo = { | ||
+ | { torpedo = 12, rank = 10, k = 1 }, | ||
+ | { torpedo = 12, rank = 10, k = 1 }, | ||
+ | { torpedo = 12 }, | ||
+ | }, | ||
+ | }, | ||
+ | CA = { | ||
+ | main = { | ||
+ | -- 20.3 #3 | ||
+ | { firepower = 10, rank = 10, k = 1 }, | ||
+ | { firepower = 10, rank = 10, k = 1 }, | ||
+ | -- FuMO | ||
+ | { firepower = 3 }, | ||
+ | }, | ||
+ | torpedo = { | ||
+ | { torpedo = 12, rank = 10, k = 1 }, | ||
+ | { torpedo = 12, rank = 10, k = 1 }, | ||
+ | { torpedo = 12, rank = 10, k = 1 }, | ||
+ | { torpedo = 12, rank = 10, k = 1 }, | ||
+ | }, | ||
+ | mixed = { | ||
+ | }, | ||
+ | }, | ||
+ | } | ||
+ | |||
+ | local normalized_type_code = { | ||
+ | DD = "DD", | ||
+ | CL = "CL", | ||
+ | CLT = "CLT", | ||
+ | FBB = "BB", | ||
+ | BB = "BB", | ||
+ | CAV = "CA", | ||
+ | BBV = "BB", | ||
+ | CVL = "CV", | ||
+ | CV = "CV", | ||
+ | CVB = "CV", | ||
+ | } | ||
+ | |||
+ | local type_code_to_template = { | ||
+ | DD = "main", | ||
+ | CL = "main", | ||
+ | CLT = "main", | ||
+ | CA = "main", | ||
+ | FBB = "main", | ||
+ | BB = "main", | ||
+ | CAV = "main_aviation", | ||
+ | BBV = "main_aviation", | ||
+ | CVL = "carrier", | ||
+ | CV = "carrier", | ||
+ | CVB = "carrier", | ||
+ | -- SS = "submarine", | ||
+ | -- SSV = "submarine_aviation", | ||
+ | -- AV = "...", | ||
+ | -- AO = "...", | ||
+ | } | ||
+ | |||
+ | function format_damage(ship_, type_code, damage_type_fn, equip_setup, night_attack, spotting) | ||
+ | local combat = Combat:new(night_attack) | ||
+ | local normal_damage = combat:damage(damage_type_fn(combat, Ship:new(ship_, {}, night_attack))) | ||
+ | local normal_damage_string = | ||
+ | normal_damage >= combat.cap | ||
+ | and string.format('<span style="color:red;">%s</span>', normal_damage) | ||
+ | or normal_damage | ||
+ | local equip = equipment[type_code][equip_setup] | ||
+ | spotting = spotting or 1 | ||
+ | local equip_damage_pre = combat:damage(damage_type_fn(combat, Ship:new(ship_, equip, night_attack))) | ||
+ | local equip_damage = combat:damage(damage_type_fn(combat, Ship:new(ship_, equip, night_attack, spotting))) | ||
+ | local equip_damage_string = | ||
+ | equip_damage_pre >= combat.cap | ||
+ | and string.format('<span style="color:red;">%s</span>', equip_damage) | ||
+ | or equip_damage | ||
+ | return | ||
+ | night_attack | ||
+ | and string.format("%s", equip_damage_string) | ||
+ | or string.format("%s, %s", normal_damage_string, equip_damage_string) | ||
+ | end | ||
+ | |||
+ | local templates = { | ||
+ | |||
+ | main = [[{| class="wikitable sortable typography-xl-optout" style="width:100%;" | ||
+ | ! colspan="2" | | ||
+ | ! colspan="4" |Day Battle | ||
+ | ! colspan="5" |Night Battle | ||
+ | |- | ||
+ | !style="width:60px;"|Rank | ||
+ | !style="width:80px;"|Name | ||
+ | !${fp} | ||
+ | !${torp} | ||
+ | !<span title="Damage: normal attack without equipment, ${db_attack_note} with maxed equipment (all other modifiers = 1, see notes)">Hit</span> | ||
+ | !<span title="Normal torpedo salvo damage, all modifiers = 1, see notes">Salvo</span> | ||
+ | !${fp_plus_torp} | ||
+ | !<span title="Maximal damage from double attack (combined)">DA</span> | ||
+ | !<span title="Maximal damage from cut-in">CI</span> | ||
+ | !${luck_minus_cap} | ||
+ | !<span title="Torpedo/mixed cut-in rate, gun cut-in rate (only luck dependent part, no bonuses)">CI%</span> | ||
+ | ${rows}|}]], | ||
+ | |||
+ | carrier = [[{| class="wikitable sortable typography-xl-optout" style="width:100%;" | ||
+ | !style="width:60px;"|Rank | ||
+ | !style="width:80px;"|Name | ||
+ | !${fp} | ||
+ | !<span title="Air Power with full >> Reppuu">Air Power</span> | ||
+ | !<span title="">Aerial Hit</span> | ||
+ | !<span title="">Shelling</span> | ||
+ | ${rows}|}]], | ||
+ | |||
+ | main_row = [[|- | ||
+ | |${rank} | ||
+ | |${name} | ||
+ | |${fp} | ||
+ | |${torp} | ||
+ | |${db_attack} | ||
+ | |${db_torp} | ||
+ | |${fp_plus_torp} | ||
+ | |${nb_da} | ||
+ | |${nb_ci} | ||
+ | |${luck_minus_cap} | ||
+ | |${nb_ci_rate} | ||
+ | ]], | ||
+ | |||
+ | carrier_row = [[|- | ||
+ | |${rank} | ||
+ | |${name} | ||
+ | |${fp} | ||
+ | | | ||
+ | | | ||
+ | | | ||
+ | ]], | ||
+ | |||
+ | } | ||
+ | |||
+ | local attacks = { | ||
+ | DD = { | ||
+ | spotting = 1, | ||
+ | note = "normal attack", | ||
+ | }, | ||
+ | CL = { | ||
+ | spotting = Combat.modifier.spotting.double, | ||
+ | note = "double attack", | ||
+ | }, | ||
+ | CLT = { | ||
+ | spotting = 1, | ||
+ | note = "normal attack", | ||
+ | }, | ||
+ | CA = { | ||
+ | spotting = Combat.modifier.spotting.double, | ||
+ | note = "double attack", | ||
+ | }, | ||
+ | } | ||
+ | |||
+ | function Combat.header(frame) | ||
+ | local type_code_ = frame.args["type"] | ||
+ | local type_code = normalized_type_code[type_code_] | ||
+ | local template = templates[type_code_to_template[type_code_]] | ||
+ | return format{ | ||
+ | template, | ||
+ | rows = frame.args[1] or "", | ||
+ | db_attack_note = attacks[type_code].note or "?", | ||
+ | fp = Formatting:format_image{StatIcons.firepower, caption = Formatting:format_stat_name("firepower")}, | ||
+ | torp = Formatting:format_image{StatIcons.torpedo, caption = Formatting:format_stat_name("torpedo")}, | ||
+ | fp_plus_torp = | ||
+ | Formatting:format_image{StatIcons.firepower, caption = Formatting:format_stat_name("firepower")} | ||
+ | .. "+" .. | ||
+ | Formatting:format_image{StatIcons.torpedo, caption = Formatting:format_stat_name("torpedo")}, | ||
+ | luck_minus_cap = | ||
+ | '<span title="Luck cap">60</span>−' .. | ||
+ | Formatting:format_image{StatIcons.luck, caption = Formatting:format_stat_name("luck")} | ||
+ | } | ||
+ | end | ||
+ | |||
+ | function Combat.row(frame) | ||
+ | |||
+ | local rank = frame.args[1] | ||
+ | local ship_key = frame.args[2] | ||
+ | local note = frame.args["note"] | ||
+ | |||
+ | local name, suffix = Ship:process_ship_key(ship_key) | ||
+ | local ship = Ship:get_table(name, suffix) | ||
+ | |||
+ | if rank and name and ship and ship._type then | ||
+ | |||
+ | local type_code_ = Formatting:format_ship_code(ship._type) | ||
+ | local type_code = normalized_type_code[type_code_] | ||
+ | local template = templates[type_code_to_template[type_code_] .. "_row"] | ||
+ | local luck_diff = 60 - ship._luck | ||
+ | |||
+ | return format{ | ||
+ | template, | ||
+ | rank = rank, | ||
+ | name = note and format{'[[${name}|<span title="${note}">${name}</span>]]<sup>?</sup>', name = name, note = note} or | ||
+ | string.format("[[%s]]", name), | ||
+ | fp = ship._firepower_max, | ||
+ | torp = ship._torpedo_max, | ||
+ | fp_plus_torp = ship._firepower_max + (ship._torpedo_max or 0), | ||
+ | db_attack = format_damage(ship, type_code, Combat.shelling, "main", nil, attacks[type_code].spotting), | ||
+ | db_torp = format_damage(ship, type_code, Combat.torpedo, "torpedo"), | ||
+ | nb_da = format_damage(ship, type_code, Combat.night_battle, "main", Combat.modifier.night_attack.double), | ||
+ | nb_ci = format_damage(ship, type_code, Combat.night_battle, "torpedo", Combat.modifier.night_attack.cut_in.torpedo), | ||
+ | luck_minus_cap = luck_diff < 0 and "−" .. -luck_diff or luck_diff, | ||
+ | nb_ci_rate = string.format( | ||
+ | "%s%%, %s%%", | ||
+ | Combat.nb_cut_in_rate(ship, Combat.nb_cut_in_types.torpedo), | ||
+ | Combat.nb_cut_in_rate(ship, Combat.nb_cut_in_types.main)), | ||
+ | } | ||
+ | else | ||
+ | return "" | ||
+ | end | ||
end | end | ||
return Combat | return Combat |
Revision as of 21:14, 22 October 2015
Documentation for this module may be created at Module:Sandbox/Combat/doc
-- **
-- Damage calculations are based on http://kancollecalc.web.fc2.com/damage_formula.html and WikiWiki combat page.
-- NB CI rate formula is from WikiWiki combat page (also, 検証、仮説スレ18).
--
local Combat = {}
-- * Experimental values.
Combat.modifier = {
comined_firepower = {
ctf_first = 0,
ctf_second = 10,
stf_first = 10,
stf_second = -5,
},
comined_torpedo = -5,
night_contact = 5,
formation = {
line_ahead = 1.0,
double_line = 0.8,
diamond = 0.7,
echelon = 0.6,
line_abreast = 0.6,
combined = {
line_ahead = 1.1,
diamond = 0.7,
double_line = 1.0,
line_abreast = 0.8,
},
},
engagement = {
green_t = 1.2,
parallel = 1.0,
head_on = 0.8,
red_t = 0.6,
},
health = {
normal = 1.0,
chuuha = 0.7,
taiha = 0.4,
},
anti_ground = 2.5,
wg_bonus = 75,
cap = {
day = 150,
night = 300,
},
spotting = {
cut_in = {
main_main = 1.5,
main_ap = 1.3,
main_radar = 1.2,
main_second = 1.1,
},
double = 1.2,
},
night_attack = {
cut_in = {
main = 2,
main_misc = 1.75,
torpedo = 1.5,
mixed = 1.3,
},
double = 1.2,
normal = 1,
},
critical = 1.5,
ap = {
main_ap = 1.08,
main_ap_radar = 1.1,
main_second_ap = 1.15,
main_second_ap_radar = 1.15,
},
}
function Combat.ammo_modifier(ammo_bars)
return ammo_bars >= 5 and 1 or ammo_bars / 5
end
-- * Combat object with ship-independent values as fields.
-- Ship and enemy values are passed via arguments.
function Combat:new(is_night_battle)
local stage = {
combined_firepower = 0,
combined_torpedo = 0,
formation = self.modifier.formation.line_ahead,
engagement = self.modifier.engagement.parallel,
night_contact = 0,
is_night_battle = is_night_battle,
cap = is_night_battle and self.modifier.cap.night or self.modifier.cap.day,
contact = 1, -- TODO
expert = 1, -- TODO
}
setmetatable(stage, self)
self.__index = self
return stage
end
function Combat:damage_pre_cap(ship)
return self.engagement * self.formation * ship.health * ship.anti_ground * ship.anti_sub * ship.night_attack * ship.attack_power
end
function Combat:damage_cap(attack_power)
if attack_power > self.cap then
attack_power = self.cap + math.sqrt(attack_power - self.cap)
end
return math.floor(attack_power)
end
function Combat:damage_post_cap(attack_power, ship, enemy_armor)
attack_power = ship.spotting * self.contact * math.floor(self.expert * ship.critical * math.floor(ship.ap * attack_power))
-- Use a note on a caller side instead
--if ship.night_attack_x2 then
-- attack_power = 2 * attack_power
--end
if enemy_armor then
local min_armor = enemy_armor * 0.7
local max_armor = enemy_armor * 0.7 + math.max(enemy_armor - 1, 0) * 0.6
local min = math.floor((attack_power - max_armor) * ship.ammo)
local max = math.floor((attack_power - min_armor) * ship.ammo)
return { min, max }
else
return math.floor(attack_power * ship.ammo)
end
end
-- TODO: pass enemy table, do additional detection (e.g. torpedo = 0 vs. ground type enemies
-- or attack_power = 0 when BB vs. enemy submarines, etc.)
function Combat:damage(ship, enemy_armor)
return self:damage_post_cap(self:damage_cap(self:damage_pre_cap(ship)), ship, enemy_armor)
end
-- TODO: carrier shelling, aerial, ASW, support expedition.
Combat.nb_cut_in_types = {
torpedo = { k = 70, luck_cap = 60 },
mixed = { k = 70, luck_cap = 70 },
main = { k = 50, luck_cap = 55 },
}
function Combat.nb_cut_in_rate(ship, modifier)
if ship._luck <= modifier.luck_cap then
return math.floor(math.sqrt(modifier.k * ship._luck))
else
return Combat.nb_cut_in_rate(modifier.luck_cap, modifier)
end
end
function Combat:shelling(ship)
ship.attack_power = 5 + ship._firepower_max + ship.equipment_bonus.firepower + self.combined_firepower + ship.anti_ground_bonus
return ship
end
function Combat:torpedo(ship)
ship.attack_power = 5 + ship._torpedo_max + ship.equipment_bonus.torpedo + self.combined_torpedo
return ship
end
function Combat:night_battle(ship)
if ship.health == self.modifier.health.taiha then
ship.attack_power = 0
else
ship.attack_power = self.night_contact + ship._firepower_max + ship._torpedo_max + ship.equipment_bonus.firepower + ship.equipment_bonus.torpedo
end
return ship
end
-- * Ship object with extra fields related to combat.
local Ship = {}
function Ship:new(ship, equip, night_attack, spotting)
self._firepower_max = ship._firepower_max or 0
self._torpedo_max = ship._torpedo_max or 0
self._luck = ship._luck or 0
self.equipment = equip or {}
self.equipment_bonus = { firepower = 0, torpedo = 0 }
for _, eq in pairs(self.equipment) do
if eq.firepower then
self.equipment_bonus.firepower = self.equipment_bonus.firepower + eq.firepower + (eq.k and eq.rank and eq.k * math.sqrt(eq.rank) or 0)
end
if eq.torpedo then
self.equipment_bonus.torpedo = self.equipment_bonus.torpedo + eq.torpedo + (eq.k and eq.rank and eq.k * math.sqrt(eq.rank) or 0)
end
end
self.equipment_bonus.firepower = math.floor(self.equipment_bonus.firepower)
self.equipment_bonus.torpedo = math.floor(self.equipment_bonus.torpedo)
self.health = ship.health or Combat.modifier.health.normal
self.anti_ground = ship.anti_ground and Combat.modifier.anti_ground or 1
self.anti_ground_bonus = ship.wg and Combat.modifier.wg_bonus or 0
self.anti_sub = ship.anti_sub or 1
self.night_attack = night_attack or 1
self.night_attack_x2 = night_attack == Combat.modifier.night_attack.cut_in.torpedo or
night_attack == Combat.modifier.night_attack.cut_in.mixed
self.spotting = spotting or 1
self.critical = ship.critical or 1
self.ap = ship.ap or 1
self.ammo = ship.ammo or 1
return self
end
-- * Table utils.
local format = require('Module:StringInterpolation').format
local Formatting = require('Module:Formatting')
local StatIcons = require('Module:StatIcons')
local Ship = require('Module:Ship')
local equipment = {
DD = {
main = {
{ firepower = 3, rank = 10, k = 1 },
{ firepower = 3, rank = 10, k = 1 },
},
torpedo = {
-- Quint/53
{ torpedo = 12, rank = 10, k = 1 },
{ torpedo = 12, rank = 10, k = 1 },
{ torpedo = 12, rank = 10, k = 1 },
},
},
CL = {
-- 20.3 #3
main = {
{ firepower = 10, rank = 10, k = 1 },
{ firepower = 10, rank = 10, k = 1 },
},
torpedo = {
{ torpedo = 12, rank = 10, k = 1 },
{ torpedo = 12, rank = 10, k = 1 },
{ torpedo = 12, rank = 10, k = 1 },
},
},
CLT = {
main = {
-- OTO
{ firepower = 8, rank = 10, k = 1 },
{ firepower = 8, rank = 10, k = 1 },
-- Hyouteki
{ torpedo = 12 },
},
torpedo = {
{ torpedo = 12, rank = 10, k = 1 },
{ torpedo = 12, rank = 10, k = 1 },
{ torpedo = 12 },
},
},
CA = {
main = {
-- 20.3 #3
{ firepower = 10, rank = 10, k = 1 },
{ firepower = 10, rank = 10, k = 1 },
-- FuMO
{ firepower = 3 },
},
torpedo = {
{ torpedo = 12, rank = 10, k = 1 },
{ torpedo = 12, rank = 10, k = 1 },
{ torpedo = 12, rank = 10, k = 1 },
{ torpedo = 12, rank = 10, k = 1 },
},
mixed = {
},
},
}
local normalized_type_code = {
DD = "DD",
CL = "CL",
CLT = "CLT",
FBB = "BB",
BB = "BB",
CAV = "CA",
BBV = "BB",
CVL = "CV",
CV = "CV",
CVB = "CV",
}
local type_code_to_template = {
DD = "main",
CL = "main",
CLT = "main",
CA = "main",
FBB = "main",
BB = "main",
CAV = "main_aviation",
BBV = "main_aviation",
CVL = "carrier",
CV = "carrier",
CVB = "carrier",
-- SS = "submarine",
-- SSV = "submarine_aviation",
-- AV = "...",
-- AO = "...",
}
function format_damage(ship_, type_code, damage_type_fn, equip_setup, night_attack, spotting)
local combat = Combat:new(night_attack)
local normal_damage = combat:damage(damage_type_fn(combat, Ship:new(ship_, {}, night_attack)))
local normal_damage_string =
normal_damage >= combat.cap
and string.format('<span style="color:red;">%s</span>', normal_damage)
or normal_damage
local equip = equipment[type_code][equip_setup]
spotting = spotting or 1
local equip_damage_pre = combat:damage(damage_type_fn(combat, Ship:new(ship_, equip, night_attack)))
local equip_damage = combat:damage(damage_type_fn(combat, Ship:new(ship_, equip, night_attack, spotting)))
local equip_damage_string =
equip_damage_pre >= combat.cap
and string.format('<span style="color:red;">%s</span>', equip_damage)
or equip_damage
return
night_attack
and string.format("%s", equip_damage_string)
or string.format("%s, %s", normal_damage_string, equip_damage_string)
end
local templates = {
main = [[{| class="wikitable sortable typography-xl-optout" style="width:100%;"
! colspan="2" |
! colspan="4" |Day Battle
! colspan="5" |Night Battle
|-
!style="width:60px;"|Rank
!style="width:80px;"|Name
!${fp}
!${torp}
!<span title="Damage: normal attack without equipment, ${db_attack_note} with maxed equipment (all other modifiers = 1, see notes)">Hit</span>
!<span title="Normal torpedo salvo damage, all modifiers = 1, see notes">Salvo</span>
!${fp_plus_torp}
!<span title="Maximal damage from double attack (combined)">DA</span>
!<span title="Maximal damage from cut-in">CI</span>
!${luck_minus_cap}
!<span title="Torpedo/mixed cut-in rate, gun cut-in rate (only luck dependent part, no bonuses)">CI%</span>
${rows}|}]],
carrier = [[{| class="wikitable sortable typography-xl-optout" style="width:100%;"
!style="width:60px;"|Rank
!style="width:80px;"|Name
!${fp}
!<span title="Air Power with full >> Reppuu">Air Power</span>
!<span title="">Aerial Hit</span>
!<span title="">Shelling</span>
${rows}|}]],
main_row = [[|-
|${rank}
|${name}
|${fp}
|${torp}
|${db_attack}
|${db_torp}
|${fp_plus_torp}
|${nb_da}
|${nb_ci}
|${luck_minus_cap}
|${nb_ci_rate}
]],
carrier_row = [[|-
|${rank}
|${name}
|${fp}
|
|
|
]],
}
local attacks = {
DD = {
spotting = 1,
note = "normal attack",
},
CL = {
spotting = Combat.modifier.spotting.double,
note = "double attack",
},
CLT = {
spotting = 1,
note = "normal attack",
},
CA = {
spotting = Combat.modifier.spotting.double,
note = "double attack",
},
}
function Combat.header(frame)
local type_code_ = frame.args["type"]
local type_code = normalized_type_code[type_code_]
local template = templates[type_code_to_template[type_code_]]
return format{
template,
rows = frame.args[1] or "",
db_attack_note = attacks[type_code].note or "?",
fp = Formatting:format_image{StatIcons.firepower, caption = Formatting:format_stat_name("firepower")},
torp = Formatting:format_image{StatIcons.torpedo, caption = Formatting:format_stat_name("torpedo")},
fp_plus_torp =
Formatting:format_image{StatIcons.firepower, caption = Formatting:format_stat_name("firepower")}
.. "+" ..
Formatting:format_image{StatIcons.torpedo, caption = Formatting:format_stat_name("torpedo")},
luck_minus_cap =
'<span title="Luck cap">60</span>−' ..
Formatting:format_image{StatIcons.luck, caption = Formatting:format_stat_name("luck")}
}
end
function Combat.row(frame)
local rank = frame.args[1]
local ship_key = frame.args[2]
local note = frame.args["note"]
local name, suffix = Ship:process_ship_key(ship_key)
local ship = Ship:get_table(name, suffix)
if rank and name and ship and ship._type then
local type_code_ = Formatting:format_ship_code(ship._type)
local type_code = normalized_type_code[type_code_]
local template = templates[type_code_to_template[type_code_] .. "_row"]
local luck_diff = 60 - ship._luck
return format{
template,
rank = rank,
name = note and format{'[[${name}|<span title="${note}">${name}</span>]]<sup>?</sup>', name = name, note = note} or
string.format("[[%s]]", name),
fp = ship._firepower_max,
torp = ship._torpedo_max,
fp_plus_torp = ship._firepower_max + (ship._torpedo_max or 0),
db_attack = format_damage(ship, type_code, Combat.shelling, "main", nil, attacks[type_code].spotting),
db_torp = format_damage(ship, type_code, Combat.torpedo, "torpedo"),
nb_da = format_damage(ship, type_code, Combat.night_battle, "main", Combat.modifier.night_attack.double),
nb_ci = format_damage(ship, type_code, Combat.night_battle, "torpedo", Combat.modifier.night_attack.cut_in.torpedo),
luck_minus_cap = luck_diff < 0 and "−" .. -luck_diff or luck_diff,
nb_ci_rate = string.format(
"%s%%, %s%%",
Combat.nb_cut_in_rate(ship, Combat.nb_cut_in_types.torpedo),
Combat.nb_cut_in_rate(ship, Combat.nb_cut_in_types.main)),
}
else
return ""
end
end
return Combat