OSDN Git Service

SGレーダー(初期型)の装備ボーナスを索敵スコアの計算から除く
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / Model / ShipStatus.cs
index 2694832..57ce901 100644 (file)
@@ -38,7 +38,6 @@ namespace KancolleSniffer.Model
         public int Fuel { get; set; }\r
         public int Bull { get; set; }\r
         public int[] OnSlot { get; set; }\r
-        public int NdockTime { get; set; }\r
         public int[] NdockItem { get; set; }\r
         public int LoS { get; set; }\r
         public int Firepower { get; set; }\r
@@ -52,6 +51,7 @@ namespace KancolleSniffer.Model
 \r
         public enum Attack\r
         {\r
+            // ReSharper disable once UnusedMember.Global\r
             None,\r
             Fire,\r
             Fired\r
@@ -161,81 +161,144 @@ namespace KancolleSniffer.Model
                 // ReSharper disable once CompareOfFloatsByEqualityOperator\r
                 if (Spec.IsAircraftCarrier && EffectiveFirepower == 0 && !CanOpeningAntiSubmarineAttack)\r
                     return 0;\r
-                var sonar = false;\r
-                var dct = false;\r
-                var dc = false;\r
-                var special = false;\r
-                var aircraft = false;\r
-                var all = 0.0;\r
-                foreach (var spec in Slot.Select(item => item.Spec))\r
+                var check = new AntiSubmarineChecker(Slot);\r
+                var vanilla = ShipAntiSubmarine;\r
+                if (vanilla == 0 && !check.Aircraft) // 素対潜0で航空機なしは対潜攻撃なし\r
+                    return 0;\r
+                var bonus = 1.0;\r
+                if (check.DCT && check.DC)\r
+                    bonus = 1.1;\r
+                if (check.Sonar && (check.DCT || check.DC || check.SpecialDCT))\r
+                    bonus = 1.15;\r
+                if (check.Sonar && check.DCT && check.DC)\r
+                    bonus = 1.15 * 1.25;\r
+                var levelBonus = Slot.Sum(item => item.AntiSubmarineLevelBonus);\r
+                return bonus * (Sqrt(vanilla) * 2 + check.All * 1.5 + levelBonus + (check.Aircraft ? 8 : 13));\r
+            }\r
+        }\r
+\r
+        private class AntiSubmarineChecker\r
+        {\r
+            public readonly bool Sonar;\r
+            public readonly bool DCT;\r
+            public readonly bool DC;\r
+            public readonly bool SpecialDCT;\r
+            public readonly bool Aircraft;\r
+            public readonly double All;\r
+\r
+            public AntiSubmarineChecker(IEnumerable<ItemStatus> items)\r
+            {\r
+                foreach (var spec in items.Select(item => item.Spec))\r
                 {\r
                     if (spec.IsSonar)\r
                     {\r
-                        sonar = true;\r
+                        Sonar = true;\r
                     }\r
                     else if (spec.IsDCT)\r
                     {\r
-                        dct = true;\r
+                        DCT = true;\r
                     }\r
                     else if (spec.IsDC)\r
                     {\r
-                        dc = true;\r
+                        DC = true;\r
                     }\r
                     else if (spec.IsSpecialDCT)\r
                     {\r
-                        special = true;\r
+                        SpecialDCT = true;\r
                     }\r
                     else if (spec.IsAircraft)\r
                     {\r
-                        aircraft = true;\r
+                        Aircraft = true;\r
                     }\r
-                    all += spec.EffectiveAntiSubmarine;\r
+                    All += spec.EffectiveAntiSubmarine;\r
                 }\r
-                var vanilla = ShipAntiSubmarine;\r
-                if (vanilla == 0 && !aircraft) // 素対潜0で航空機なしは対潜攻撃なし\r
-                    return 0;\r
-                var bonus = 1.0;\r
-                if (dct && dc)\r
-                    bonus = 1.1;\r
-                if (sonar && (dct || dc || special))\r
-                    bonus = 1.15;\r
-                if (sonar && dct && dc)\r
-                    bonus = 1.15 * 1.25;\r
-                var levelBonus = Slot.Sum(item => item.AntiSubmarineLevelBonus);\r
-                return bonus * (Sqrt(vanilla) * 2 + all * 1.5 + levelBonus + (aircraft ? 8 : 13));\r
             }\r
         }\r
 \r
