OSDN Git Service

戦況にツールチップで味方の装備を表示する
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / BattleResultPanel.cs
index f816e91..60740dc 100644 (file)
@@ -12,6 +12,7 @@
 // See the License for the specific language governing permissions and\r
 // limitations under the License.\r
 \r
+using System;\r
 using System.Collections.Generic;\r
 using System.Drawing;\r
 using System.Linq;\r
@@ -30,10 +31,21 @@ namespace KancolleSniffer
         private bool _hpPercent;\r
         private readonly List<ShipLabel> _hpLabels = new List<ShipLabel>();\r
         private readonly ToolTip _toolTip = new ToolTip {ShowAlways = true};\r
+        private readonly BattleInfo.BattleResult[] _result = new BattleInfo.BattleResult[2];\r
+        private Label _phaseLabel, _rankLabel;\r
+        private BattleState _prevBattleState;\r
+        private readonly BattleResultRank[] _rank = new BattleResultRank[2];\r
+        private readonly InformationPanel _infomationPanel;\r
+\r
+        public bool Spoiler { get; set; }\r
 \r
         public BattleResultPanel()\r
         {\r
+            SuspendLayout();\r
             CreateLabels();\r
+            _infomationPanel = new InformationPanel();\r
+            Controls.Add(_infomationPanel);\r
+            ResumeLayout();\r
         }\r
 \r
         public void SetShowHpPercent(bool hpPercent)\r
@@ -47,16 +59,120 @@ namespace KancolleSniffer
 \r
         public void Update(Sniffer sniffer)\r
         {\r
-            SuspendLayout();\r
-            var friend = sniffer.Battle.Result.Friend;\r
-            var enemy = sniffer.Battle.Result.Enemy;\r
+            if (_prevBattleState == BattleState.None)\r
+                _result[0] = _result[1] = null;\r
+            var state = _prevBattleState = sniffer.Battle.BattleState;\r
+            if (state != BattleState.Day && state != BattleState.Night)\r
+                return;\r
+            if (Spoiler)\r
+            {\r
+                ShowResult(sniffer.Battle.Result);\r
+                ShowResultRank(sniffer.Battle.ResultRank);\r
+                if (state == BattleState.Day)\r
+                {\r
+                    _result[0] = sniffer.Battle.Result;\r
+                    _rank[0] = sniffer.Battle.ResultRank;\r
+                    SetPhase("昼戦");\r
+                }\r
+                else if (state == BattleState.Night)\r
+                {\r
+                    _result[1] = sniffer.Battle.Result;\r
+                    _rank[1] = sniffer.Battle.ResultRank;\r
+                    SetPhase("夜戦");\r
+                }\r
+                _infomationPanel.Visible = true;\r
+            }\r
+            else\r
+            {\r
+                ClearResult();\r
+                SetPhase("結果");\r
+                if (state == BattleState.Day)\r
+                {\r
+                    _result[0] = sniffer.Battle.Result;\r
+                    _rank[0] = sniffer.Battle.ResultRank;\r
+                }\r
+                else if (state == BattleState.Night)\r
+                {\r
+                    _result[1] = sniffer.Battle.Result;\r
+                    _rank[1] = sniffer.Battle.ResultRank;\r
+                }\r
+            }\r
+            _infomationPanel.SetInformation(sniffer.Battle);\r
+        }\r
 \r
