// You should have received a copy of the GNU General Public License\r
// along with this program; if not, see <http://www.gnu.org/licenses/>.\r
\r
+using System;\r
using System.Linq;\r
\r
namespace KancolleSniffer\r
{\r
private readonly ShipMaster _shipMaster;\r
private readonly ShipInfo _shipInfo;\r
+ private readonly ItemInfo _itemInfo;\r
public bool InBattle { get; set; }\r
public string Formation { get; private set; }\r
public int DelayInFormation { get; private set; }\r
+ public int EnemyAirSuperiority { get; private set; }\r
+ public int DelayInAirSuperiority { get; private set; }\r
\r
private struct Delay\r
{\r
- public const int Basic = 7200;\r
+ public const int Basic = 4100;\r
+ public const int Formation = 1100;\r
public const int Tau = 200;\r
public const int SearchAirSuccess = 5700;\r
public const int SearchAirFailure = 4900;\r
public const int SearchSuccess = 5400;\r
public const int Submarine = 2500;\r
+ public const int Emergence = 2000;\r
public const int AirFight = 8700;\r
public const int AirFightBoth = 2700;\r
public const int Support = 9800;\r
public const int Cutin = 4900;\r
}\r
\r
- public BattleInfo(ShipMaster shipMaster, ShipInfo shipInfo)\r
+ public BattleInfo(ShipMaster shipMaster, ShipInfo shipInfo, ItemInfo itemInfo)\r
{\r
_shipMaster = shipMaster;\r
_shipInfo = shipInfo;\r
+ _itemInfo = itemInfo;\r
}\r
\r
public void InspectBattle(dynamic json)\r
{\r
InBattle = true;\r
- var delay = Delay.Basic;\r
+ Formation = FormationName(json);\r
+ EnemyAirSuperiority = CalcEnemyAirSuperiority(json);\r
+ SetDelay(json);\r
+ }\r
+\r
+ private string FormationName(dynamic json)\r
+ {\r
switch ((int)json.api_formation[2])\r
{\r
case 1:\r
- Formation = "同航戦";\r
- break;\r
+ return "同航戦";\r
case 2:\r
- Formation = "反航戦";\r
- break;\r
+ return "反航戦";\r
case 3:\r
- Formation = "T字有利";\r
- delay += Delay.Tau;\r
- break;\r
+ return "T字有利";\r
case 4:\r
- Formation = "T字不利";\r
- delay += Delay.Tau;\r
- break;\r
+ return "T字不利";\r
}\r
+ return "";\r
+ }\r
+\r
+ private void SetDelay(dynamic json)\r
+ {\r
+ // 敵出現まで\r
+ var delay = Delay.Basic;\r
+ if ((int)json.api_formation[2] >= 3)\r
+ delay += Delay.Tau;\r
var subm = (SubmarineFlags)CheckSubmarine(json);\r
- delay += SearchDelay(json) + SupportDelay(json) + CutinDelay(json) + subm.SubmarineDelay();\r
- if (!subm.PreventOpeningAttack)\r
- delay += OpeningAttackDelay(json);\r
+ bool success;\r
+ delay += SearchDelay(json, out success) + subm.AddtionalDelay;\r
+ DelayInAirSuperiority = delay + (success ? 0 : Delay.Emergence); // 失敗すると出現が遅れる\r
+ // 敵艦隊発見以降\r
+ delay += Delay.Emergence + Delay.Formation + SupportDelay(json) + CutinDelay(json);\r
if (!subm.PreventAirFight)\r
delay += AirFightDelay(json);\r
+ if (!subm.PreventOpeningAttack)\r
+ delay += OpeningAttackDelay(json);\r
DelayInFormation = delay;\r
}\r
\r
- private int SearchDelay(dynamic json)\r
+ private int SearchDelay(dynamic json, out bool success)\r
{\r
+ success = false;\r
switch ((int)json.api_search[0])\r
{\r
case 1: // 索敵機による索敵成功\r
case 2: // 索敵機未帰還あり\r
+ success = true;\r
return Delay.SearchAirSuccess;\r
case 3: // 索敵機未帰還\r
case 4: // 索敵機による索敵失敗\r
return Delay.SearchAirFailure;\r
case 5: // 索敵力による索敵成功\r
+ success = true;\r
return Delay.SearchSuccess;\r
}\r
return 0;\r
public bool[] Friend;\r
public bool[] Enemy;\r
\r
- public int SubmarineDelay()\r
+ public int AddtionalDelay\r
{\r
- return Friend.Any(x => x) || Enemy.Any(x => x) ? Delay.Submarine : 0; // どちらかに潜水艦 \r
+ get { return Friend.Any(x => x) || Enemy.Any(x => x) ? Delay.Submarine : 0; }\r
+ // どちらかに潜水艦 \r
}\r
\r
public bool PreventAirFight\r
}\r
return false;\r
}\r
+\r
+ private int CalcEnemyAirSuperiority(dynamic json)\r
+ {\r
+ var maxEq = ((int[])json.api_ship_ke).Skip(1).SelectMany(id => _shipMaster[id].MaxEq);\r
+ var equips = ((int[][])json.api_eSlot).SelectMany(x => x);\r
+ return (from slot in equips.Zip(maxEq, (id, max) => new {id, max})\r
+ select (int)Math.Floor(_itemInfo.GetSpecByItemId(slot.id).TyKu * Math.Sqrt(slot.max))).Sum();\r
+ }\r
}\r
}
\ No newline at end of file
{\r
return _itemSpecs[_itemIds[id]];\r
}\r
+\r
+ public ItemSpec GetSpecByItemId(int id)\r
+ {\r
+ return _itemSpecs[id];\r
+ }\r
}\r
}
\ No newline at end of file
this.labelNumOfShips = new System.Windows.Forms.Label();\r
this.label1 = new System.Windows.Forms.Label();\r
this.panelFleet1 = new System.Windows.Forms.Panel();\r
+ this.panelBattleInfo = new System.Windows.Forms.Panel();\r
+ this.labelEnemyAirSuperiority = new System.Windows.Forms.Label();\r
+ this.label30 = new System.Windows.Forms.Label();\r
+ this.labelFormation = new System.Windows.Forms.Label();\r
+ this.label29 = new System.Windows.Forms.Label();\r
this.label19 = new System.Windows.Forms.Label();\r
this.labelAkashiTimer = new System.Windows.Forms.Label();\r
this.labelAirSuperiority = new System.Windows.Forms.Label();\r
this.labelFleet3 = new System.Windows.Forms.Label();\r
this.labelCheckFleet2 = new System.Windows.Forms.Label();\r
this.labelFleet2 = new System.Windows.Forms.Label();\r
- this.panelBattleInfo = new System.Windows.Forms.Panel();\r
- this.label29 = new System.Windows.Forms.Label();\r
- this.labelFormation = new System.Windows.Forms.Label();\r
this.panelHeadquarters.SuspendLayout();\r
this.panelFleet1.SuspendLayout();\r
+ this.panelBattleInfo.SuspendLayout();\r
this.panelDock.SuspendLayout();\r
this.panel1.SuspendLayout();\r
this.panel2.SuspendLayout();\r
this.panel3.SuspendLayout();\r
this.contextMenuStripToolTip.SuspendLayout();\r
this.panel4.SuspendLayout();\r
- this.panelBattleInfo.SuspendLayout();\r
this.SuspendLayout();\r
// \r
// panelHeadquarters\r
this.panelFleet1.Size = new System.Drawing.Size(245, 136);\r
this.panelFleet1.TabIndex = 2;\r
// \r
+ // panelBattleInfo\r
+ // \r
+ this.panelBattleInfo.Controls.Add(this.labelEnemyAirSuperiority);\r
+ this.panelBattleInfo.Controls.Add(this.label30);\r
+ this.panelBattleInfo.Controls.Add(this.labelFormation);\r
+ this.panelBattleInfo.Controls.Add(this.label29);\r
+ this.panelBattleInfo.Location = new System.Drawing.Point(66, 119);\r
+ this.panelBattleInfo.Name = "panelBattleInfo";\r
+ this.panelBattleInfo.Size = new System.Drawing.Size(175, 12);\r
+ this.panelBattleInfo.TabIndex = 40;\r
+ this.panelBattleInfo.Visible = false;\r
+ // \r
+ // labelEnemyAirSuperiority\r
+ // \r
+ this.labelEnemyAirSuperiority.Location = new System.Drawing.Point(141, 0);\r
+ this.labelEnemyAirSuperiority.Name = "labelEnemyAirSuperiority";\r
+ this.labelEnemyAirSuperiority.Size = new System.Drawing.Size(23, 12);\r
+ this.labelEnemyAirSuperiority.TabIndex = 3;\r
+ this.labelEnemyAirSuperiority.TextAlign = System.Drawing.ContentAlignment.MiddleRight;\r
+ // \r
+ // label30\r
+ // \r
+ this.label30.AutoSize = true;\r
+ this.label30.Location = new System.Drawing.Point(99, 0);\r
+ this.label30.Name = "label30";\r
+ this.label30.Size = new System.Drawing.Size(41, 12);\r
+ this.label30.TabIndex = 2;\r
+ this.label30.Text = "敵制空";\r
+ // \r
+ // labelFormation\r
+ // \r
+ this.labelFormation.Location = new System.Drawing.Point(44, 0);\r
+ this.labelFormation.Name = "labelFormation";\r
+ this.labelFormation.Size = new System.Drawing.Size(48, 12);\r
+ this.labelFormation.TabIndex = 1;\r
+ // \r
+ // label29\r
+ // \r
+ this.label29.AutoSize = true;\r
+ this.label29.Location = new System.Drawing.Point(1, 0);\r
+ this.label29.Name = "label29";\r
+ this.label29.Size = new System.Drawing.Size(41, 12);\r
+ this.label29.TabIndex = 0;\r
+ this.label29.Text = "交戦形";\r
+ // \r
// label19\r
// \r
this.label19.AutoSize = true;\r
this.labelFleet2.Text = "第二艦隊";\r
this.labelFleet2.Click += new System.EventHandler(this.labelFleet_Click);\r
// \r
- // panelBattleInfo\r
- // \r
- this.panelBattleInfo.Controls.Add(this.labelFormation);\r
- this.panelBattleInfo.Controls.Add(this.label29);\r
- this.panelBattleInfo.Location = new System.Drawing.Point(66, 119);\r
- this.panelBattleInfo.Name = "panelBattleInfo";\r
- this.panelBattleInfo.Size = new System.Drawing.Size(175, 12);\r
- this.panelBattleInfo.TabIndex = 40;\r
- this.panelBattleInfo.Visible = false;\r
- // \r
- // label29\r
- // \r
- this.label29.AutoSize = true;\r
- this.label29.Location = new System.Drawing.Point(1, 0);\r
- this.label29.Name = "label29";\r
- this.label29.Size = new System.Drawing.Size(41, 12);\r
- this.label29.TabIndex = 0;\r
- this.label29.Text = "戦闘中";\r
- // \r
- // labelFormation\r
- // \r
- this.labelFormation.Location = new System.Drawing.Point(44, 0);\r
- this.labelFormation.Name = "labelFormation";\r
- this.labelFormation.Size = new System.Drawing.Size(48, 12);\r
- this.labelFormation.TabIndex = 1;\r
- // \r
// MainForm\r
// \r
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);\r
this.panelHeadquarters.PerformLayout();\r
this.panelFleet1.ResumeLayout(false);\r
this.panelFleet1.PerformLayout();\r
+ this.panelBattleInfo.ResumeLayout(false);\r
+ this.panelBattleInfo.PerformLayout();\r
this.panelDock.ResumeLayout(false);\r
this.panelDock.PerformLayout();\r
this.panel1.ResumeLayout(false);\r
this.contextMenuStripToolTip.ResumeLayout(false);\r
this.panel4.ResumeLayout(false);\r
this.panel4.PerformLayout();\r
- this.panelBattleInfo.ResumeLayout(false);\r
- this.panelBattleInfo.PerformLayout();\r
this.ResumeLayout(false);\r
this.PerformLayout();\r
\r
private System.Windows.Forms.Panel panelBattleInfo;\r
private System.Windows.Forms.Label labelFormation;\r
private System.Windows.Forms.Label label29;\r
+ private System.Windows.Forms.Label labelEnemyAirSuperiority;\r
+ private System.Windows.Forms.Label label30;\r
}\r
}\r
\r
Application.Exit();\r
}\r
\r
-\r
private void ConfigToolStripMenuItem_Click(object sender, EventArgs e)\r
{\r
if (_configDialog.ShowDialog(this) == DialogResult.OK)\r
private void UpdateBattleInfo()\r
{\r
labelFormation.Text = "";\r
+ labelEnemyAirSuperiority.Text = "";\r
panelBattleInfo.Visible = _sniffer.Battle.InBattle;\r
if (!_sniffer.Battle.InBattle)\r
return;\r
- var timer = new Timer {Interval = _sniffer.Battle.DelayInFormation};\r
- timer.Tick += (sender, args) =>\r
+ var tf = new Timer {Interval = _sniffer.Battle.DelayInFormation};\r
+ tf.Tick += (sender, args) =>\r
{\r
labelFormation.Text = _sniffer.Battle.Formation;\r
- timer.Stop();\r
+ tf.Stop();\r
+ };\r
+ tf.Start();\r
+ var ta = new Timer {Interval = _sniffer.Battle.DelayInAirSuperiority};\r
+ ta.Tick += (sender, args) =>\r
+ {\r
+ labelEnemyAirSuperiority.Text = _sniffer.Battle.EnemyAirSuperiority.ToString("D");\r
+ ta.Stop();\r
};\r
- timer.Start();\r
+ ta.Start();\r
}\r
\r
private void UpdateChargeInfo()\r
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w\r
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0\r
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAQ\r
- CwAAAk1TRnQBSQFMAgEBBQEAASgBAAEoAQABDgEAAQ8BAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo\r
+ CwAAAk1TRnQBSQFMAgEBBQEAATgBAAE4AQABDgEAAQ8BAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo\r
AwABOAMAAR4DAAEBAQABCAUAAZABBhgAAYACAAGAAwACgAEAAYADAAGAAQABgAEAAoACAAPAAQABwAHc\r
AcABAAHwAcoBpgEAATMFAAEzAQABMwEAATMBAAIzAgADFgEAAxwBAAMiAQADKQEAA1UBAANNAQADQgEA\r
AzkBAAGAAXwB/wEAAlAB/wEAAZMBAAHWAQAB/wHsAcwBAAHGAdYB7wEAAdYC5wEAAZABqQGtAgAB/wEz\r
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w\r
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0\r
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAA0\r
- CwAAAk1TRnQBSQFMAgEBBQEAASgBAAEoAQABDgEAAQ4BAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo\r
+ CwAAAk1TRnQBSQFMAgEBBQEAATgBAAE4AQABDgEAAQ4BAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo\r
AwABOAMAARwDAAEBAQABCAUAASABBhgAAYACAAGAAwACgAEAAYADAAGAAQABgAEAAoACAAPAAQABwAHc\r
AcABAAHwAcoBpgEAATMFAAEzAQABMwEAATMBAAIzAgADFgEAAxwBAAMiAQADKQEAA1UBAANNAQADQgEA\r
AzkBAAGAAXwB/wEAAlAB/wEAAZMBAAHWAQAB/wHsAcwBAAHGAdYB7wEAAdYC5wEAAZABqQGtAgAB/wEz\r
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w\r
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0\r
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABm\r
- BwAAAk1TRnQBSQFMAwEBAAFgAQABYAEAAQcBAAEPAQAE/wEJAQAI/wFCAU0BNgEEBgABNgEEAgABKAMA\r
+ BwAAAk1TRnQBSQFMAwEBAAFwAQABcAEAAQcBAAEPAQAE/wEJAQAI/wFCAU0BNgEEBgABNgEEAgABKAMA\r
ARwDAAEPAwABAQEAAQgFAAGkAQEYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA\r
AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5\r
AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA\r
{\r
public class ShipMaster\r
{\r
+ public const int NumSlots = 5;\r
private readonly Dictionary<int, ShipSpec> _shipSpecs = new Dictionary<int, ShipSpec>();\r
\r
public void Inspect(dynamic json)\r
Name = entry.api_name,\r
FuelMax = (int)entry.api_fuel_max,\r
BullMax = (int)entry.api_bull_max,\r
+ MaxEq = (int[])entry.api_maxeq,\r
ShipType = (int)entry.api_stype,\r
};\r
}\r
- _shipSpecs[-1] = new ShipSpec {Name = "不明"};\r
+ _shipSpecs[-1] = new ShipSpec {Name = "不明", MaxEq = new int[NumSlots]};\r
}\r
\r
public ShipSpec this[int id]\r
public string Name { get; set; }\r
public int FuelMax { get; set; }\r
public int BullMax { get; set; }\r
+ public int[] MaxEq { get; set; }\r
public int ShipType { get; set; }\r
\r
public bool IsSubmarine\r
_shipInfo = new ShipInfo(_shipMaster, _itemInfo);\r
_dockInfo = new DockInfo(_shipInfo);\r
_akashiTimer = new AkashiTimer(_shipInfo, _itemInfo, _dockInfo, _missionInfo);\r
- _battleInfo = new BattleInfo(_shipMaster, _shipInfo);\r
+ _battleInfo = new BattleInfo(_shipMaster, _shipInfo, _itemInfo);\r
}\r
\r
public void SaveState()\r