-        public int ShipAntiSubmarine => AntiSubmarine - Slot.Sum(item => item.Spec.AntiSubmarine);\r
+        public int ShipAntiSubmarine => AntiSubmarine - Slot.Sum(item => item.Spec.AntiSubmarine + AntiSubmarineBonus(item.Spec));\r
+\r
+        private int AntiSubmarineBonus(ItemSpec spec)\r
+        {\r
+            switch (spec.Name)\r
+            {\r
+                case "四式水中聴音機":\r
+                    if (Spec.ShipClass == 54) // 秋月型\r
+                        return 1;\r
+                    if (new[] {"五十鈴改二", "那珂改二", "由良改二", "夕張改二", "夕張改二特"}.Any(name => Spec.Name == name))\r
+                        return 1;\r
+                    if (Spec.Name == "夕張改二丁")\r
+                        return 3;\r
+                    break;\r
+                case "三式水中探信儀":\r
+                    if (new[] {"神風", "春風", "時雨", "山風", "舞風", "朝霜"}.Any(Spec.Name.StartsWith))\r
+                        return 3;\r
+                    if (new[] {"潮", "雷", "山雲", "磯風", "浜風", "岸波"}.Any(Spec.Name.StartsWith))\r
+                        return 2;\r
+                    break;\r
+                case "三式爆雷投射機 集中配備":\r
+                    if (new[] {"五十鈴改二", "那珂改二", "由良改二"}.Any(name => Spec.Name == name))\r
+                        return 1;\r
+                    break;\r
+                case "試製15cm9連装対潜噴進砲":\r
+                    if (new[] {"五十鈴改二", "那珂改二", "由良改二", "夕張改二"}.Any(name => Spec.Name == name))\r
+                        return 2;\r
+                    if (Spec.Name == "夕張改二丁")\r
+                        return 3;\r
+                    break;\r
+            }\r
+            return 0;\r
+        }\r
 \r
         public bool CanOpeningAntiSubmarineAttack\r
         {\r
             get\r
             {\r
+                var specs = Slot.Select(item => item.Spec).ToArray();\r
                 switch (Name)\r
                 {\r
                     case "五十鈴改二":\r
                     case "龍田改二":\r
                     case "Jervis改":\r
+                    case "Janus改":\r
                     case "Samuel B.Roberts改":\r
+                    case "Johnston":\r
+                    case "Johnston改":\r
+                    case "Fletcher":\r
+                    case "Fletcher改":\r
                         return true;\r
                     case "大鷹改":\r
                     case "大鷹改二":\r
-                        return Slot.Any(item => item.Spec.IsAircraft && item.Spec.EffectiveAntiSubmarine > 0);\r
+                    case "神鷹改":\r
+                    case "神鷹改二":\r
+                        return specs.Any(spec => spec.IsTorpedoBomber && spec.AntiSubmarine >= 1 ||\r
+                                                 spec.IsArmyAircraft || spec.IsDiveBomber);\r
                     case "大鷹":\r
                     case "Gambier Bay":\r
                     case "Gambier Bay改":\r
                     case "瑞鳳改二乙":\r
                     case "神鷹":\r
-                    case "神鷹改":\r
-                    case "神鷹改二":\r
-                        return Slot.Any(item => item.Spec.IsAircraft && item.Spec.EffectiveAntiSubmarine >= 7) &&\r
-                               AntiSubmarine >= (HaveSonar ? 50 : 65);\r
+                        if (AntiSubmarine < 50)\r
+                            return false;\r
+                        if (AntiSubmarine >= 50 && AntiSubmarine < 100)\r
+                            return (AntiSubmarine >= 65 || HaveSonar) &&\r
+                                   specs.Any(spec => spec.IsTorpedoBomber && spec.AntiSubmarine >= 7 ||\r
+                                                     spec.IsArmyAircraft);\r
+                        return HaveSonar &&\r
+                               specs.Any(spec => spec.IsTorpedoBomber && spec.AntiSubmarine >= 1 ||\r
+                                                 spec.IsDiveBomber);\r
+                    case "瑞鳳改二":\r
+                        if (AntiSubmarine < 50)\r
+                            return false;\r
+                        return HaveSonar &&\r
+                               specs.Any(spec => spec.IsTorpedoBomber && spec.AntiSubmarine >= 7 ||\r
+                                                 spec.IsArmyAircraft);\r
                     default:\r
-                        return Spec.ShipType == 1\r
-                            ? Slot.Sum(item => item.Spec.AntiSubmarine) >= 4 && AntiSubmarine >= 75 ||\r
-                              HaveSonar && AntiSubmarine >= 60\r
-                            : HaveSonar && AntiSubmarine >= 100;\r
+                        if (HaveSonar && AntiSubmarine >= 100)\r
+                            return true;\r
+                        if (Spec.ShipType != 1)\r
+                            return false;\r
+                        return Slot.Sum(item => item.Spec.AntiSubmarine) >= 4 && AntiSubmarine >= 75 ||\r
+                               HaveSonar && AntiSubmarine >= 60;\r
                 }\r
             }\r
         }\r