+        private void PhaseLabelClick(object sender, EventArgs ev)\r
+        {\r
+            switch (_phaseLabel.Text)\r
+            {\r
+                case "結果":\r
+                    if (_result[0] != null)\r
+                    {\r
+                        ShowResult(_result[0]);\r
+                        ShowResultRank(_rank[0]);\r
+                        SetPhase("昼戦");\r
+                    }\r
+                    else if (_result[1] != null)\r
+                    {\r
+                        ShowResult(_result[1]);\r
+                        ShowResultRank(_rank[1]);\r
+                        SetPhase("夜戦");\r
+                    }\r
+                    break;\r
+                case "昼戦":\r
+                    if (_result[1] != null)\r
+                    {\r
+                        ShowResult(_result[1]);\r
+                        ShowResultRank(_rank[1]);\r
+                        SetPhase("夜戦");\r
+                    }\r
+                    break;\r
+                case "夜戦":\r
+                    if (_result[0] != null)\r
+                    {\r
+                        ShowResult(_result[0]);\r
+                        ShowResultRank(_rank[0]);\r
+                        SetPhase("昼戦");\r
+                    }\r
+                    break;\r
+            }\r
+        }\r
+\r
+        private void SetPhase(string phase)\r
+        {\r
+            _phaseLabel.Text = phase;\r
+            if (phase == "結果" || _result[0] != null && _result[1] != null)\r
+            {\r
+                _phaseLabel.BorderStyle = BorderStyle.FixedSingle;\r
+                _phaseLabel.Cursor = Cursors.Hand;\r
+            }\r
+            else\r
+            {\r
+                _phaseLabel.BorderStyle = BorderStyle.None;\r
+                _phaseLabel.Cursor = Cursors.Default;\r
+            }\r
+        }\r
+\r
+        private void ClearResult()\r
+        {\r
+            foreach (var panel in _panelList)\r
+                panel.Visible = false;\r
+            _rankLabel.Visible = _infomationPanel.Visible = false;\r
+        }\r
+\r
+        private void ShowResult(BattleInfo.BattleResult result)\r
+        {\r
+            SuspendLayout();\r
+            var friend = result.Friend;\r
+            var enemy = result.Enemy;\r
             var fleet = new[] {"第一", "第二", "第三", "第四"};\r
             _friendLabels[0][1].Text = fleet[friend.Main[0].Fleet];\r
             for (var i = 0; i < friend.Main.Length; i++)\r
             {\r
-                _friendLabels[i + 1][0].SetHp(friend.Main[i]);\r
-                _friendLabels[i + 1][1].SetName(friend.Main[i], ShipNameWidth.BattleResult);\r
+                var labels = _friendLabels[i + 1];\r
+                var ship = friend.Main[i];\r
+                labels[0].SetHp(ship);\r
+                labels[1].SetName(ship, ShipNameWidth.BattleResult);\r
+                _toolTip.SetToolTip(labels[1], GetEqipString(ship));\r
             }\r
             if (friend.Guard.Length > 0)\r
             {\r
@@ -65,8 +181,10 @@ namespace KancolleSniffer
                 for (var i = 0; i < friend.Guard.Length; i++)\r
                 {\r
                     var labels = _friendLabels[friend.Main.Length + 2 + i];\r
-                    labels[0].SetHp(friend.Guard[i]);\r
-                    labels[1].SetName(friend.Guard[i], ShipNameWidth.BattleResult);\r
+                    var ship = friend.Guard[i];\r
+                    labels[0].SetHp(ship);\r
+                    labels[1].SetName(ship, ShipNameWidth.BattleResult);\r
+                    _toolTip.SetToolTip(labels[1], GetEqipString(ship));\r
                 }\r
             }\r
             var friendLines = 1 + friend.Main.Length + (friend.Guard.Length > 0 ? friend.Guard.Length + 1 : 0);\r
@@ -79,9 +197,10 @@ namespace KancolleSniffer
             for (var i = 0; i < enemy.Main.Length; i++)\r
             {\r
                 var labels = _enemyLabels[i + 1];\r
-                labels[0].SetHp(enemy.Main[i]);\r
-                labels[1].SetName(ShortenName(enemy.Main[i].Name));\r
-                _toolTip.SetToolTip(labels[1], string.Join("\r\n", enemy.Main[i].Slot.Select(item => item.Spec.Name)));\r
+                var ship = enemy.Main[i];\r
+                labels[0].SetHp(ship);\r
+                labels[1].SetName(ShortenName(ship.Name));\r
+                _toolTip.SetToolTip(labels[1], string.Join("\r\n", ship.Slot.Select(item => item.Spec.Name)));\r
             }\r
             if (enemy.Guard.Length > 0)\r
             {\r
@@ -90,10 +209,11 @@ namespace KancolleSniffer
                 for (var i = 0; i < enemy.Guard.Length; i++)\r
                 {\r
                     var labels = _enemyLabels[enemy.Main.Length + 2 + i];\r
-                    labels[0].SetHp(enemy.Guard[i]);\r
-                    labels[1].SetName(ShortenName(enemy.Guard[i].Name));\r
+                    var ship = enemy.Guard[i];\r
+                    labels[0].SetHp(ship);\r
+                    labels[1].SetName(ShortenName(ship.Name));\r
                     _toolTip.SetToolTip(labels[1],\r
-                        string.Join("\r\n", enemy.Guard[i].Slot.Select(item => item.Spec.Name)));\r
+                        string.Join("\r\n", ship.Slot.Select(item => item.Spec.Name)));\r
                 }\r
             }\r
             var enemyLines = 1 + enemy.Main.Length + (enemy.Guard.Length > 0 ? enemy.Guard.Length + 1 : 0);\r
