OSDN Git Service

8ed38c52101bbf40ff643108fd71ff1a3d572689
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / Model / ItemStatus.cs
1 // Copyright (C) 2018 Kazuhiro Fujieda <fujieda@users.osdn.me>\r
2 //\r
3 // Licensed under the Apache License, Version 2.0 (the "License");\r
4 // you may not use this file except in compliance with the License.\r
5 // You may obtain a copy of the License at\r
6 //\r
7 //    http://www.apache.org/licenses/LICENSE-2.0\r
8 //\r
9 // Unless required by applicable law or agreed to in writing, software\r
10 // distributed under the License is distributed on an "AS IS" BASIS,\r
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
12 // See the License for the specific language governing permissions and\r
13 // limitations under the License.\r
14 \r
15 using System;\r
16 using System.Linq;\r
17 \r
18 namespace KancolleSniffer.Model\r
19 {\r
20     public class ItemStatus\r
21     {\r
22         public int Id { get; set; }\r
23         public bool Empty => Id == -1;\r
24         public bool Unimplemented => Id == 0;\r
25         public ItemSpec Spec { get; set; } = new ItemSpec();\r
26         public int Level { get; set; }\r
27         public int Alv { get; set; }\r
28         public bool Locked { get; set; }\r
29         public ShipStatus Holder { get; set; }\r
30 \r
31         public ItemStatus()\r
32         {\r
33             Id = -1;\r
34         }\r
35 \r
36         public ItemStatus(int id)\r
37         {\r
38             Id = id;\r
39         }\r
40 \r
41         public Range CalcFighterPower(int slot)\r
42         {\r
43             if (!Spec.CanAirCombat || slot == 0)\r
44                 return new Range();\r
45             var withoutAlv = (Spec.AntiAir + FighterPowerLevelBonus) * Math.Sqrt(slot);\r
46             return new Range(withoutAlv, AlvBonus);\r
47         }\r
48 \r
49         private RangeD AlvBonus\r
50         {\r
51             get\r
52             {\r
53                 var table = AlvTypeBonusTable;\r
54                 if (table == null)\r
55                     return new RangeD();\r
56                 return _alvBonus[Alv] + table[Alv];\r
57             }\r
58         }\r
59 \r
60         public AirCorpsFighterPower.Range CalcFighterPowerInBase(int slot)\r
61         {\r
62             if (!Spec.IsAircraft || slot == 0)\r
63                 return new AirCorpsFighterPower.Range();\r
64             var withoutAlv =\r
65                 (new AirCorpsFighterPower.Pair(Spec.Interception * 1.5, Spec.AntiBomber * 2 + Spec.Interception) +\r
66                  Spec.AntiAir + FighterPowerLevelBonus) * Math.Sqrt(slot);\r
67             return new AirCorpsFighterPower.Range(withoutAlv, AlvBonusInBase);\r
68         }\r
69 \r
70         private RangeD AlvBonusInBase\r
71         {\r
72             get\r
73             {\r
74                 switch (Spec.Type)\r
75                 {\r
76                     case 9: // 艦偵\r
77                     case 10: // 水偵\r
78                     case 41: // 大艇\r
79                     case 49: // 陸偵\r
80                         return _alvBonus[Alv];\r
81                     default:\r
82                         return AlvBonus;\r
83                 }\r
84             }\r
85         }\r
86 \r
87         private readonly RangeD[] _alvBonus =\r
88             new[]\r
89             {\r
90                 new RangeD(0.0, 0.9), new RangeD(1.0, 2.4), new RangeD(2.5, 3.9), new RangeD(4.0, 5.4),\r
91                 new RangeD(5.5, 6.9), new RangeD(7.0, 8.4), new RangeD(8.5, 9.9), new RangeD(10.0, 12.0)\r
92             }.Select(range => range.Sqrt()).ToArray();\r
93 \r
94 \r
95         private int[] AlvTypeBonusTable\r
96         {\r
97             get\r
98             {\r
99                 switch (Spec.Type)\r
100                 {\r
101                     case 6: // 艦戦\r
102                     case 45: // 水戦\r
103                     case 48: // 局地戦闘機\r
104                     case 56: // 噴式戦闘機\r
105                         return new[] {0, 0, 2, 5, 9, 14, 14, 22};\r
106                     case 7: // 艦爆\r
107                     case 8: // 艦攻\r
108                     case 47: // 陸攻\r
109                     case 57: // 噴式戦闘爆撃機\r
110                     case 58: // 噴式攻撃機\r
111                         return new[] {0, 0, 0, 0, 0, 0, 0, 0};\r
112                     case 11: // 水爆\r
113                         return new[] {0, 0, 1, 1, 1, 3, 3, 6};\r
114                     default:\r
115                         return null;\r
116                 }\r
117             }\r
118         }\r
119 \r
120         private double FighterPowerLevelBonus\r
121         {\r
122             get\r
123             {\r
124                 switch (Spec.Type)\r
125                 {\r
126                     case 6: // 艦戦\r
127                     case 45: // 水戦\r
128                     case 48: // 陸戦・局戦\r
129                         return 0.2 * Level;\r
130                     case 7: // 改修可能なのは爆戦のみ\r
131                         return 0.25 * Level;\r
132                 }\r
133                 return 0;\r
134             }\r
135         }\r
136 \r
137         public double LoSLevelBonus\r
138         {\r
139             get\r
140             {\r
141                 switch (Spec.Type)\r
142                 {\r
143                     case 10: // 水偵\r
144                         return 1.2 * Math.Sqrt(Level);\r
145                     case 11: // 水爆\r
146                         return 1.15 * Math.Sqrt(Level);\r
147                     case 12: // 小型電探\r
148                         return 1.25 * Math.Sqrt(Level);\r
149                     case 13: // 大型電探\r
150                         return 1.4 * Math.Sqrt(Level);\r
151                     case 9: // 艦偵\r
152                     case 94: // 艦上偵察機(II)\r
153                         return 1.2 * Math.Sqrt(Level);\r
154                     default:\r
155                         return 0;\r
156                 }\r
157             }\r
158         }\r
159 \r
160         public double FirepowerLevelBonus\r
161         {\r
162             get\r
163             {\r
164                 switch (Spec.Type)\r
165                 {\r
166                     case 1: // 小口径\r
167                     case 2: // 中口径\r
168                     case 19: // 徹甲弾\r
169                     case 21: // 対空機銃\r
170                     case 24: // 上陸用舟艇\r
171                     case 29: // 探照灯\r
172                     case 36: // 高射装置\r
173                     case 42: // 大型探照灯\r
174                     case 46: // 特型内火艇\r
175                         return Math.Sqrt(Level);\r
176                     case 3: // 大口径\r
177                         return 1.5 * Math.Sqrt(Level);\r
178                     case 4: // 副砲\r
179                         return SecondaryGunLevelBonus;\r
180                     case 14: // ソナー\r
181                     case 15: // 爆雷\r
182                         return Spec.Id == 226 // 九五式爆雷\r
183                             ? 0\r
184                             : 0.75 * Math.Sqrt(Level);\r
185                     default:\r
186                         return 0;\r
187                 }\r
188             }\r
189         }\r
190 \r
191         private double SecondaryGunLevelBonus\r
192         {\r
193             get\r
194             {\r
195                 switch (Spec.Id)\r
196                 {\r
197                     case 10: // 12.7cm連装高角砲\r
198                     case 66: // 8cm高角砲\r
199                     case 220: // 8cm高角砲改+増設機銃\r
200                     case 275: // 10cm連装高角砲改+増設機銃\r
201                         return 0.2 * Level;\r
202                     case 12: // 15.5cm三連装副砲\r
203                     case 234: // 15.5cm三連装副砲改\r
204                     case 247: // 15.2cm三連装砲\r
205                         return 0.3 * Level;\r
206                     default:\r
207                         return Math.Sqrt(Level);\r
208                 }\r
209             }\r
210         }\r
211 \r
212         public double TorpedoLevelBonus\r
213         {\r
214             get\r
215             {\r
216                 switch (Spec.Type)\r
217                 {\r
218                     case 5: // 魚雷\r
219                     case 21: // 機銃\r
220                         return 1.2 * Math.Sqrt(Level);\r
221                     default:\r
222                         return 0;\r
223                 }\r
224             }\r
225         }\r
226 \r
227         public double AntiSubmarineLevelBonus\r
228         {\r
229             get\r
230             {\r
231                 switch (Spec.Type)\r
232                 {\r
233                     case 14:\r
234                     case 15:\r
235                         return Math.Sqrt(Level);\r
236                     default:\r
237                         return 0;\r
238                 }\r
239             }\r
240         }\r
241 \r
242         public double BomberLevelBonus => Spec.Type == 11 /* 水爆 */ ? 0.2 * Level : 0;\r
243 \r
244         public double NightBattleLevelBonus\r
245         {\r
246             get\r
247             {\r
248                 switch (Spec.Type)\r
249                 {\r
250                     case 1: // 小口径\r
251                     case 2: // 中口径\r
252                     case 3: // 大口径\r
253                     case 5: // 魚雷\r
254                     case 19: // 徹甲弾\r
255                     case 22: // 特殊潜航艇\r
256                     case 24: // 上陸用舟艇\r
257                     case 29: // 探照灯\r
258                     case 36: // 高射装置\r
259                     case 42: // 大型探照灯\r
260                     case 46: // 特型内火艇\r
261                         return Math.Sqrt(Level);\r
262                     case 4: // 副砲\r
263                         return SecondaryGunLevelBonus;\r
264                     default:\r
265                         return 0;\r
266                 }\r
267             }\r
268         }\r
269 \r
270         public double EffectiveAntiAirForShip\r
271         {\r
272             get\r
273             {\r
274                 switch (Spec.IconType)\r
275                 {\r
276                     case 15: // 機銃\r
277                         return 6 * Spec.AntiAir + 4 * Math.Sqrt(Level);\r
278                     case 16: // 高角砲\r
279                         return 4 * Spec.AntiAir + (Spec.AntiAir >= 8 ? 3 : 2) * Math.Sqrt(Level);\r
280                     case 11: // 電探\r
281                         return 3 * Spec.AntiAir;\r
282                     case 30: // 高射装置\r
283                         return 4 * Spec.AntiAir + 2 * Math.Sqrt(Level);\r
284                 }\r
285                 return 0;\r
286             }\r
287         }\r
288 \r
289         public double EffectiveAntiAirForFleet\r
290         {\r
291             get\r
292             {\r
293                 switch (Spec.IconType)\r
294                 {\r
295                     case 1:\r
296                     case 2:\r
297                     case 3: // 主砲\r
298                     case 4: // 副砲\r
299                     case 6: // 艦戦\r
300                     case 7: // 艦爆\r
301                     case 15: // 機銃\r
302                         return 0.2 * Spec.AntiAir;\r
303                     case 11: // 電探\r
304                         return 0.4 * Spec.AntiAir + 1.5 * Math.Sqrt(Level);\r
305                     case 12: // 三式弾\r
306                         return 0.6 * Spec.AntiAir;\r
307                     case 16: // 高角砲\r
308                         return 0.35 * Spec.AntiAir + (Spec.AntiAir >= 8 ? 3 : 2) * Math.Sqrt(Level);\r
309                     case 30: // 高射装置\r
310                         return 0.35 * Spec.AntiAir + 2 * Math.Sqrt(Level);\r
311                     default:\r
312                         if (Spec.Id == 9) // 46cm三連装砲\r
313                             return 0.25 * Spec.AntiAir;\r
314                         if (Spec.Type == 10) // 水偵\r
315                             return 0.2 * Spec.AntiAir;\r
316                         break;\r
317                 }\r
318                 return 0;\r
319             }\r
320         }\r
321     }\r
322 }