Line 1: |
Line 1: |
− | local format = require("Module:Utils").format | + | local format = require("Module:Core").format |
| local BaseData = require("Module:BaseData") | | local BaseData = require("Module:BaseData") |
| local Formatting = require("Module:Formatting") | | local Formatting = require("Module:Formatting") |
Line 29: |
Line 29: |
| [7] = "Cut-in: Torpedo", | | [7] = "Cut-in: Torpedo", |
| [8] = "Bombing", | | [8] = "Bombing", |
| + | [9] = "Cut-in: Carrier", |
| }, | | }, |
| _night_battle_attack_counts = { | | _night_battle_attack_counts = { |
Line 36: |
Line 37: |
| }, | | }, |
| _asw_attack_modes = { | | _asw_attack_modes = { |
| + | opening = "Opening", |
| day = "Day", | | day = "Day", |
| night = "Night", | | night = "Night", |
Line 80: |
Line 82: |
| local asw_leveled = ship:asw_leveled() | | local asw_leveled = ship:asw_leveled() |
| return (asw_leveled == nil or asw_leveled > 0) | | return (asw_leveled == nil or asw_leveled > 0) |
− | and ship_type ~= 7 | + | and not self:_is_carrier(ship) |
| --[[ | | --[[ |
| ship_type == 2 | | ship_type == 2 |
Line 141: |
Line 143: |
| or ship_type == 14 | | or ship_type == 14 |
| end | | end |
− |
| + | |
| + | -- Automatically make units with 0 speed installations |
| + | -- todo: the effect of type 3 shell |
| function ShipCapabilities:_is_installation(ship) | | function ShipCapabilities:_is_installation(ship) |
| if not ship then | | if not ship then |
| ship = self._ship | | ship = self._ship |
| end | | end |
− | return ship:is_installation() | + | return ship:speed() == 0 and not ship:is_pillbox() |
| + | end |
| + | |
| + | -- The logic is copied from Kan Colle Kai |
| + | -- Automatically make most of enemy carriers night bombing |
| + | -- _night_bombing is now used to disable night bombing caused by firepower and torpedo, and not related to night ASW |
| + | function ShipCapabilities:_is_night_bombing(ship) |
| + | if not ship then |
| + | ship = self._ship |
| + | end |
| + | return ship:night_bombing() ~= false |
| + | and self:_is_carrier(ship) |
| + | and (ship:firepower() or 0) + (ship:torpedo() or 0) > 0 |
| end | | end |
| | | |
Line 180: |
Line 196: |
| or equipment_type == 8 | | or equipment_type == 8 |
| or equipment_type == 11 | | or equipment_type == 11 |
| + | or equipment_type == 47 |
| end | | end |
| | | |
Line 212: |
Line 229: |
| end | | end |
| | | |
− | -- small main guns', recon sea planes' and radars' asw is invalid | + | -- only following equipments' asw value are counted for attack |
− | function ShipCapabilities:_is_unable_asw_equip(equipment) | + | function ShipCapabilities:_is_damaging_asw_equip(equipment) |
| local equipment_type = equipment:type() | | local equipment_type = equipment:type() |
− | return equipment_type == 1 | + | return equipment_type == 7 |
− | or equipment_type == 10 | + | or equipment_type == 8 |
− | or equipment_type == 12 | + | or equipment_type == 11 |
− | or equipment_type == 13 | + | or equipment_type == 14 |
− | or equipment_type == 93 | + | or equipment_type == 15 |
| + | or equipment_type == 25 |
| + | or equipment_type == 26 |
| + | or equipment_type == 40 |
| end | | end |
| | | |
Line 241: |
Line 261: |
| function Self._is_active_midget_submarine(equipment) | | function Self._is_active_midget_submarine(equipment) |
| return equipment:id() == 41 or equipment:id() == 541 | | return equipment:id() == 41 or equipment:id() == 541 |
| + | end |
| + | |
| + | function ShipCapabilities:_is_night_aviation_personnel(equipment) |
| + | return equipment:id() == 258 |
| + | or equipment:id() == 259 |
| + | or equipment:id() == 608 |
| end | | end |
| | | |
Line 256: |
Line 282: |
| end | | end |
| return { type_3_shell_equiped = type_3_shells > 0, wg_equiped = wgs > 0 } | | return { type_3_shell_equiped = type_3_shells > 0, wg_equiped = wgs > 0 } |
| + | end |
| + | |
| + | -- Single Attack, Single Torpedo and Bombing are actually same |
| + | -- https://github.com/andanteyk/ElectronicObserver/blob/master/ElectronicObserver/Other/Information/kcmemo.md#%E5%A4%9C%E6%88%A6 |
| + | function ShipCapabilities:_single_attack_style(ship) |
| + | if not ship then |
| + | ship = self._ship |
| + | end |
| + | local ship_type = ship:type() |
| + | if ship_type == 13 or ship_type == 14 then |
| + | return 2 |
| + | end |
| + | if ship_type == 7 or ship_type == 11 or ship_type == 18 then |
| + | -- currently hard coding, lack of Graf Zeppelin (Kai) and Saratoga |
| + | -- a flag like _cv_night_shelling might be better? |
| + | local ship_name = ship:name() or "" |
| + | if ship_name:match("Lycoris Princess") or ship_name:match("Abyssal Jellyfish Princess") then |
| + | return 1 |
| + | elseif ship:id() == 1964 then |
| + | return 9 |
| + | else |
| + | return 8 |
| + | end |
| + | end |
| + | for i = 1, ship:slots_length() or 0 do |
| + | local equipment, size = ship:slot(i) |
| + | if equipment then |
| + | if self:_is_main_gun(equipment) or self:_is_secondary_gun(equipment) then |
| + | return 1 |
| + | elseif self:_is_torpedo(equipment) then |
| + | return 2 |
| + | end |
| + | end |
| + | end |
| + | return 1 |
| end | | end |
| | | |
Line 265: |
Line 326: |
| return nil | | return nil |
| end | | end |
− | local is_installation = self:_is_installation() | + | --[[ |
− | local shiptype = self._ship:type()
| + | local has_bomber_planes = false |
− | local is_installation_bb = ((shiptype == 8) or (shiptype == 9)) and is_installation | + | for i = 1, self._ship:slots_length() do |
− | if not self:_is_carrier() and not is_installation or is_installation_bb then | + | local equipment, size = self._ship:slot(i) |
| + | if equipment and self:_is_bomber(equipment) and size and size > 0 then |
| + | has_bomber_planes = true |
| + | break |
| + | end |
| + | end |
| + | ]]-- |
| + | local is_installation_bbv = self._ship:speed() == 0 and self._ship:type() == 10 |
| + | if not self:_is_carrier() and not is_installation_bbv then |
| if firepower > 0 then | | if firepower > 0 then |
| for i = 1, self._ship:slots_length() do | | for i = 1, self._ship:slots_length() do |
Line 325: |
Line 394: |
| torpedo = 0 | | torpedo = 0 |
| end | | end |
− | return is_installation and 3 or 2, 55 + math.floor(1.5 * (firepower + torpedo + math.floor(1.3 * bombing))) | + | return is_installation_bbv and 3 or 2, 55 + math.floor(1.5 * (firepower + torpedo + math.floor(1.3 * bombing))) |
| end | | end |
| end | | end |
Line 451: |
Line 520: |
| -- Or basic attack power for night battle attack, including night special attack, anti-installation and contact modifiers. | | -- Or basic attack power for night battle attack, including night special attack, anti-installation and contact modifiers. |
| function ShipCapabilities:night_battle(vs_installation, contact) | | function ShipCapabilities:night_battle(vs_installation, contact) |
− | local main_guns, secondary_guns, torpedoes, has_planes, firepower, torpedo = 0, 0, 0, false, self._ship:firepower_leveled(), self._ship:torpedo_leveled() | + | local main_guns, secondary_guns, torpedoes, has_planes, has_night_aviation_personnel, firepower, torpedo = 0, 0, 0, false, self._ship:night_aviation_personnel(), self._ship:firepower_leveled(), self._ship:torpedo_leveled() |
| if not firepower or not torpedo then | | if not firepower or not torpedo then |
| return nil | | return nil |
| end | | end |
| + | if firepower + torpedo <= 0 then |
| + | return false |
| + | end |
| for i = 1, self._ship:slots_length() or 0 do | | for i = 1, self._ship:slots_length() or 0 do |
| local equipment, size = self._ship:slot(i) | | local equipment, size = self._ship:slot(i) |
Line 472: |
Line 544: |
| equipment_torpedo = 0 | | equipment_torpedo = 0 |
| end | | end |
| + | elseif self:_is_night_aviation_personnel(equipment) then |
| + | has_night_aviation_personnel = true |
| end | | end |
| if equipment_firepower then | | if equipment_firepower then |
Line 484: |
Line 558: |
| firepower = firepower + 5 | | firepower = firepower + 5 |
| end | | end |
− | if self:_is_carrier() then | + | if self._ship:night_bombing() == false then |
− | if has_planes and self._ship:night_bombing() then
| + | -- if night bombing is forbidden |
− | return 8, firepower + torpedo
| |
− | end
| |
| return false | | return false |
| else | | else |
Line 516: |
Line 588: |
| elseif main_guns + secondary_guns >= 2 and firepower > 0 then | | elseif main_guns + secondary_guns >= 2 and firepower > 0 then |
| return 3, ((firepower + torpedo) * anti_installation_modifier + anti_installation_bonus) * 1.2 | | return 3, ((firepower + torpedo) * anti_installation_modifier + anti_installation_bonus) * 1.2 |
− | elseif torpedoes > 0 and torpedo > 0 then | + | -- WIP: just a hack for enemy CVs, no plane checked, only NF + NTB (120%) supported |
− | if vs_installation then
| + | elseif self:_is_carrier(self._ship) and has_night_aviation_personnel then |
− | return false
| + | return 9, ((firepower + torpedo) * anti_installation_modifier + anti_installation_bonus) * 1.2 |
− | else
| + | -- Single Attack, Single Torpedo and Bombing are actually same |
− | return 2, firepower + torpedo
| |
− | end
| |
− | elseif firepower > 0 then | |
− | return 1, (firepower + torpedo) * anti_installation_modifier + anti_installation_bonus
| |
| else | | else |
− | return false | + | return self:_single_attack_style(), (firepower + torpedo) * anti_installation_modifier + anti_installation_bonus |
| end | | end |
| end | | end |
Line 555: |
Line 623: |
| local is_player_submarine = not is_enemy and self:_is_submarine() | | local is_player_submarine = not is_enemy and self:_is_submarine() |
| if | | if |
| + | self._ship:opening_torpedo() == true or |
| not is_enemy_submarine and self:_find_equipment(Self._is_active_midget_submarine) or | | not is_enemy_submarine and self:_find_equipment(Self._is_active_midget_submarine) or |
| is_player_submarine and self._ship:level() and self._ship:level() >= 10 or | | is_player_submarine and self._ship:level() and self._ship:level() >= 10 or |
Line 572: |
Line 641: |
| function ShipCapabilities:asw_attack() | | function ShipCapabilities:asw_attack() |
| local base_asw | | local base_asw |
− | local asw_override, day, night = self._ship:asw_attack(), true, true | + | local asw_override, opening, day, night = self._ship:asw_attack(), false, true, true |
| if asw_override == false then | | if asw_override == false then |
| return false | | return false |
Line 579: |
Line 648: |
| elseif self:_is_asw_aviation_ship() then | | elseif self:_is_asw_aviation_ship() then |
| base_asw = 8 | | base_asw = 8 |
− | if not self._ship:night_bombing() or self._ship:asw_leveled() == 0 then | + | if not self:_is_night_bombing() or self._ship:asw_leveled() == 0 then |
| night = false | | night = false |
| end | | end |
Line 585: |
Line 654: |
| return false | | return false |
| end | | end |
| + | if self._ship._opening_asw then |
| + | opening = true |
| + | end |
| local asw_leveled = self._ship:asw_leveled() | | local asw_leveled = self._ship:asw_leveled() |
| local ship_asw, equipment_asw, depth_charge, sonar, bomber = (asw_leveled or 0), 0, false, false, false | | local ship_asw, equipment_asw, depth_charge, sonar, bomber = (asw_leveled or 0), 0, false, false, false |
Line 599: |
Line 671: |
| end | | end |
| -- some equipments' asw value is invalid | | -- some equipments' asw value is invalid |
− | if not self:_is_unable_asw_equip(equipment) then | + | if self:_is_damaging_asw_equip(equipment) then |
| equipment_asw = equipment_asw + (equipment:asw_leveled() or 0) | | equipment_asw = equipment_asw + (equipment:asw_leveled() or 0) |
| end | | end |
Line 612: |
Line 684: |
| depth_charge_sonar_boost = 1.15 | | depth_charge_sonar_boost = 1.15 |
| end | | end |
− | return depth_charge_sonar_boost * (base_asw + 1.5 * equipment_asw + 2 * math.sqrt(ship_asw)), day, night, not asw_leveled | + | return depth_charge_sonar_boost * (base_asw + 1.5 * equipment_asw + 2 * math.sqrt(ship_asw)), opening, day, night, not asw_leveled |
| end | | end |
| | | |
− | function ShipCapabilities:format_asw_attack(attack_power, day, night, uncertain) | + | function ShipCapabilities:format_asw_attack(attack_power, opening, day, night, uncertain) |
| if attack_power then | | if attack_power then |
| attack_power = math.floor(attack_power) | | attack_power = math.floor(attack_power) |
| local phases = {} | | local phases = {} |
| + | if opening then |
| + | table.insert(phases, self._asw_attack_modes.opening) |
| + | end |
| if day then | | if day then |
| table.insert(phases, self._asw_attack_modes.day) | | table.insert(phases, self._asw_attack_modes.day) |
Line 638: |
Line 713: |
| -- Basic attack power for opening airstrike (returns an array with attack values per each bomber). | | -- Basic attack power for opening airstrike (returns an array with attack values per each bomber). |
| function ShipCapabilities:opening_airstrike() | | function ShipCapabilities:opening_airstrike() |
− | if not self:_is_aviation_ship() then
| |
− | return false
| |
− | end
| |
| local airstrikes = {} | | local airstrikes = {} |
| for i = 1, self._ship:slots_length() or 0 do | | for i = 1, self._ship:slots_length() or 0 do |