2 using System.Drawing;
\r
4 using System.Windows.Forms;
\r
5 using KancolleSniffer.Model;
\r
7 namespace KancolleSniffer.View.MainWindow
\r
9 public class ShipInfoPanel : PanelWithToolTip, IUpdateTimers
\r
11 private readonly Panel _combinedFleet = new Panel
\r
13 Location = new Point(0, 0),
\r
14 Size = new Size(220, 113),
\r
18 private readonly Panel _7Ships = new Panel
\r
20 Location = new Point(0, 0),
\r
21 Size = new Size(220, 113),
\r
25 private readonly Panel _battleInfo = new Panel
\r
27 Location = new Point(59, 116),
\r
28 Size = new Size(157, 14),
\r
32 private readonly Label _presetAkashiTimer = new Label
\r
34 Location = new Point(2, 3),
\r
35 Size = new Size(32, 12),
\r
36 BackColor = CustomColors.ColumnColors.Bright
\r
39 public LinkLabel Guide { get; } = new LinkLabel
\r
42 Font = new Font("MS UI Gothic", 9.75F, FontStyle.Regular, GraphicsUnit.Point, 128),
\r
43 LinkArea = new LinkArea(0, 0),
\r
44 Location = new Point(31, 51),
\r
45 Text = "右クリックでメニューが出ます。"
\r
48 private readonly Label _enemyFighterPower = new Label
\r
50 Location = new Point(129, 1),
\r
51 Size = new Size(29, 12),
\r
52 TextAlign = ContentAlignment.MiddleRight
\r
55 private readonly Label _enemyFighterPowerCaption = new Label
\r
58 Location = new Point(90, 1),
\r
62 private readonly Label _formation = new Label
\r
64 Location = new Point(40, 1),
\r
65 Size = new Size(48, 12)
\r
68 private readonly Label _resultRank = new Label
\r
70 Location = new Point(1, 1),
\r
71 Size = new Size(42, 12),
\r
76 private readonly Label _lineOfSight = new Label
\r
78 Location = new Point(85, 117),
\r
79 Size = new Size(38, 12),
\r
81 TextAlign = ContentAlignment.MiddleRight
\r
84 private readonly Label _lineOfSightCaption = new Label
\r
87 Location = new Point(59, 117),
\r
91 private readonly Label _fighterPower = new Label
\r
93 Location = new Point(28, 117),
\r
94 Size = new Size(29, 12),
\r
96 TextAlign = ContentAlignment.MiddleRight
\r
99 private readonly Label _fighterPowerCaption = new Label
\r
102 Location = new Point(2, 117),
\r
106 private readonly Label _condTimerCaption = new Label
\r
108 Location = new Point(128, 117),
\r
109 Size = new Size(60, 12)
\r
112 private readonly Label _condTimer = new Label
\r
115 Location = new Point(186, 117)
\r
118 private readonly MainShipLabels _mainLabels = new MainShipLabels();
\r
120 public UpdateContext Context { get; set; }
\r
122 public int CurrentFleet { get; set; }
\r
124 public bool CombinedFleet { get; set; }
\r
126 public Action<int> ShowShipOnList { get; set; }
\r
128 public ShipInfoPanel()
\r
130 Controls.AddRange(new Control[] {Guide, _presetAkashiTimer, _combinedFleet, _7Ships});
\r
131 BorderStyle = BorderStyle.FixedSingle;
\r
132 _mainLabels.CreateAllShipLabels(new MainShipPanels
\r
134 PanelShipInfo = this,
\r
135 Panel7Ships = _7Ships,
\r
136 PanelCombinedFleet = _combinedFleet
\r
137 }, ShipClickHandler);
\r
138 _battleInfo.Controls.AddRange(new Control[]
\r
140 _enemyFighterPower, _enemyFighterPowerCaption, _formation, _resultRank
\r
142 Controls.AddRange(new Control[]
\r
145 _lineOfSight, _lineOfSightCaption, _fighterPower, _fighterPowerCaption, _condTimer, _condTimerCaption
\r
147 _resultRank.Click += ResultRankClick;
\r
148 Size = new Size(220, 134);
\r
151 private void ShipClickHandler(object sender, EventArgs e)
\r
153 var idx = (int)((Control)sender).Tag;
\r
154 var ship = (CombinedFleet
\r
155 ? Context.Sniffer.Fleets[0].Ships.Concat(Context.Sniffer.Fleets[1].Ships)
\r
156 : Context.Sniffer.Fleets[CurrentFleet].Ships).ElementAt(idx);
\r
158 ShowShipOnList(ship.Id);
\r
161 public void ToggleHpPercent()
\r
163 _mainLabels.ToggleHpPercent();
\r
166 public bool ShowHpInPercent => _mainLabels.ShowHpInPercent;
\r
168 private bool _inSortie;
\r
170 public void SetCurrentFleet()
\r
172 var inSortie = Context.Sniffer.InSortie;
\r
173 if (_inSortie || inSortie == -1)
\r
175 _inSortie = inSortie != -1;
\r
179 if (inSortie == 10)
\r
181 CombinedFleet = true;
\r
186 CombinedFleet = false;
\r
187 CurrentFleet = inSortie;
\r
192 private bool _prevCombined;
\r
194 private void SetCombined()
\r
196 if (Context.Sniffer.IsCombinedFleet && !_prevCombined)
\r
198 CombinedFleet = true;
\r
201 _prevCombined = Context.Sniffer.IsCombinedFleet;
\r
204 public new void Update()
\r
206 var ships = Context.Sniffer.Fleets[CurrentFleet].ActualShips;
\r
207 _7Ships.Visible = ships.Count == 7;
\r
208 _mainLabels.SetShipLabels(ships);
\r
209 ShowCombinedFleet();
\r
210 _presetAkashiTimer.Visible = Context.Config.UsePresetAkashi;
\r
211 UpdateAkashiTimer();
\r
212 UpdateFighterPower(IsCombinedFighterPower);
\r
214 UpdateCondTimers();
\r
217 private void ShowCombinedFleet()
\r
219 if (!Context.Sniffer.IsCombinedFleet)
\r
220 CombinedFleet = false;
\r
221 _combinedFleet.Visible = CombinedFleet;
\r
224 _mainLabels.SetCombinedShipLabels(Context.Sniffer.Fleets[0].ActualShips,
\r
225 Context.Sniffer.Fleets[1].ActualShips);
\r
229 private bool IsCombinedFighterPower => CombinedFleet &&
\r
230 (Context.Sniffer.Battle.BattleState == BattleState.None ||
\r
231 Context.Sniffer.Battle.EnemyIsCombined);
\r
233 private void UpdateFighterPower(bool combined)
\r
235 var fleets = Context.Sniffer.Fleets;
\r
237 ? fleets[0].FighterPower + fleets[1].FighterPower
\r
238 : fleets[CurrentFleet].FighterPower;
\r
239 _fighterPower.Text = fp.Min.ToString("D");
\r
241 ? fleets[0].ContactTriggerRate + fleets[1].ContactTriggerRate
\r
242 : fleets[CurrentFleet].ContactTriggerRate;
\r
243 var text = "制空: " + (fp.Diff ? fp.RangeString : fp.Min.ToString()) +
\r
244 $" 触接: {cr * 100:f1}";
\r
245 ToolTip.SetToolTip(_fighterPower, text);
\r
246 ToolTip.SetToolTip(_fighterPowerCaption, text);
\r
249 private void UpdateLoS()
\r
251 var fleet = Context.Sniffer.Fleets[CurrentFleet];
\r
252 _lineOfSight.Text = RoundDown(fleet.GetLineOfSights(1)).ToString("F1");
\r
253 var text = $"係数2: {RoundDown(fleet.GetLineOfSights(2)):F1}\r\n" +
\r
254 $"係数3: {RoundDown(fleet.GetLineOfSights(3)):F1}\r\n" +
\r
255 $"係数4: {RoundDown(fleet.GetLineOfSights(4)):F1}";
\r
256 ToolTip.SetToolTip(_lineOfSight, text);
\r
257 ToolTip.SetToolTip(_lineOfSightCaption, text);
\r
260 private double RoundDown(double number)
\r
262 return Math.Floor(number * 10) / 10.0;
\r
265 public void UpdateBattleInfo()
\r
268 if (Context.Sniffer.Battle.BattleState == BattleState.None)
\r
270 _battleInfo.BringToFront();
\r
271 var battle = Context.Sniffer.Battle;
\r
272 _formation.Text = new[] {"同航戦", "反航戦", "T字有利", "T字不利"}[battle.Formation[2] - 1];
\r
273 UpdateBattleFighterPower();
\r
274 if ((Context.Config.Spoilers & Spoiler.ResultRank) != 0)
\r
278 private void ResetBattleInfo()
\r
280 _formation.Text = "";
\r
281 _enemyFighterPower.Text = "";
\r
282 _fighterPower.ForeColor = DefaultForeColor;
\r
283 _fighterPowerCaption.Text = "制空";
\r
284 _resultRank.Text = "判定";
\r
285 _battleInfo.Visible = Context.Sniffer.Battle.BattleState != BattleState.None;
\r
288 private void UpdateBattleFighterPower()
\r
290 UpdateEnemyFighterPower();
\r
291 var battle = Context.Sniffer.Battle;
\r
292 _fighterPower.ForeColor = AirControlLevelColor(battle);
\r
293 _fighterPowerCaption.Text = AirControlLevelString(battle);
\r
294 if (battle.BattleState == BattleState.AirRaid)
\r
296 UpdateAirRaidFighterPower();
\r
300 UpdateFighterPower(Context.Sniffer.IsCombinedFleet && battle.EnemyIsCombined);
\r
304 private void UpdateEnemyFighterPower()
\r
306 var fp = Context.Sniffer.Battle.EnemyFighterPower;
\r
307 _enemyFighterPower.Text = fp.AirCombat + fp.UnknownMark;
\r
308 var toolTip = fp.AirCombat == fp.Interception ? "" : "防空: " + fp.Interception + fp.UnknownMark;
\r
309 ToolTip.SetToolTip(_enemyFighterPower, toolTip);
\r
310 ToolTip.SetToolTip(_enemyFighterPowerCaption, toolTip);
\r
313 private void UpdateAirRaidFighterPower()
\r
315 var fp = Context.Sniffer.Battle.FighterPower;
\r
316 _fighterPower.Text = fp.Min.ToString();
\r
317 var toolTop = fp.Diff ? fp.RangeString : "";
\r
318 ToolTip.SetToolTip(_fighterPower, toolTop);
\r
319 ToolTip.SetToolTip(_fighterPowerCaption, toolTop);
\r
322 private static Color AirControlLevelColor(BattleInfo battle)
\r
325 {DefaultForeColor, DefaultForeColor, CUDColors.Blue, CUDColors.Green, CUDColors.Orange, CUDColors.Red}[
\r
326 battle.BattleState == BattleState.Night ? 0 : battle.AirControlLevel + 1];
\r
329 private static string AirControlLevelString(BattleInfo battle)
\r
331 return new[] {"制空", "拮抗", "確保", "優勢", "劣勢", "喪失"}[
\r
332 battle.BattleState == BattleState.Night ? 0 : battle.AirControlLevel + 1];
\r
335 private void ShowResultRank()
\r
337 var result = new[] {"完全S", "勝利S", "勝利A", "勝利B", "敗北C", "敗北D", "敗北E"};
\r
338 _resultRank.Text = result[(int)Context.Sniffer.Battle.ResultRank];
\r
341 private void ResultRankClick(object sender, EventArgs e)
\r
346 private void UpdateCondTimers()
\r
351 var timer1 = Context.Sniffer.GetConditionTimer(0);
\r
352 var timer2 = Context.Sniffer.GetConditionTimer(1);
\r
353 timer = timer2 > timer1 ? timer2 : timer1;
\r
357 timer = Context.Sniffer.GetConditionTimer(CurrentFleet);
\r
359 if (timer == DateTime.MinValue)
\r
361 _condTimerCaption.Text = "";
\r
362 _condTimer.Text = "";
\r
365 var span = TimeSpan.FromSeconds(Math.Ceiling((timer - Context.GetStep().Now).TotalSeconds));
\r
366 if (span >= TimeSpan.FromMinutes(9) && Context.Config.NotifyConditions.Contains(40))
\r
368 _condTimerCaption.Text = "cond40まで";
\r
369 _condTimer.Text = (span - TimeSpan.FromMinutes(9)).ToString(@"mm\:ss");
\r
370 _condTimer.ForeColor = DefaultForeColor;
\r
374 _condTimerCaption.Text = "cond49まで";
\r
375 _condTimer.Text = (span >= TimeSpan.Zero ? span : TimeSpan.Zero).ToString(@"mm\:ss");
\r
376 _condTimer.ForeColor = span <= TimeSpan.Zero ? CUDColors.Red : DefaultForeColor;
\r
380 public Label AkashiRepairTimer { get; set; }
\r
382 public void UpdateTimers()
\r
384 UpdateAkashiTimer();
\r
385 UpdatePresetAkashiTimer();
\r
388 private void UpdateAkashiTimer()
\r
390 if (Context.Config.UsePresetAkashi)
\r
391 UpdatePresetAkashiTimer();
\r
392 _mainLabels.SetAkashiTimer(Context.Sniffer.Fleets[CurrentFleet].ActualShips,
\r
393 Context.Sniffer.AkashiTimer.GetTimers(CurrentFleet, Context.GetStep().Now));
\r
396 private void UpdatePresetAkashiTimer()
\r
398 var now = Context.GetStep().Now;
\r
399 var akashi = Context.Sniffer.AkashiTimer;
\r
400 var span = akashi.GetPresetDeckTimer(now);
\r
401 var color = span == TimeSpan.Zero && akashi.CheckPresetRepairing() ? CUDColors.Red : DefaultForeColor;
\r
402 var text = span == TimeSpan.MinValue ? "" : span.ToString(@"mm\:ss");
\r
403 AkashiRepairTimer.ForeColor = color;
\r
404 AkashiRepairTimer.Text = text;
\r
405 if (akashi.CheckPresetRepairing() && !akashi.CheckRepairing(CurrentFleet, now))
\r
407 _presetAkashiTimer.ForeColor = color;
\r
408 _presetAkashiTimer.Text = text;
\r
412 _presetAkashiTimer.ForeColor = DefaultForeColor;
\r
413 _presetAkashiTimer.Text = "";
\r