@@ -264,6 +327,7 @@ namespace KancolleSniffer.Model
 \r
                 if (Slot.Any(item => item.Spec.IconType == 45 || item.Spec.IconType == 46) && // 夜戦か夜攻\r
                     (Spec.Id == 545 || // Saratoga Mk.II\r
+                     Spec.Id == 599 || // 赤城改二戊\r
                      Slot.Any(item => item.Spec.Id == 258 || item.Spec.Id == 259))) // 夜間作戦航空要員\r
                 {\r
                     return Firepower + Slot.Zip(OnSlot, (item, onSlot) =>\r
@@ -276,6 +340,7 @@ namespace KancolleSniffer.Model
                             case 242: // Swordfish\r
                             case 243: // Swordfish Mk.II(熟練)\r
                             case 244: // Swordfish Mk.III(熟練)\r
+                            case 320: // 彗星一二型(三一号光電管爆弾搭載機)\r
                                 a = 0.0;\r
                                 b = 0.3;\r
                                 break;\r
@@ -335,10 +400,26 @@ namespace KancolleSniffer.Model
 \r
         public int EffectiveAntiAirForFleet => (int)AllSlot.Sum(item => item.EffectiveAntiAirForFleet);\r
 \r
+        public double AntiAirPropellantBarrageChance\r
+        {\r
+            get\r
+            {\r
+                var launcherCount = AllSlot.Count(item => item.Spec.Id == 274);\r
+                if (launcherCount == 0)\r
+                    return 0;\r
+                var iseClass = Spec.ShipClass == 2;\r
+                var baseChance = (EffectiveAntiAirForShip + 0.9 * Lucky) / 281.0;\r
+                return (baseChance + 0.15 * (launcherCount - 1) + (iseClass ? 0.25 : 0)) * 100;\r
+            }\r
+        }\r
+\r
         public int EffectiveFuelMax => Max((int)(Spec.FuelMax * (Level >= 100 ? 0.85 : 1.0)), 1);\r
 \r
         public int EffectiveBullMax => Max((int)(Spec.BullMax * (Level >= 100 ? 0.85 : 1.0)), 1);\r
 \r
+        public int RawLoS =>\r
+            LoS - AllSlot.Sum(item => item.Spec.LoS + (Spec.HaveSgRadarBonus ? item.Spec.LoSSgRadarBonus : 0));\r
+\r
         public object Clone()\r
         {\r
             var r = (ShipStatus)MemberwiseClone();\r