@@ -103,20 +223,39 @@ namespace KancolleSniffer
                 _enemyLabels[i][1].SetName("");\r
             }\r
             var lines = Max(friendLines, enemyLines);\r
-            var labelWidth = _enemyLabels.Max(labels => labels[1].Size.Width);\r
             for (var i = 0; i < lines; i++)\r
             {\r
                 var panel = _panelList[i];\r
-                _panelList[i].Width = Max(ClientSize.Width,\r
-                    (int)Round(164 * ShipLabel.ScaleFactor.Width) + labelWidth - 1);\r
                 if (panel.Visible)\r
                     continue;\r
-                panel.Location = new Point(AutoScrollPosition.X, (int)panel.Tag + AutoScrollPosition.Y);\r
+                panel.Location = new Point(AutoScrollPosition.X,\r
+                    (int)Round((int)panel.Tag * ShipLabel.ScaleFactor.Height) + AutoScrollPosition.Y);\r
                 panel.Visible = true;\r
             }\r
             for (var i = lines; i < _panelList.Count; i++)\r
                 _panelList[i].Visible = false;\r
-            ResumeLayout();\r
+            ResumeLayout(); // スクロールバーの有無を決定する\r
+            var panelWidth = Max(ClientSize.Width, // スクロールバーの有無を反映した横幅\r
+                _enemyLabels[0][1].Location.X + _enemyLabels.Max(labels => labels[1].Size.Width) - 1); // 敵の名前の右端\r
+            for (var i = 0; i < lines; i++)\r
+                _panelList[i].Width = panelWidth;\r
+            _infomationPanel.Location = new Point(AutoScrollPosition.X, 2 + AutoScrollPosition.Y);\r
+            _infomationPanel.Visible = true;\r
+        }\r
+\r
+        private string GetEqipString(ShipStatus ship)\r
+        {\r
+            var result = new List<string>();\r
+            for (var i = 0; i < ship.Slot.Length; i++)\r
+            {\r
+                var item = ship.Slot[i];\r
+                var onslot = ship.OnSlot[i];\r
+                var max = ship.Spec.MaxEq[i];\r
+                if (item.Id == -1)\r
+                    continue;\r
+                result.Add(item.Spec.Name + (item.Spec.IsAircraft ? $" {onslot}/{max}" : ""));\r
+            }\r
+            return string.Join("\r\n", result);\r
         }\r
 \r
         private string ShortenName(string name)\r
@@ -125,12 +264,31 @@ namespace KancolleSniffer
                 match => match.Value == "(elite)" ? "(e)" : "(f)");\r
         }\r
 \r
+        private void ShowResultRank(BattleResultRank rank)\r
+        {\r
+            _rankLabel.Visible = true;\r
+            var result = new[] {"完全S", "勝利S", "勝利A", "勝利B", "敗北C", "敗北D", "敗北E"};\r
+            _rankLabel.Text = result[(int)rank];\r
+        }\r
+\r
         private void CreateLabels()\r
         {\r
-            SuspendLayout();\r
+            _phaseLabel = new Label\r
+            {\r
+                Location = new Point(78, 18),\r
+                Size = new Size(31, 14)\r
+            };\r
+            _phaseLabel.Click += PhaseLabelClick;\r
+            Controls.Add(_phaseLabel);\r
+            _rankLabel = new Label\r
+            {\r
+                Location = new Point(110, 18),\r
+                Size = new Size(42, 12)\r
+            };\r
+            Controls.Add(_rankLabel);\r
             for (var i = 0; i < 14; i++)\r
             {\r
-                var y = 1 + LineHeight * i;\r
+                var y = LineHeight * (i + 1);\r
                 var panel = new Panel\r
                 {\r
                     Location = new Point(0, y),\r
@@ -161,7 +319,114 @@ namespace KancolleSniffer
                 }\r
                 Controls.Add(panel);\r
             }\r
-            ResumeLayout();\r
+        }\r
+\r
+        private class InformationPanel : Panel\r
+        {\r
+            private readonly Label[] _formation;\r
+            private readonly Label[] _fighterPower;\r
+            private readonly ToolTip _toolTip = new ToolTip {ShowAlways = true};\r
+\r
+            public InformationPanel()\r
+            {\r
+                Visible = false;\r
+                Size = new Size(213, 12);\r
+                Controls.AddRange(_formation = new[]\r
+                {\r
+                    new Label\r
+                    {\r
+                        Location = new Point(47, 0),\r
+                        Size = new Size(29, 12)\r
+                    },\r
+                    new Label\r
+                    {\r
+                        Location = new Point(75, 0),\r
+                        Size = new Size(29, 12)\r
+                    },\r
+                    new Label\r
+                    {\r
+                        Location = new Point(0, 0),\r
+                        Size = new Size(48, 12),\r
+                        TextAlign = ContentAlignment.MiddleRight\r
+                    }\r
+                });\r
+                Controls.AddRange(_fighterPower = new[]\r
+                {\r
+                    new Label\r
+                    {\r
+                        Location = new Point(168, 0),\r
+                        Size = new Size(23, 12),\r
+                        TextAlign = ContentAlignment.MiddleRight\r
+                    },\r
+                    new Label\r
+                    {\r
+                        Location = new Point(190, 0),\r
+                        Size = new Size(23, 12),\r
+                        TextAlign = ContentAlignment.MiddleRight\r
+                    },\r
+                    new Label\r
+                    {\r
+                        Location = new Point(116, 0),\r
+                        Size = new Size(53, 12)\r
+                    }\r
+                });\r
+            }\r
+\r
+            public void SetInformation(BattleInfo battleInfo)\r
+            {\r
+                _formation[0].Text = FormationName(battleInfo.Formation[0]);\r
+                _formation[1].Text = FormationName(battleInfo.Formation[1]);\r
+                _formation[2].Text = new[] {"同航戦", "反航戦", "T字有利", "T字不利"}[battleInfo.Formation[2] - 1];\r
+\r
+                if (battleInfo.AirControlLevel == -1)\r
+                {\r
+                    if (battleInfo.BattleState == BattleState.Night)\r
+                        return;\r
+                    foreach (var label in _fighterPower)\r
+                        label.Visible = false;\r
+                    return;\r
+                }\r
+                var fp = battleInfo.FighterPower;\r
+                _fighterPower[0].Text = fp[0].ToString("D");\r
+                _toolTip.SetToolTip(_fighterPower[0], fp[0] == fp[1] ? "" : $"{fp[0]}~{fp[1]}");\r
+                var efp = battleInfo.EnemyFighterPower;\r
+                _fighterPower[1].Text = efp.AirCombat + efp.UnknownMark;\r
+                _toolTip.SetToolTip(_fighterPower[1],\r
+                    efp.AirCombat == efp.Interception ? "" : "防空:" + efp.Interception + efp.UnknownMark);\r
+                _fighterPower[2].Text =\r
+                    new[] {"", "制空均衡", "制空確保", "航空優勢", "航空劣勢", "制空喪失"}[battleInfo.AirControlLevel + 1];\r
+                foreach (var label in _fighterPower)\r
+                    label.Visible = true;\r
+            }\r
+\r
+            private string FormationName(int formation)\r
+            {\r
+                switch (formation)\r
+                {\r
+                    case 1:\r
+                        return "単縦";\r
+                    case 2:\r
+                        return "複縦";\r
+                    case 3:\r
+                        return "輪形";\r
+                    case 4:\r
+                        return "梯形";\r
+                    case 5:\r
+                        return "単横";\r
+                    case 6:\r
+                        return "警戒";\r
+                    case 11:\r
+                        return "第一";\r
+                    case 12:\r
+                        return "第二";\r
+                    case 13:\r
+                        return "第三";\r
+                    case 14:\r
+                        return "第四";\r
+                    default:\r
+                        return "";\r
+                }\r
+            }\r
         }\r
     }\r
 }
\ No newline at end of file