public override void LoadFromResponse( string apiname, dynamic data ) { switch ( apiname ) { case "api_req_combined_battle/goback_port": foreach ( int index in KCDatabase.Instance.Battle.Result.EscapingShipIndex ) { Fleets[( index - 1 ) < 6 ? 1 : 2].Escape( ( index - 1 ) % 6 ); } break; case "api_get_member/ndock": foreach ( var fleet in Fleets.Values ) { fleet.LoadFromResponse( apiname, data ); } break; case "api_req_hensei/preset_select": { int id = (int)data.api_id; if ( !Fleets.ContainsKey( id ) ) { var a = new FleetData(); a.LoadFromResponse( apiname, data ); Fleets.Add( a ); } else { Fleets[id].LoadFromResponse( apiname, data ); } } break; default: base.LoadFromResponse( apiname, (object)data ); //api_port/port, api_get_member/deck foreach ( var elem in data ) { int id = (int)elem.api_id; if ( !Fleets.ContainsKey( id ) ) { var a = new FleetData(); a.LoadFromResponse( apiname, elem ); Fleets.Add( a ); } else { Fleets[id].LoadFromResponse( apiname, elem ); } } break; } // 泊地修理の処理 if ( apiname == "api_port/port" ) { if ( ( DateTime.Now - AnchorageRepairingTimer ).TotalMinutes >= 20 ) StartAnchorageRepairingTimer(); } }
/// <summary> /// 艦隊の状態の情報をラベルに適用します。 /// </summary> /// <param name="fleet">艦隊データ。</param> /// <param name="label">適用するラベル。</param> /// <param name="tooltip">適用するツールチップ。</param> /// <param name="prevstate">前回の状態。</param> /// <param name="timer">日時。</param> /// <returns>艦隊の状態を表す定数。</returns> public static FleetStates UpdateFleetState( FleetData fleet, ImageLabel label, ToolTip tooltip, FleetStates prevstate, ref DateTime timer ) { KCDatabase db = KCDatabase.Instance; //初期化 tooltip.SetToolTip( label, null ); label.BackColor = Color.Transparent; //所属艦なし if ( fleet == null || fleet.Members.Count( id => id != -1 ) == 0 ) { label.Text = FleetRes.NoShips; label.ImageIndex = (int)ResourceManager.IconContent.FleetNoShip; return FleetStates.NoShip; } { //入渠中 long ntime = db.Docks.Values.Max( dock => { if ( dock.State == 1 && fleet.Members.Count( ( id => id == dock.ShipID ) ) > 0 ) return dock.CompletionTime.Ticks; else return 0; } ); if ( ntime > 0 ) { //入渠中 timer = new DateTime( ntime ); label.Text = FleetRes.Docking + DateTimeHelper.ToTimeRemainString( timer ); label.ImageIndex = (int)ResourceManager.IconContent.FleetDocking; tooltip.SetToolTip( label, FleetRes.CompletionTime + DateTimeHelper.TimeToCSVString( timer ) ); return FleetStates.Docking; } } if ( fleet.IsInSortie ) { //大破出撃中 if ( fleet.MembersInstance.Count( s => ( s != null && !fleet.EscapedShipList.Contains( s.MasterID ) && (double)s.HPCurrent / s.HPMax <= 0.25 ) ) > 0 ) { label.Text = FleetRes.CriticalDamageAdvance; label.ImageIndex = (int)ResourceManager.IconContent.FleetSortieDamaged; return FleetStates.SortieDamaged; } else { //出撃中 label.Text = FleetRes.OnSortie; label.ImageIndex = (int)ResourceManager.IconContent.FleetSortie; return FleetStates.Sortie; } } //遠征中 if ( fleet.ExpeditionState != 0 ) { timer = fleet.ExpeditionTime; label.Text = FleetRes.OnExped + DateTimeHelper.ToTimeRemainString( timer ); label.ImageIndex = (int)ResourceManager.IconContent.FleetExpedition; tooltip.SetToolTip( label, string.Format( "{0} : {1}\r\n" + FleetRes.CompletionTime + " {2}", KCDatabase.Instance.Mission[fleet.ExpeditionDestination].ID, KCDatabase.Instance.Mission[fleet.ExpeditionDestination].Name, DateTimeHelper.TimeToCSVString( timer ) ) ); return FleetStates.Expedition; } //大破艦あり if ( fleet.MembersInstance.Count( s => ( s != null && !fleet.EscapedShipList.Contains( s.MasterID ) && (double)s.HPCurrent / s.HPMax <= 0.25 ) ) > 0 ) { label.Text = FleetRes.CriticallyDamagedShip; label.ImageIndex = (int)ResourceManager.IconContent.FleetDamaged; //label.BackColor = Color.LightCoral; return FleetStates.Damaged; } //泊地修理中 { if ( fleet.CanAnchorageRepairing && fleet.MembersInstance.Take( 2 + KCDatabase.Instance.Ships[fleet[0]].SlotInstanceMaster.Count( eq => eq != null && eq.CategoryType == 31 ) ) .Any( s => s != null && s.HPRate < 1.0 && s.HPRate > 0.5 && s.RepairingDockID == -1 ) ) { label.Text = FleetRes.AnchorageRepairing + DateTimeHelper.ToTimeElapsedString( KCDatabase.Instance.Fleet.AnchorageRepairingTimer ); label.ImageIndex = (int)ResourceManager.IconContent.FleetAnchorageRepairing; StringBuilder sb = new StringBuilder(); sb.AppendFormat( FleetRes.StartTime, DateTimeHelper.TimeToCSVString( KCDatabase.Instance.Fleet.AnchorageRepairingTimer ) ); for ( int i = 0; i < fleet.Members.Count; i++ ) { var ship = fleet.MembersInstance[i]; if ( ship != null && ship.HPRate < 1.0 ) { var totaltime = DateTimeHelper.FromAPITimeSpan( ship.RepairTime ); var unittime = Calculator.CalculateDockingUnitTime( ship ); sb.AppendFormat( "#{0} : {1:00}:{2:00}:{3:00} @ {4:00}:{5:00}:{6:00} x -{7} HP\r\n", i + 1, (int)totaltime.TotalHours, totaltime.Minutes, totaltime.Seconds, (int)unittime.TotalHours, unittime.Minutes, unittime.Seconds, ship.HPMax - ship.HPCurrent ); } else { sb.Append( "#" ).Append( i + 1 ).Append( " : ----\r\n" ); } } tooltip.SetToolTip( label, sb.ToString() ); return FleetStates.AnchorageRepairing; } } //未補給 { int fuel = fleet.MembersInstance.Sum( ship => ship == null ? 0 : (int)( ( ship.FuelMax - ship.Fuel ) * ( ship.IsMarried ? 0.85 : 1.00 ) ) ); int ammo = fleet.MembersInstance.Sum( ship => ship == null ? 0 : (int)( ( ship.AmmoMax - ship.Ammo ) * ( ship.IsMarried ? 0.85 : 1.00 ) ) ); int aircraft = fleet.MembersInstance.Sum( ship => { if ( ship == null ) return 0; else { int c = 0; for ( int i = 0; i < ship.Slot.Count; i++ ) { c += ship.MasterShip.Aircraft[i] - ship.Aircraft[i]; } return c; } } ); int bauxite = aircraft * 5; if ( fuel > 0 || ammo > 0 || bauxite > 0 ) { label.Text = FleetRes.SupplyNeeded; label.ImageIndex = (int)ResourceManager.IconContent.FleetNotReplenished; tooltip.SetToolTip( label, string.Format( FleetRes.ResupplyTooltip, fuel, ammo, bauxite, aircraft ) ); return FleetStates.NotReplenished; } } //疲労 { int cond = fleet.MembersInstance.Min( s => s == null ? 100 : s.Condition ); if ( cond < Configuration.Config.Control.ConditionBorder && fleet.ConditionTime != null ) { timer = (DateTime)fleet.ConditionTime; label.Text = FleetRes.Fatigued + DateTimeHelper.ToTimeRemainString( timer ); if ( cond < 20 ) label.ImageIndex = (int)ResourceManager.IconContent.ConditionVeryTired; else if ( cond < 30 ) label.ImageIndex = (int)ResourceManager.IconContent.ConditionTired; else label.ImageIndex = (int)ResourceManager.IconContent.ConditionLittleTired; tooltip.SetToolTip( label, string.Format( FleetRes.EstimatedRecoveryTime + ": {0}", DateTimeHelper.TimeToCSVString( timer ) ) ); return FleetStates.Tired; } else if ( cond >= 50 ) { //戦意高揚 label.Text = FleetRes.FightingSpiritHigh; label.ImageIndex = (int)ResourceManager.IconContent.ConditionSparkle; tooltip.SetToolTip( label, string.Format( FleetRes.SparkledTooltip, cond, Math.Ceiling( ( cond - 49 ) / 3.0 ) ) ); return FleetStates.Sparkled; } } //出撃可能! { label.Text = FleetRes.ReadyToSortie; label.ImageIndex = (int)ResourceManager.IconContent.FleetReady; return FleetStates.Ready; } }
/// <summary> /// 索敵能力を求めます。「2-5式」です。 /// </summary> /// <param name="fleet">対象の艦隊。</param> public static int GetSearchingAbility_Old( FleetData fleet ) { KCDatabase db = KCDatabase.Instance; int los_reconplane = 0; int los_radar = 0; int los_other = 0; foreach ( var ship in fleet.MembersWithoutEscaped ) { if ( ship == null ) continue; los_other += ship.LOSBase; var slot = ship.SlotInstanceMaster; for ( int j = 0; j < slot.Count; j++ ) { if ( slot[j] == null ) continue; switch ( slot[j].EquipmentType[2] ) { case 9: //艦偵 case 10: //水偵 case 11: //水爆 if ( ship.Aircraft[j] > 0 ) los_reconplane += slot[j].LOS * 2; break; case 12: //小型電探 case 13: //大型電探 los_radar += slot[j].LOS; break; default: los_other += slot[j].LOS; break; } } } return (int)Math.Sqrt( los_other ) + los_radar + los_reconplane; }
/// <summary> /// 制空戦力を求めます。 /// </summary> /// <param name="fleet">対象の艦隊。</param> public static int GetAirSuperiority( FleetData fleet ) { return fleet.MembersWithoutEscaped.Select( ship => GetAirSuperiority( ship ) ).Sum(); }
public override void LoadFromResponse(string apiname, dynamic data) { switch (apiname) { case "api_req_sortie/goback_port": case "api_req_combined_battle/goback_port": { var battle = KCDatabase.Instance.Battle; foreach (int ii in battle.Result.EscapingShipIndex) { int index = ii - 1; if (index < battle.FirstBattle.Initial.FriendFleet.Members.Count) { battle.FirstBattle.Initial.FriendFleet.Escape(index); } else { battle.FirstBattle.Initial.FriendFleetEscort.Escape(index - 6); } } } break; case "api_get_member/ndock": foreach (var fleet in Fleets.Values) { fleet.LoadFromResponse(apiname, data); } break; case "api_req_hensei/preset_select": { int id = (int)data.api_id; if (!Fleets.ContainsKey(id)) { var a = new FleetData(); a.LoadFromResponse(apiname, data); Fleets.Add(a); } else { Fleets[id].LoadFromResponse(apiname, data); } } break; default: base.LoadFromResponse(apiname, (object)data); //api_port/port, api_get_member/deck foreach (var elem in data) { int id = (int)elem.api_id; if (!Fleets.ContainsKey(id)) { var a = new FleetData(); a.LoadFromResponse(apiname, elem); Fleets.Add(a); } else { Fleets[id].LoadFromResponse(apiname, elem); } } break; } // 泊地修理・コンディションの処理 if (apiname == "api_port/port") { if ((DateTime.Now - AnchorageRepairingTimer).TotalMinutes >= 20) { StartAnchorageRepairingTimer(); } else { CheckAnchorageRepairingHealing(); } UpdateConditionPrediction(); } }
public MissionClearConditionResult(FleetData targetFleet) { this.targetFleet = targetFleet; IsSuceeded = true; failureReason = new List <string>(); }
public void Update( FleetData fleet ) { KCDatabase db = KCDatabase.Instance; if ( fleet == null ) return; Name.Text = fleet.Name; { int levelSum = fleet.MembersInstance.Sum( s => s != null ? s.Level : 0 ); int fueltotal = fleet.MembersInstance.Sum( s => s == null ? 0 : (int)Math.Floor( s.FuelMax * ( s.IsMarried ? 0.85 : 1.00 ) ) ); int ammototal = fleet.MembersInstance.Sum( s => s == null ? 0 : (int)Math.Floor( s.AmmoMax * ( s.IsMarried ? 0.85 : 1.00 ) ) ); int fuelunit = fleet.MembersInstance.Sum( s => s == null ? 0 : (int)Math.Floor( s.MasterShip.Fuel * 0.2 * ( s.IsMarried ? 0.85 : 1.00 ) ) ); int ammounit = fleet.MembersInstance.Sum( s => s == null ? 0 : (int)Math.Floor( s.MasterShip.Ammo * 0.2 * ( s.IsMarried ? 0.85 : 1.00 ) ) ); int speed = fleet.MembersWithoutEscaped.Min( s => s == null ? 10 : s.MasterShip.Speed ); ToolTipInfo.SetToolTip( Name, string.Format( "Lv合計: {0} / 平均: {1:0.00}\r\n{2}艦隊\r\nドラム缶搭載: {3}個 ({4}艦)\r\n大発動艇搭載: {5}個\r\n総積載: 燃 {6} / 弾 {7}\r\n(1戦当たり 燃 {8} / 弾 {9})", levelSum, (double)levelSum / Math.Max( fleet.Members.Count( id => id != -1 ), 1 ), Constants.GetSpeed( speed ), fleet.MembersInstance.Sum( s => s == null ? 0 : s.SlotInstanceMaster.Count( q => q == null ? false : q.CategoryType == 30 ) ), fleet.MembersInstance.Count( s => s == null ? false : s.SlotInstanceMaster.Count( q => q == null ? false : q.CategoryType == 30 ) > 0 ), fleet.MembersInstance.Sum( s => s == null ? 0 : s.SlotInstanceMaster.Count( q => q == null ? false : q.CategoryType == 24 ) ), fueltotal, ammototal, fuelunit, ammounit ) ); } State = FleetData.UpdateFleetState( fleet, StateMain, ToolTipInfo, State, ref Timer ); //制空戦力計算 { int airSuperiority = fleet.GetAirSuperiority(); AirSuperiority.Text = airSuperiority.ToString(); ToolTipInfo.SetToolTip( AirSuperiority, string.Format( "確保: {0}\r\n優勢: {1}\r\n均衡: {2}\r\n劣勢: {3}\r\n", (int)( airSuperiority / 3.0 ), (int)( airSuperiority / 1.5 ), (int)( airSuperiority * 1.5 - 1 ), (int)( airSuperiority * 3.0 - 1 ) ) ); } //索敵能力計算 SearchingAbility.Text = fleet.GetSearchingAbilityString(); ToolTipInfo.SetToolTip( SearchingAbility, string.Format( "(旧)2-5式: {0}\r\n2-5式(秋): {1}\r\n2-5新秋簡易式: {2}\r\n", fleet.GetSearchingAbilityString( 0 ), fleet.GetSearchingAbilityString( 1 ), fleet.GetSearchingAbilityString( 2 ) ) ); }
/// <summary> /// 索敵能力を求めます。「判定式(33)」です。 /// </summary> /// <param name="fleet">対象の艦隊。</param> public static double GetSearchingAbility_33( FleetData fleet ) { double ret = 0.0; foreach ( var ship in fleet.MembersWithoutEscaped ) { if ( ship == null ) continue; //equipments foreach ( var slot in ship.SlotInstance ) { if ( slot == null ) continue; switch ( slot.MasterEquipment.CategoryType ) { case 8: //艦上攻撃機 ret += 0.8 * slot.MasterEquipment.LOS; break; case 9: //艦上偵察機 case 94: //艦上偵察機(II) 存在しないが念のため ret += 1.0 * slot.MasterEquipment.LOS; break; case 10: //水上偵察機 ret += 1.2 * ( slot.MasterEquipment.LOS + 1.2 * Math.Sqrt( slot.Level ) ); break; case 11: //水上爆撃機 ret += 1.1 * slot.MasterEquipment.LOS; break; case 12: //小型電探 case 13: //大型電探 ret += 0.6 * ( slot.MasterEquipment.LOS + 1.25 * Math.Sqrt( slot.Level ) ); break; default: ret += 0.6 * slot.MasterEquipment.LOS; break; } } ret += Math.Sqrt( ship.LOSBase ); } ret -= Math.Ceiling( 0.4 * KCDatabase.Instance.Admiral.Level ); ret += 2.0 * ( 6 - fleet.MembersWithoutEscaped.Count( s => s != null ) ); return ret; }
private string[] GetDamagedShips( FleetData fleet, int[] hps ) { LinkedList<string> list = new LinkedList<string>(); for ( int i = 0; i < fleet.Members.Count; i++ ) { if ( i == 0 && !ContainsFlagship ) continue; ShipData s = fleet.MembersInstance[i]; if ( s != null && !fleet.EscapedShipList.Contains( s.MasterID ) && IsShipDamaged( s, hps[i] ) ) { list.AddLast( string.Format( "{0} ({1}/{2})", s.NameWithLevel, hps[i], s.HPMax ) ); } } return list.ToArray(); }
public void Update( FleetData fleet ) { KCDatabase db = KCDatabase.Instance; if ( fleet == null ) return; Name.Text = fleet.Name; { int levelSum = fleet.MembersInstance.Sum( s => s != null ? s.Level : 0 ); int fueltotal = fleet.MembersInstance.Sum( s => s == null ? 0 : (int)Math.Floor( s.FuelMax * ( s.IsMarried ? 0.85 : 1.00 ) ) ); int ammototal = fleet.MembersInstance.Sum( s => s == null ? 0 : (int)Math.Floor( s.AmmoMax * ( s.IsMarried ? 0.85 : 1.00 ) ) ); int fuelunit = fleet.MembersInstance.Sum( s => s == null ? 0 : (int)Math.Floor( s.MasterShip.Fuel * 0.2 * ( s.IsMarried ? 0.85 : 1.00 ) ) ); int ammounit = fleet.MembersInstance.Sum( s => s == null ? 0 : (int)Math.Floor( s.MasterShip.Ammo * 0.2 * ( s.IsMarried ? 0.85 : 1.00 ) ) ); int speed = fleet.MembersWithoutEscaped.Min( s => s == null ? 10 : s.MasterShip.Speed ); ToolTipInfo.SetToolTip( Name, string.Format( "Lv合計: {0} / 平均: {1:0.00}\r\n{2}艦隊\r\nドラム缶搭載: {3}個 ({4}艦)\r\n大発動艇搭載: {5}個\r\n総積載: 燃 {6} / 弾 {7}\r\n(1戦当たり 燃 {8} / 弾 {9})", levelSum, (double)levelSum / Math.Max( fleet.Members.Count( id => id != -1 ), 1 ), Constants.GetSpeed( speed ), fleet.MembersInstance.Sum( s => s == null ? 0 : s.SlotInstanceMaster.Count( q => q == null ? false : q.CategoryType == 30 ) ), fleet.MembersInstance.Count( s => s == null ? false : s.SlotInstanceMaster.Count( q => q == null ? false : q.CategoryType == 30 ) > 0 ), fleet.MembersInstance.Sum( s => s == null ? 0 : s.SlotInstanceMaster.Count( q => q == null ? false : q.CategoryType == 24 ) ), fueltotal, ammototal, fuelunit, ammounit ) ); } State = FleetData.UpdateFleetState( fleet, StateMain, ToolTipInfo, State, ref Timer ); //制空戦力計算 { int airSuperiority = fleet.GetAirSuperiority(); AirSuperiority.Text = airSuperiority.ToString(); ToolTipInfo.SetToolTip( AirSuperiority, string.Format( "確保: {0}\r\n優勢: {1}\r\n均衡: {2}\r\n劣勢: {3}\r\n", (int)( airSuperiority / 3.0 ), (int)( airSuperiority / 1.5 ), (int)( airSuperiority * 1.5 - 1 ), (int)( airSuperiority * 3.0 - 1 ) ) ); } //索敵能力計算 SearchingAbility.Text = fleet.GetSearchingAbilityString(); { StringBuilder sb = new StringBuilder(); double probStart = fleet.GetContactProbability(); var probSelect = fleet.GetContactSelectionProbability(); sb.AppendFormat("(旧)2-5式: {0}\r\n2-5式(秋): {1}\r\n2-5新秋簡易式: {2}\r\n\r\n触接開始率: \r\n 確保 {3:p1} / 優勢 {4:p1}\r\n", fleet.GetSearchingAbilityString( 0 ), fleet.GetSearchingAbilityString( 1 ), fleet.GetSearchingAbilityString( 2 ), probStart, probStart * 0.6 ); if ( probSelect.Count > 0 ) { sb.AppendLine( "触接選択率: " ); foreach ( var p in probSelect.OrderBy( p => p.Key ) ) { sb.AppendFormat( " 命中{0} : {1:p1}\r\n", p.Key, p.Value ); } } ToolTipInfo.SetToolTip( SearchingAbility, sb.ToString() ); } }
/// <summary> /// 艦隊の状態の情報をラベルに適用します。 /// </summary> /// <param name="fleet">艦隊データ。</param> /// <param name="label">適用するラベル。</param> /// <param name="tooltip">適用するツールチップ。</param> /// <param name="prevstate">前回の状態。</param> /// <param name="timer">日時。</param> /// <returns>艦隊の状態を表す定数。</returns> public static FleetStates UpdateFleetState( FleetData fleet, ImageLabel label, ToolTip tooltip, FleetStates prevstate, ref DateTime timer ) { KCDatabase db = KCDatabase.Instance; //初期化 tooltip.SetToolTip( label, null ); label.BackColor = Color.Transparent; //所属艦なし if ( fleet == null || fleet.Members.Count( id => id != -1 ) == 0 ) { label.Text = FleetRes.NoShips; label.ImageIndex = (int)ResourceManager.IconContent.FleetNoShip; return FleetStates.NoShip; } { //入渠中 long ntime = db.Docks.Values.Max( dock => { if ( dock.State == 1 && fleet.Members.Count( ( id => id == dock.ShipID ) ) > 0 ) return dock.CompletionTime.Ticks; else return 0; } ); if ( ntime > 0 ) { //入渠中 timer = new DateTime( ntime ); label.Text = FleetRes.Docking + DateTimeHelper.ToTimeRemainString( timer ); label.ImageIndex = (int)ResourceManager.IconContent.FleetDocking; tooltip.SetToolTip( label, FleetRes.CompletionTime + ": " + timer ); return FleetStates.Docking; } } if ( fleet.IsInSortie ) { //大破出撃中 if ( fleet.MembersInstance.Count( s => ( s != null && !fleet.EscapedShipList.Contains( s.MasterID ) && (double)s.HPCurrent / s.HPMax <= 0.25 ) ) > 0 ) { label.Text = FleetRes.CriticalDamageAdvance; label.ImageIndex = (int)ResourceManager.IconContent.FleetSortieDamaged; return FleetStates.SortieDamaged; } else { //出撃中 label.Text = FleetRes.OnSortie; label.ImageIndex = (int)ResourceManager.IconContent.FleetSortie; return FleetStates.Sortie; } } //遠征中 if ( fleet.ExpeditionState != 0 ) { timer = fleet.ExpeditionTime; label.Text = FleetRes.OnExped + DateTimeHelper.ToTimeRemainString( timer ); label.ImageIndex = (int)ResourceManager.IconContent.FleetExpedition; tooltip.SetToolTip( label, string.Format( "{0} : {1}\r\n" + FleetRes.CompletionTime + " : {2}", KCDatabase.Instance.Mission[fleet.ExpeditionDestination].ID, KCDatabase.Instance.Mission[fleet.ExpeditionDestination].Name, timer ) ); return FleetStates.Expedition; } //大破艦あり if ( fleet.MembersInstance.Count( s => ( s != null && !fleet.EscapedShipList.Contains( s.MasterID ) && (double)s.HPCurrent / s.HPMax <= 0.25 ) ) > 0 ) { label.Text = FleetRes.CriticallyDamagedShip; label.ImageIndex = (int)ResourceManager.IconContent.FleetDamaged; //label.BackColor = Color.LightCoral; return FleetStates.Damaged; } //泊地修理中 { if ( fleet.IsAnchorageRepairing ) { label.Text = FleetRes.AnchorageRepairing + DateTimeHelper.ToTimeElapsedString( KCDatabase.Instance.Fleet.AnchorageRepairingTimer ); label.ImageIndex = (int)ResourceManager.IconContent.FleetAnchorageRepairing; tooltip.SetToolTip( label, string.Format( FleetRes.StartTime + ": {0}", KCDatabase.Instance.Fleet.AnchorageRepairingTimer ) ); return FleetStates.AnchorageRepairing; } } //未補給 { int fuel = fleet.MembersInstance.Sum( ship => ship == null ? 0 : (int)( ( ship.MasterShip.Fuel - ship.Fuel ) * ( ship.IsMarried ? 0.85 : 1.00 ) ) ); int ammo = fleet.MembersInstance.Sum( ship => ship == null ? 0 : (int)( ( ship.MasterShip.Ammo - ship.Ammo ) * ( ship.IsMarried ? 0.85 : 1.00 ) ) ); int aircraft = fleet.MembersInstance.Sum( ship => { if ( ship == null ) return 0; else { int c = 0; for ( int i = 0; i < ship.Slot.Count; i++ ) { c += ship.MasterShip.Aircraft[i] - ship.Aircraft[i]; } return c; } } ); int bauxite = aircraft * 5; if ( fuel > 0 || ammo > 0 || bauxite > 0 ) { label.Text = FleetRes.SupplyNeeded; label.ImageIndex = (int)ResourceManager.IconContent.FleetNotReplenished; tooltip.SetToolTip( label, string.Format( FleetRes.ResupplyTooltip, fuel, ammo, bauxite, aircraft ) ); return FleetStates.NotReplenished; } } //疲労 { int cond = fleet.MembersInstance.Min( s => s == null ? 100 : s.Condition ); if ( cond < Configuration.Config.Control.ConditionBorder && fleet.ConditionTime != null ) { timer = (DateTime)fleet.ConditionTime; label.Text = FleetRes.Fatigued + DateTimeHelper.ToTimeRemainString( timer ); if ( cond < 20 ) label.ImageIndex = (int)ResourceManager.IconContent.ConditionVeryTired; else if ( cond < 30 ) label.ImageIndex = (int)ResourceManager.IconContent.ConditionTired; else label.ImageIndex = (int)ResourceManager.IconContent.ConditionLittleTired; tooltip.SetToolTip( label, string.Format( FleetRes.EstimatedRecoveryTime + ": {0}", timer ) ); return FleetStates.Tired; } else if ( cond >= 50 ) { //戦意高揚 label.Text = FleetRes.FightingSpiritHigh; label.ImageIndex = (int)ResourceManager.IconContent.ConditionSparkle; tooltip.SetToolTip( label, string.Format( FleetRes.SparkledTooltip, cond, Math.Ceiling( ( cond - 49 ) / 3.0 ) ) ); return FleetStates.Sparkled; } } //出撃可能! { label.Text = FleetRes.ReadyToSortie; label.ImageIndex = (int)ResourceManager.IconContent.FleetReady; return FleetStates.Ready; } }
public override void LoadFromResponse(string apiname, dynamic data) { switch (apiname) { case "api_req_combined_battle/goback_port": foreach (int index in KCDatabase.Instance.Battle.Result.EscapingShipIndex) { Fleets[(index - 1) < 6 ? 1 : 2].Escape((index - 1) % 6); } break; case "api_get_member/ndock": foreach (var fleet in Fleets.Values) { fleet.LoadFromResponse(apiname, data); } break; case "api_req_hensei/preset_select": { int id = (int)data.api_id; if (!Fleets.ContainsKey(id)) { var a = new FleetData(); a.LoadFromResponse(apiname, data); Fleets.Add(a); } else { Fleets[id].LoadFromResponse(apiname, data); } } break; default: base.LoadFromResponse(apiname, (object)data); //api_port/port, api_get_member/deck foreach (var elem in data) { int id = (int)elem.api_id; if (!Fleets.ContainsKey(id)) { var a = new FleetData(); a.LoadFromResponse(apiname, elem); Fleets.Add(a); } else { Fleets[id].LoadFromResponse(apiname, elem); } } break; } // 泊地修理の処理 if (apiname == "api_port/port") { if ((DateTime.Now - AnchorageRepairingTimer).TotalMinutes >= 20) { StartAnchorageRepairingTimer(); } } }
/// <summary> /// 艦隊の状態の情報をラベルに適用します。 /// </summary> /// <param name="fleet">艦隊データ。</param> /// <param name="label">適用するラベル。</param> /// <param name="tooltip">適用するツールチップ。</param> /// <param name="prevstate">前回の状態。</param> /// <param name="timer">日時。</param> /// <returns>艦隊の状態を表す定数。</returns> public static FleetStates UpdateFleetState( FleetData fleet, ImageLabel label, ToolTip tooltip, FleetStates prevstate, ref DateTime timer ) { KCDatabase db = KCDatabase.Instance; //初期化 tooltip.SetToolTip( label, null ); label.BackColor = Color.Transparent; //所属艦なし if ( fleet == null || fleet.Members.Count( id => id != -1 ) == 0 ) { label.Text = "所属艦なし"; label.ImageIndex = (int)ResourceManager.IconContent.FleetNoShip; return FleetStates.NoShip; } // その他の状態は設定した順番に判定 foreach ( var key in Configuration.Config.FormFleetPlus.FleetIconOrder.List ) { var result = fleetStateFuncs[(int)key]( fleet, label, tooltip, prevstate ); if (result != null ) { if ( result.Item2 != null ) { timer = result.Item2.Value; } return result.Item1; } } //出撃可能! { label.Text = "出撃可能!"; label.ImageIndex = (int)ResourceManager.IconContent.FleetReady; return FleetStates.Ready; } }
/// <summary> /// 艦隊の状態の情報をラベルに適用します。 /// </summary> /// <param name="fleet">艦隊データ。</param> /// <param name="label">適用するラベル。</param> /// <param name="tooltip">適用するツールチップ。</param> /// <param name="prevstate">前回の状態。</param> /// <param name="timer">日時。</param> /// <returns>艦隊の状態を表す定数。</returns> public static FleetStates UpdateFleetState( FleetData fleet, ImageLabel label, ToolTip tooltip, FleetStates prevstate, ref DateTime timer ) { KCDatabase db = KCDatabase.Instance; //初期化 tooltip.SetToolTip( label, null ); label.BackColor = Color.Transparent; //所属艦なし if ( fleet == null || fleet.Members.Count( id => id != -1 ) == 0 ) { label.Text = "所属艦なし"; label.ImageIndex = (int)ResourceManager.IconContent.FleetNoShip; return FleetStates.NoShip; } { //入渠中 long ntime = db.Docks.Values.Max( dock => { if ( dock.State == 1 && fleet.Members.Count( ( id => id == dock.ShipID ) ) > 0 ) return dock.CompletionTime.Ticks; else return 0; } ); if ( ntime > 0 ) { //入渠中 timer = new DateTime( ntime ); label.Text = "入渠中 " + DateTimeHelper.ToTimeRemainString( timer ); label.ImageIndex = (int)ResourceManager.IconContent.FleetDocking; tooltip.SetToolTip( label, "完了日時 : " + DateTimeHelper.TimeToCSVString( timer ) ); return FleetStates.Docking; } } if ( fleet.IsInSortie ) { //大破出撃中 if ( fleet.MembersInstance.Count( s => ( s != null && !fleet.EscapedShipList.Contains( s.MasterID ) && (double)s.HPCurrent / s.HPMax <= 0.25 ) ) > 0 ) { label.Text = "!!大破進撃中!!"; label.ImageIndex = (int)ResourceManager.IconContent.FleetSortieDamaged; return FleetStates.SortieDamaged; } else { //出撃中 label.Text = "出撃中"; label.ImageIndex = (int)ResourceManager.IconContent.FleetSortie; return FleetStates.Sortie; } } //遠征中 if ( fleet.ExpeditionState != 0 ) { timer = fleet.ExpeditionTime; label.Text = "遠征中 " + DateTimeHelper.ToTimeRemainString( timer ); label.ImageIndex = (int)ResourceManager.IconContent.FleetExpedition; tooltip.SetToolTip( label, string.Format( "{0} : {1}\r\n完了日時 : {2}", KCDatabase.Instance.Mission[fleet.ExpeditionDestination].ID, KCDatabase.Instance.Mission[fleet.ExpeditionDestination].Name, DateTimeHelper.TimeToCSVString( timer ) ) ); return FleetStates.Expedition; } //大破艦あり if ( fleet.MembersInstance.Count( s => ( s != null && !fleet.EscapedShipList.Contains( s.MasterID ) && (double)s.HPCurrent / s.HPMax <= 0.25 ) ) > 0 ) { label.Text = "大破艦あり!"; label.ImageIndex = (int)ResourceManager.IconContent.FleetDamaged; //label.BackColor = Color.LightCoral; return FleetStates.Damaged; } //泊地修理中 { if ( fleet.CanAnchorageRepairing && fleet.MembersInstance.Take( 2 + KCDatabase.Instance.Ships[fleet[0]].SlotInstanceMaster.Count( eq => eq != null && eq.CategoryType == 31 ) ) .Any( s => s != null && s.HPRate < 1.0 && s.HPRate > 0.5 && s.RepairingDockID == -1 ) ) { label.Text = "泊地修理中 " + DateTimeHelper.ToTimeElapsedString( KCDatabase.Instance.Fleet.AnchorageRepairingTimer ); label.ImageIndex = (int)ResourceManager.IconContent.FleetAnchorageRepairing; tooltip.SetToolTip( label, string.Format( "開始日時 : {0}", DateTimeHelper.TimeToCSVString( KCDatabase.Instance.Fleet.AnchorageRepairingTimer ) ) ); return FleetStates.AnchorageRepairing; } } //未補給 { int fuel = fleet.MembersInstance.Sum( ship => ship == null ? 0 : (int)( ( ship.FuelMax - ship.Fuel ) * ( ship.IsMarried ? 0.85 : 1.00 ) ) ); int ammo = fleet.MembersInstance.Sum( ship => ship == null ? 0 : (int)( ( ship.AmmoMax - ship.Ammo ) * ( ship.IsMarried ? 0.85 : 1.00 ) ) ); int aircraft = fleet.MembersInstance.Sum( ship => { if ( ship == null ) return 0; else { int c = 0; for ( int i = 0; i < ship.Slot.Count; i++ ) { c += ship.MasterShip.Aircraft[i] - ship.Aircraft[i]; } return c; } } ); int bauxite = aircraft * 5; if ( fuel > 0 || ammo > 0 || bauxite > 0 ) { label.Text = "未補給"; label.ImageIndex = (int)ResourceManager.IconContent.FleetNotReplenished; tooltip.SetToolTip( label, string.Format( "燃 : {0}\r\n弾 : {1}\r\nボ : {2} ({3}機)", fuel, ammo, bauxite, aircraft ) ); return FleetStates.NotReplenished; } } //疲労 { int cond = fleet.MembersInstance.Min( s => s == null ? 100 : s.Condition ); if ( cond < Configuration.Config.Control.ConditionBorder && fleet.ConditionTime != null ) { timer = (DateTime)fleet.ConditionTime; label.Text = "疲労 " + DateTimeHelper.ToTimeRemainString( timer ); if ( cond < 20 ) label.ImageIndex = (int)ResourceManager.IconContent.ConditionVeryTired; else if ( cond < 30 ) label.ImageIndex = (int)ResourceManager.IconContent.ConditionTired; else label.ImageIndex = (int)ResourceManager.IconContent.ConditionLittleTired; tooltip.SetToolTip( label, string.Format( "回復目安日時: {0}", DateTimeHelper.TimeToCSVString( timer ) ) ); return FleetStates.Tired; } else if ( cond >= 50 ) { //戦意高揚 label.Text = "戦意高揚!"; label.ImageIndex = (int)ResourceManager.IconContent.ConditionSparkle; tooltip.SetToolTip( label, string.Format( "最低cond: {0}\r\nあと {1} 回遠征可能", cond, Math.Ceiling( ( cond - 49 ) / 3.0 ) ) ); return FleetStates.Sparkled; } } //出撃可能! { label.Text = "出撃可能!"; label.ImageIndex = (int)ResourceManager.IconContent.FleetReady; return FleetStates.Ready; } }
/// <summary> /// 艦隊の触接開始率を求めます。 /// </summary> /// <param name="fleet">対象の艦隊。</param> public static double GetContactProbability( FleetData fleet ) { double successProb = 0.0; foreach ( var ship in fleet.MembersWithoutEscaped ) { if ( ship == null ) continue; var eqs = ship.SlotInstanceMaster; for ( int i = 0; i < ship.Slot.Count; i++ ) { if ( eqs[i] == null ) continue; if ( eqs[i].CategoryType == 9 || // 艦上偵察機 eqs[i].CategoryType == 10 || // 水上偵察機 eqs[i].CategoryType == 41 ) { // 大型飛行艇 successProb += 0.04 * eqs[i].LOS * Math.Sqrt( ship.Aircraft[i] ); } } } return successProb; }
/// <summary> /// 機体命中率別の触接選択率を求めます。 /// </summary> /// <param name="fleet">対象の艦隊。</param> /// <returns>機体の命中をキー, 触接選択率を値とした Dictionary 。</returns> public static Dictionary<int, double> GetContactSelectionProbability( FleetData fleet ) { var probs = new Dictionary<int, double>(); foreach ( var ship in fleet.MembersWithoutEscaped ) { if ( ship == null ) continue; foreach ( var eq in ship.SlotInstanceMaster ) { if ( eq == null ) continue; switch ( eq.CategoryType ) { case 8: // 艦上攻撃機 case 9: // 艦上偵察機 case 10: // 水上偵察機 case 41: // 大型飛行艇 if ( !probs.ContainsKey( eq.Accuracy ) ) probs.Add( eq.Accuracy, 1.0 ); probs[eq.Accuracy] *= 1.0 - ( 0.07 * eq.LOS ); break; } } } foreach ( int key in probs.Keys.ToArray() ) { //列挙中の変更エラーを防ぐため probs[key] = 1.0 - probs[key]; } return probs; }
/// <summary> /// 艦隊の状態の情報をラベルに適用します。 /// </summary> /// <param name="fleet">艦隊データ。</param> /// <param name="label">適用するラベル。</param> /// <param name="tooltip">適用するツールチップ。</param> /// <param name="prevstate">前回の状態。</param> /// <param name="timer">日時。</param> /// <returns>艦隊の状態を表す定数。</returns> public static FleetStates UpdateFleetState(FleetData fleet, ImageLabel label, ToolTip tooltip, FleetStates prevstate, ref DateTime timer) { KCDatabase db = KCDatabase.Instance; //初期化 tooltip.SetToolTip(label, null); label.BackColor = Color.Transparent; //所属艦なし if (fleet == null || fleet.Members.Count(id => id != -1) == 0) { label.Text = "所属艦なし"; label.ImageIndex = (int)ResourceManager.IconContent.FleetNoShip; return(FleetStates.NoShip); } { //入渠中 long ntime = db.Docks.Values.Max( dock => { if (dock.State == 1 && fleet.Members.Count((id => id == dock.ShipID)) > 0) { return(dock.CompletionTime.Ticks); } else { return(0); } } ); if (ntime > 0) //入渠中 { timer = new DateTime(ntime); label.Text = "入渠中 " + DateTimeHelper.ToTimeRemainString(timer); label.ImageIndex = (int)ResourceManager.IconContent.FleetDocking; tooltip.SetToolTip(label, "完了日時 : " + DateTimeHelper.TimeToCSVString(timer)); return(FleetStates.Docking); } } if (fleet.IsInSortie) { //大破出撃中 if (fleet.MembersInstance.Count(s => (s != null && !fleet.EscapedShipList.Contains(s.MasterID) && (double)s.HPCurrent / s.HPMax <= 0.25) ) > 0) { label.Text = "!!大破進撃中!!"; label.ImageIndex = (int)ResourceManager.IconContent.FleetSortieDamaged; return(FleetStates.SortieDamaged); } else //出撃中 { label.Text = "出撃中"; label.ImageIndex = (int)ResourceManager.IconContent.FleetSortie; return(FleetStates.Sortie); } } //遠征中 if (fleet.ExpeditionState != 0) { timer = fleet.ExpeditionTime; label.Text = "遠征中 " + DateTimeHelper.ToTimeRemainString(timer); label.ImageIndex = (int)ResourceManager.IconContent.FleetExpedition; tooltip.SetToolTip(label, string.Format("{0} : {1}\r\n完了日時 : {2}", KCDatabase.Instance.Mission[fleet.ExpeditionDestination].ID, KCDatabase.Instance.Mission[fleet.ExpeditionDestination].Name, DateTimeHelper.TimeToCSVString(timer))); return(FleetStates.Expedition); } //大破艦あり if (fleet.MembersInstance.Count(s => (s != null && !fleet.EscapedShipList.Contains(s.MasterID) && (double)s.HPCurrent / s.HPMax <= 0.25) ) > 0) { label.Text = "大破艦あり!"; label.ImageIndex = (int)ResourceManager.IconContent.FleetDamaged; //label.BackColor = Color.LightCoral; return(FleetStates.Damaged); } //泊地修理中 { if (fleet.CanAnchorageRepairing && fleet.MembersInstance.Take(2 + KCDatabase.Instance.Ships[fleet[0]].SlotInstanceMaster.Count(eq => eq != null && eq.CategoryType == 31)) .Any(s => s != null && s.HPRate <1.0 && s.HPRate> 0.5 && s.RepairingDockID == -1)) { label.Text = "泊地修理中 " + DateTimeHelper.ToTimeElapsedString(KCDatabase.Instance.Fleet.AnchorageRepairingTimer); label.ImageIndex = (int)ResourceManager.IconContent.FleetAnchorageRepairing; StringBuilder sb = new StringBuilder(); sb.AppendFormat("開始日時 : {0}\r\n修理時間 :\r\n", DateTimeHelper.TimeToCSVString(KCDatabase.Instance.Fleet.AnchorageRepairingTimer)); for (int i = 0; i < fleet.Members.Count; i++) { var ship = fleet.MembersInstance[i]; if (ship != null && ship.HPRate < 1.0) { var totaltime = DateTimeHelper.FromAPITimeSpan(ship.RepairTime); var unittime = Calculator.CalculateDockingUnitTime(ship); sb.AppendFormat("#{0} : {1:00}:{2:00}:{3:00} @ {4:00}:{5:00}:{6:00} x -{7} HP\r\n", i + 1, (int)totaltime.TotalHours, totaltime.Minutes, totaltime.Seconds, (int)unittime.TotalHours, unittime.Minutes, unittime.Seconds, ship.HPMax - ship.HPCurrent ); } else { sb.Append("#").Append(i + 1).Append(" : ----\r\n"); } } tooltip.SetToolTip(label, sb.ToString()); return(FleetStates.AnchorageRepairing); } } //未補給 { int fuel = fleet.MembersInstance.Sum(ship => ship == null ? 0 : (int)((ship.FuelMax - ship.Fuel) * (ship.IsMarried ? 0.85 : 1.00))); int ammo = fleet.MembersInstance.Sum(ship => ship == null ? 0 : (int)((ship.AmmoMax - ship.Ammo) * (ship.IsMarried ? 0.85 : 1.00))); int aircraft = fleet.MembersInstance.Sum( ship => { if (ship == null) { return(0); } else { int c = 0; for (int i = 0; i < ship.Slot.Count; i++) { c += ship.MasterShip.Aircraft[i] - ship.Aircraft[i]; } return(c); } }); int bauxite = aircraft * 5; if (fuel > 0 || ammo > 0 || bauxite > 0) { label.Text = "未補給"; label.ImageIndex = (int)ResourceManager.IconContent.FleetNotReplenished; tooltip.SetToolTip(label, string.Format("燃 : {0}\r\n弾 : {1}\r\nボ : {2} ({3}機)", fuel, ammo, bauxite, aircraft)); return(FleetStates.NotReplenished); } } //疲労 { int cond = fleet.MembersInstance.Min(s => s == null ? 100 : s.Condition); if (cond < Configuration.Config.Control.ConditionBorder && fleet.ConditionTime != null) { timer = (DateTime)fleet.ConditionTime; label.Text = "疲労 " + DateTimeHelper.ToTimeRemainString(timer); if (cond < 20) { label.ImageIndex = (int)ResourceManager.IconContent.ConditionVeryTired; } else if (cond < 30) { label.ImageIndex = (int)ResourceManager.IconContent.ConditionTired; } else { label.ImageIndex = (int)ResourceManager.IconContent.ConditionLittleTired; } tooltip.SetToolTip(label, string.Format("回復目安日時: {0}", DateTimeHelper.TimeToCSVString(timer))); return(FleetStates.Tired); } else if (cond >= 50) //戦意高揚 { label.Text = "戦意高揚!"; label.ImageIndex = (int)ResourceManager.IconContent.ConditionSparkle; tooltip.SetToolTip(label, string.Format("最低cond: {0}\r\nあと {1} 回遠征可能", cond, Math.Ceiling((cond - 49) / 3.0))); return(FleetStates.Sparkled); } } //出撃可能! { label.Text = "出撃可能!"; label.ImageIndex = (int)ResourceManager.IconContent.FleetReady; return(FleetStates.Ready); } }
/// <summary> /// 輸送作戦成功時の輸送量(減少TP)を求めます。 /// (S勝利時のもの。A勝利時は int( value * 0.7 ) ) /// </summary> /// <param name="fleet">対象の艦隊。</param> /// <returns>減少TP。</returns> public static int GetTPDamage( FleetData fleet ) { int tp = 0; foreach ( var ship in fleet.MembersWithoutEscaped.Where( s => s != null && s.HPRate > 0.25 ) ) { // 装備ボーナス foreach ( var eq in ship.AllSlotInstanceMaster.Where( q => q != null ) ) { switch ( eq.CategoryType ) { case 24: // 上陸用舟艇 tp += 8; break; case 30: // 簡易輸送部材 tp += 5; break; case 43: // 戦闘糧食 tp += 1; break; case 46: // 特型内火艇 tp += 2; break; } } // 艦種ボーナス switch ( ship.MasterShip.ShipType ) { case 2: // 駆逐艦 tp += 5; break; case 3: // 軽巡洋艦 tp += 2; break; case 5: // 重巡洋艦 tp += 0; break; case 6: // 航空巡洋艦 tp += 4; break; case 10: // 航空戦艦 tp += 7; break; case 16: // 水上機母艦 tp += 9; break; case 17: // 揚陸艦 tp += 12; break; case 20: // 潜水母艦 tp += 7; break; case 21: // 練習巡洋艦 tp += 6; break; case 22: // 補給艦 tp += 15; break; } } return tp; }
/// <summary> /// 制空戦力を求めます。 /// </summary> /// <param name="fleet">対象の艦隊。</param> public static int GetAirSuperiority( FleetData fleet ) { int air = 0; foreach ( var ship in fleet.MembersWithoutEscaped ) { if ( ship == null ) continue; air += GetAirSuperiority( ship ); } return air; }
/// <summary> /// 遠征に成功する編成かどうかを判定します。 /// </summary> /// <param name="missionID">遠征ID。</param> /// <param name="fleet">対象となる艦隊。達成条件を確認したい場合は null を指定します。</param> public static MissionClearConditionResult Check(int missionID, FleetData fleet) { var result = new MissionClearConditionResult(fleet); switch (missionID) { case 1: // 練習航海 return(result .CheckFlagshipLevel(1) .CheckShipCount(2)); case 2: // 長距離練習航海 return(result .CheckFlagshipLevel(2) .CheckShipCount(4)); case 3: // 警備任務 return(result .CheckFlagshipLevel(3) .CheckShipCount(3)); case 4: // 対潜警戒任務 return(result .CheckFlagshipLevel(3) .CheckEscortFleet()); case 5: // 海上護衛任務 return(result .CheckFlagshipLevel(3) .CheckShipCount(4) .CheckEscortFleet()); case 6: // 防空射撃演習 return(result .CheckFlagshipLevel(4) .CheckShipCount(4)); case 7: // 観艦式予行 return(result .CheckFlagshipLevel(5) .CheckShipCount(6)); case 8: // 観艦式 return(result .CheckFlagshipLevel(6) .CheckShipCount(6)); case 100: // 兵站強化任務 return(result .CheckFlagshipLevel(5) .CheckLevelSum(10) .CheckShipCount(4) .CheckSmallShipCount(3)); case 101: // 海峡警備行動 return(result .CheckFlagshipLevel(20) .CheckSmallShipCount(4) .CheckFirepower(50) .CheckAA(70) .CheckASW(180)); case 102: // 長時間対潜警戒 return(result .CheckFlagshipLevel(35) .CheckLevelSum(185) .CheckShipCount(5) .CheckEscortFleetDD3() .CheckAA(59) .CheckASW(280) .CheckLOS(60)); case 103: // 南西方面連絡線哨戒 return(result .CheckFlagshipLevel(40) .CheckLevelSum(200) .CheckShipCount(5) .CheckEscortFleet() .CheckFirepower(300) .CheckAA(200) .CheckASW(200) .CheckLOS(120)); case 104: // 小笠原沖哨戒線 return(result .CheckFlagshipLevel(45) .CheckLevelSum(230) .CheckShipCount(5) .CheckEscortFleetDD3() .CheckFirepower(280) .CheckAA(220) .CheckASW(240) .CheckLOS(150)); case 105: // 小笠原沖戦闘哨戒 return(result .CheckFlagshipLevel(55) .CheckLevelSum(290) .CheckShipCount(6) .CheckEscortFleetDD3() .CheckFirepower(330) .CheckAA(300) .CheckASW(270) .CheckLOS(180)); case 9: // タンカー護衛任務 return(result .CheckFlagshipLevel(3) .CheckShipCount(4) .CheckEscortFleet()); case 10: // 強行偵察任務 return(result .CheckFlagshipLevel(3) .CheckShipCount(3) .CheckShipCountByType(ShipTypes.LightCruiser, 2)); case 11: // ボーキサイト輸送任務 return(result .CheckFlagshipLevel(6) .CheckShipCount(4) .CheckSmallShipCount(2)); case 12: // 資源輸送任務 return(result .CheckFlagshipLevel(4) .CheckShipCount(4) .CheckSmallShipCount(2)); case 13: // 鼠輸送作戦 return(result .CheckFlagshipLevel(5) .CheckShipCount(6) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 4)); case 14: // 包囲陸戦隊撤収作戦 return(result .CheckFlagshipLevel(6) .CheckShipCount(6) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 3)); case 15: // 囮機動部隊支援作戦 return(result .CheckFlagshipLevel(8) .CheckShipCount(6) .CheckAircraftCarrierCount(2) .CheckShipCountByType(ShipTypes.Destroyer, 2)); case 16: // 艦隊決戦援護作戦 return(result .CheckFlagshipLevel(10) .CheckShipCount(6) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 2)); case 110: // 南西方面航空偵察作戦 return(result .CheckFlagshipLevel(40) .CheckLevelSum(150) .CheckShipCount(6) .CheckShipCountByType(ShipTypes.SeaplaneTender, 1) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckSmallShipCount(2) .CheckAA(200) .CheckASW(200) .CheckLOS(140)); case 111: // 敵泊地強襲反撃作戦 return(result .CheckFlagshipLevel(45) .CheckLevelSum(220) .CheckShipCount(6) .CheckShipCountByType(ShipTypes.HeavyCruiser, 1) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 3) .CheckFirepower(360) .CheckAA(160) .CheckASW(160) .CheckLOS(140)); case 112: // 南西諸島離島哨戒作戦 return(result .CheckFlagshipLevel(50) .CheckLevelSum(250) .CheckShipCountByType(ShipTypes.SeaplaneTender, 1) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckSmallShipCount(4) .CheckFirepower(400) .CheckAA(220) .CheckASW(220) .CheckLOS(190)); case 113: // 南西諸島離島防衛作戦 return(result .CheckFlagshipLevel(55) .CheckLevelSum(300) .CheckShipCountByType(ShipTypes.HeavyCruiser, 2) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 2) .CheckSubmarineCount(1) .CheckFirepower(500) .CheckAA(280) .CheckASW(280) .CheckLOS(170)); case 114: // 南西諸島捜索撃滅戦 return(result .CheckFlagshipLevel(60) .CheckLevelSum(330) .CheckShipCount(6) .CheckShipCountByType(ShipTypes.SeaplaneTender, 1) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 2) .CheckFirepower(510) .CheckAA(400) .CheckASW(285) .CheckLOS(385)); case 17: // 敵地偵察作戦 return(result .CheckFlagshipLevel(20) .CheckShipCount(6) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 3)); case 18: // 航空機輸送作戦 return(result .CheckFlagshipLevel(15) .CheckShipCount(6) .CheckAircraftCarrierCount(3) .CheckShipCountByType(ShipTypes.Destroyer, 2)); case 19: // 北号作戦 return(result .CheckFlagshipLevel(20) .CheckShipCount(6) .CheckShipCountByType(ShipTypes.AviationBattleship, 2) .CheckShipCountByType(ShipTypes.Destroyer, 2)); case 20: // 潜水艦哨戒任務 return(result .CheckFlagshipLevel(1) .CheckSubmarineCount(1) .CheckShipCountByType(ShipTypes.LightCruiser, 1)); case 21: // 北方鼠輸送作戦 return(result .CheckFlagshipLevel(15) .CheckLevelSum(30) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 4) .CheckEquippedShipCount(EquipmentTypes.TransportContainer, 3)); case 22: // 艦隊演習 return(result .CheckFlagshipLevel(30) .CheckLevelSum(45) .CheckShipCount(6) .CheckShipCountByType(ShipTypes.HeavyCruiser, 1) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 2)); case 23: // 航空戦艦運用演習 return(result .CheckFlagshipLevel(50) .CheckLevelSum(200) .CheckShipCount(6) .CheckShipCountByType(ShipTypes.AviationBattleship, 2) .CheckShipCountByType(ShipTypes.Destroyer, 2)); case 24: // 北方航路海上護衛 return(result .CheckFlagshipLevel(50) .CheckLevelSum(200) .CheckShipCount(6) .CheckFlagshipType(ShipTypes.LightCruiser) .CheckSmallShipCount(4)); case 25: // 通商破壊作戦 return(result .CheckFlagshipLevel(25) .CheckShipCountByType(ShipTypes.HeavyCruiser, 2) .CheckShipCountByType(ShipTypes.Destroyer, 2)); case 26: // 敵母港空襲作戦 return(result .CheckFlagshipLevel(30) .CheckAircraftCarrierCount(1) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 2)); case 27: // 潜水艦通商破壊作戦 return(result .CheckFlagshipLevel(1) .CheckSubmarineCount(2)); case 28: // 潜水艦通商破壊作戦 return(result .CheckFlagshipLevel(30) .CheckSubmarineCount(3)); case 29: // 潜水艦派遣演習 return(result .CheckFlagshipLevel(50) .CheckSubmarineCount(3)); case 30: // 潜水艦派遣作戦 return(result .CheckFlagshipLevel(55) .CheckSubmarineCount(4)); case 31: // 海外艦との接触 return(result .CheckFlagshipLevel(60) .CheckLevelSum(200) .CheckSubmarineCount(4)); case 32: // 遠洋練習航海 return(result .CheckFlagshipLevel(5) .CheckFlagshipType(ShipTypes.TrainingCruiser) .CheckShipCountByType(ShipTypes.Destroyer, 2)); case 131: // 西方海域偵察作戦 return(result .CheckFlagshipLevel(50) .CheckLevelSum(200) .CheckShipCount(5) .CheckFlagshipType(ShipTypes.SeaplaneTender) .CheckShipCountByType(ShipTypes.Destroyer, 3) .CheckAA(240) .CheckASW(240) .CheckLOS(300)); case 132: // 西方潜水艦作戦 return(result .CheckFlagshipLevel(55) .CheckLevelSum(270) .CheckShipCount(5) .CheckFlagshipType(ShipTypes.SubmarineTender) .CheckSubmarineCount(3) .CheckFirepower(60) .CheckAA(80) .CheckASW(50)); case 33: // 前衛支援任務 return(result .CheckShipCountByType(ShipTypes.Destroyer, 2)); case 34: // 艦隊決戦支援任務 return(result .CheckShipCountByType(ShipTypes.Destroyer, 2)); case 35: // MO作戦 return(result .CheckFlagshipLevel(40) .CheckShipCount(6) .CheckAircraftCarrierCount(2) .CheckShipCountByType(ShipTypes.HeavyCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 1)); case 36: // 水上機基地建設 return(result .CheckFlagshipLevel(30) .CheckShipCount(6) .CheckShipCountByType(ShipTypes.SeaplaneTender, 2) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 1)); case 37: // 東京急行 return(result .CheckFlagshipLevel(50) .CheckLevelSum(200) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 5) .CheckEquippedShipCount(EquipmentTypes.TransportContainer, 3) .CheckEquipmentCount(EquipmentTypes.TransportContainer, 4)); case 38: // 東京急行(弐) return(result .CheckFlagshipLevel(65) .CheckLevelSum(240) .CheckShipCount(6) .CheckShipCountByType(ShipTypes.Destroyer, 5) .CheckEquippedShipCount(EquipmentTypes.TransportContainer, 4) .CheckEquipmentCount(EquipmentTypes.TransportContainer, 8)); case 39: // 遠洋潜水艦作戦 return(result .CheckFlagshipLevel(3) .CheckLevelSum(180) .CheckShipCountByType(ShipTypes.SubmarineTender, 1) .CheckSubmarineCount(4)); case 40: // 水上機前線輸送 return(result .CheckFlagshipLevel(25) .CheckLevelSum(150) .CheckShipCount(6) .CheckFlagshipType(ShipTypes.LightCruiser) .CheckShipCountByType(ShipTypes.SeaplaneTender, 2) .CheckShipCountByType(ShipTypes.Destroyer, 2)); case 141: // ラバウル方面艦隊進出 return(result .CheckFlagshipLevel(55) .CheckLevelSum(290) .CheckShipCount(6) .CheckFlagshipType(ShipTypes.HeavyCruiser) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 3) .CheckFirepower(450) .CheckAA(350) .CheckASW(330) .CheckLOS(250)); case 142: // 強行鼠輸送作戦 (unchecked) return(result .CheckFlagshipLevel(70) .CheckLevelSum(353) .CheckShipCountByType(ShipTypes.Destroyer, 5) .CheckEquippedShipCount(EquipmentTypes.TransportContainer, 3) .CheckEquipmentCount(EquipmentTypes.TransportContainer, 5) .CheckFirepower(280) .CheckAA(289) .CheckASW(278) .CheckLOS(164) .SuppressWarnings()); case 41: // ブルネイ泊地沖哨戒 return(result .CheckFlagshipLevel(30) .CheckLevelSum(100) .CheckSmallShipCount(3) .CheckFirepower(60) .CheckAA(80) .CheckASW(210)); case 42: // ミ船団護衛(一号船団) return(result .CheckFlagshipLevel(45) .CheckLevelSum(200) .CheckShipCount(4) .CheckEscortFleet()); case 43: // ミ船団護衛(二号船団) return(result .CheckFlagshipLevel(55) .CheckLevelSum(300) .CheckShipCount(6) .CheckFlagshipType(ShipTypes.LightAircraftCarrier) .CheckEscortFleet() .CheckFirepower(500) .CheckAA(280) .CheckASW(280) .CheckLOS(170)); case 44: // 航空装備輸送任務 return(result .CheckFlagshipLevel(35) .CheckLevelSum(210) .CheckShipCount(6) .CheckAircraftCarrierCount(1, includesSeaplaneTender: false) .CheckShipCountByType(ShipTypes.SeaplaneTender, 1) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckSmallShipCount(2) .CheckEquippedShipCount(EquipmentTypes.TransportContainer, 3) .CheckEquipmentCount(EquipmentTypes.TransportContainer, 6) .CheckAA(200) .CheckASW(200) .CheckLOS(150)); case 45: // ボーキサイト船団護衛 return(result .CheckFlagshipLevel(50) .CheckLevelSum(240) .CheckFlagshipType(ShipTypes.LightAircraftCarrier) .CheckSmallShipCount(4) .CheckAA(240) .CheckASW(300) .CheckLOS(180)); case 46: // 南西海域戦闘哨戒 (unchecked) return(result .CheckFlagshipLevel(65) .CheckLevelSum(300) .CheckShipCount(5) .CheckShipCountByType(ShipTypes.HeavyCruiser, 2) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 2) .CheckFirepower(350) .CheckAA(324) .CheckASW(220) .CheckLOS(220) .SuppressWarnings()); default: { // イベント海域での支援遠征への対応 var mission = KCDatabase.Instance.Mission[missionID]; if (mission != null && (mission.Name == "前衛支援任務" || mission.Name == "艦隊決戦支援任務")) { return(result .CheckShipCountByType(ShipTypes.Destroyer, 2)); } return(result .AddMessage($"未対応(ID:{missionID})")); } } }
public void Update( FleetData fleet ) { KCDatabase db = KCDatabase.Instance; if ( fleet == null ) return; Name.Text = fleet.Name; { int levelSum = fleet.MembersInstance.Sum( s => s != null ? s.Level : 0 ); int fueltotal = fleet.MembersInstance.Sum( s => s == null ? 0 : (int)( s.MasterShip.Fuel * ( s.IsMarried ? 0.85 : 1.00 ) ) ); int ammototal = fleet.MembersInstance.Sum( s => s == null ? 0 : (int)( s.MasterShip.Ammo * ( s.IsMarried ? 0.85 : 1.00 ) ) ); int speed = fleet.MembersWithoutEscaped.Min( s => s == null ? 10 : s.MasterShip.Speed ); ToolTipInfo.SetToolTip(Name, string.Format( GeneralRes.FleetTooltip, levelSum, (double)levelSum / Math.Max( fleet.Members.Count( id => id != -1 ), 1 ), Constants.GetSpeed( speed ), fleet.MembersInstance.Sum( s => s == null ? 0 : s.SlotInstanceMaster.Count( q => q == null ? false : q.CategoryType == 30 ) ), fleet.MembersInstance.Count( s => s == null ? false : s.SlotInstanceMaster.Count( q => q == null ? false : q.CategoryType == 30 ) > 0 ), fleet.MembersInstance.Sum( s => s == null ? 0 : s.SlotInstanceMaster.Count( q => q == null ? false : q.CategoryType == 24 ) ), fueltotal, ammototal, (int)( fueltotal * 0.2 ), (int)( ammototal * 0.2 ) ) ); } State = FleetData.UpdateFleetState( fleet, StateMain, ToolTipInfo, State, ref Timer ); //制空戦力計算 { int airSuperiority = fleet.GetAirSuperiority(); AirSuperiority.Text = airSuperiority.ToString(); ToolTipInfo.SetToolTip( AirSuperiority, string.Format( GeneralRes.ASTooltip, (int)( airSuperiority / 3.0 ), (int)( airSuperiority / 1.5 ), (int)( airSuperiority * 1.5 ), (int)( airSuperiority * 3.0 ) ) ); } //索敵能力計算 SearchingAbility.Text = fleet.GetSearchingAbilityString(); ToolTipInfo.SetToolTip( SearchingAbility, string.Format( GeneralRes.LoSTooltip, fleet.GetSearchingAbilityString( 0 ), fleet.GetSearchingAbilityString( 1 ), fleet.GetSearchingAbilityString( 2 ) ) ); }
public void Update( FleetData fleet ) { KCDatabase db = KCDatabase.Instance; if ( fleet == null ) return; Name.Text = fleet.Name; { int levelSum = fleet.MembersInstance.Sum( s => s != null ? s.Level : 0 ); int fueltotal = fleet.MembersInstance.Sum( s => s == null ? 0 : (int)Math.Floor( s.FuelMax * ( s.IsMarried ? 0.85 : 1.00 ) ) ); int ammototal = fleet.MembersInstance.Sum( s => s == null ? 0 : (int)Math.Floor( s.AmmoMax * ( s.IsMarried ? 0.85 : 1.00 ) ) ); int fuelunit = fleet.MembersInstance.Sum( s => s == null ? 0 : (int)Math.Floor( s.MasterShip.Fuel * 0.2 * ( s.IsMarried ? 0.85 : 1.00 ) ) ); int ammounit = fleet.MembersInstance.Sum( s => s == null ? 0 : (int)Math.Floor( s.MasterShip.Ammo * 0.2 * ( s.IsMarried ? 0.85 : 1.00 ) ) ); int speed = fleet.MembersWithoutEscaped.Min( s => s == null ? 10 : s.MasterShip.Speed ); var slots = fleet.MembersWithoutEscaped .Where( s => s != null ) .SelectMany( s => s.SlotInstance ) .Where( e => e != null ); var daihatsu = slots.Where( e => e.EquipmentID == 68 ); var daihatsu_tank = slots.Where( e => e.EquipmentID == 166 ); var landattacker = slots.Where( e => e.EquipmentID == 167 ); double expeditionBonus = Math.Min( daihatsu.Count() * 0.05 + daihatsu_tank.Count() * 0.02 + landattacker.Count() * 0.01, 0.20 ); ToolTipInfo.SetToolTip( Name, string.Format( "Lv合計: {0} / 平均: {1:0.00}\r\n{2}艦隊\r\nドラム缶搭載: {3}個 ({4}艦)\r\n大発動艇搭載: {5}個 ({6}艦, +{7:p1})\r\n総積載: 燃 {8} / 弾 {9}\r\n(1戦当たり 燃 {10} / 弾 {11})", levelSum, (double)levelSum / Math.Max( fleet.Members.Count( id => id != -1 ), 1 ), Constants.GetSpeed( speed ), fleet.MembersInstance.Sum( s => s == null ? 0 : s.SlotInstanceMaster.Count( q => q == null ? false : q.CategoryType == 30 ) ), fleet.MembersInstance.Count( s => s == null ? false : s.SlotInstanceMaster.Any( q => q == null ? false : q.CategoryType == 30 ) ), daihatsu.Count() + daihatsu_tank.Count() + landattacker.Count(), fleet.MembersInstance.Count( s => s == null ? false : s.SlotInstanceMaster.Any( q => q == null ? false : q.CategoryType == 24 || q.CategoryType == 46 ) ), expeditionBonus + 0.01 * expeditionBonus * ( daihatsu.Sum( e => e.Level ) + daihatsu_tank.Sum( e => e.Level ) + landattacker.Sum( e => e.Level ) ) / Math.Max( daihatsu.Count() + daihatsu_tank.Count() + landattacker.Count(), 1 ), fueltotal, ammototal, fuelunit, ammounit ) ); } State = FleetData.UpdateFleetState( fleet, StateMain, ToolTipInfo, State, ref Timer ); var config = Utility.Configuration.Config.FormFleetPlus.FleetsInfoIcon[FleetID - 1]; //制空戦力計算 { int airSuperiority = fleet.GetAirSuperiority(); AirSuperiority.Text = airSuperiority.ToString(); ToolTipInfo.SetToolTip( AirSuperiority, string.Format( "確保: {0}\r\n優勢: {1}\r\n均衡: {2}\r\n劣勢: {3}\r\n", (int)( airSuperiority / 3.0 ), (int)( airSuperiority / 1.5 ), (int)( airSuperiority * 1.5 - 1 ), (int)( airSuperiority * 3.0 - 1 ) ) ); AirSuperiority.Visible = config[0]; } //索敵能力計算 SearchingAbility.Text = fleet.GetSearchingAbilityString(); { StringBuilder sb = new StringBuilder(); double probStart = fleet.GetContactProbability(); var probSelect = fleet.GetContactSelectionProbability(); sb.AppendFormat( "(旧)2-5式: {0}\r\n2-5式(秋): {1}\r\n2-5新秋簡易式: {2}\r\n判定式(33): {3}\r\n\r\n触接開始率: \r\n 確保 {4:p1} / 優勢 {5:p1}\r\n", fleet.GetSearchingAbilityString( 0 ), fleet.GetSearchingAbilityString( 1 ), fleet.GetSearchingAbilityString( 2 ), fleet.GetSearchingAbilityString( 3 ), probStart, probStart * 0.6 ); if ( probSelect.Count > 0 ) { sb.AppendLine( "触接選択率: " ); foreach ( var p in probSelect.OrderBy( p => p.Key ) ) { sb.AppendFormat( " 命中{0} : {1:p1}\r\n", p.Key, p.Value ); } } ToolTipInfo.SetToolTip( SearchingAbility, sb.ToString() ); } SearchingAbility.Visible = config[1]; int drumTotal = fleet.MembersInstance.Sum( s => s?.SlotInstanceMaster.Count( q => q?.CategoryType == 30 ) ?? 0 ); int drumShipTotal = fleet.MembersInstance.Count( s => s?.SlotInstanceMaster.Any( q => q?.CategoryType == 30 ) ?? false ); DrumCanister.Text = $"{drumTotal}/{drumShipTotal}"; DrumCanister.Visible = config[2]; int landingCraftTotal = fleet.MembersInstance.Sum(s => s?.SlotInstanceMaster.Count(q => q?.CategoryType == 24) ?? 0); LandingCraft.Text = $"{landingCraftTotal}"; LandingCraft.Visible = config[3]; if ( ConditionSparkle.Visible = config[4] ) { var sparkleShipCount = fleet.MembersInstance.Count(s => s?.Condition > 50); if ( sparkleShipCount == 6 ) { // 全艦キラ var minCond = fleet.MembersInstance.Min(s => s.Condition); ConditionSparkle.Text = $"{Math.Ceiling((minCond - 49.0) / 3.0)}"; ConditionSparkle.ForeColor = Color.Black; } else if ( sparkleShipCount >= 4 ) { // 4隻以上キラ var minCond = fleet.MembersInstance.Where(s => s?.Condition > 50).Min(s => s.Condition); ConditionSparkle.Text = $"{Math.Ceiling((minCond - 49.0) / 3.0)}"; ConditionSparkle.ForeColor = Color.Red; } else { // キラ3隻以下 ConditionSparkle.Text = "0"; ConditionSparkle.ForeColor = Color.Red; } } }
/// <summary> /// 艦隊の状態の情報をラベルに適用します。 /// </summary> /// <param name="fleet">艦隊データ。</param> /// <param name="label">適用するラベル。</param> /// <param name="tooltip">適用するツールチップ。</param> /// <param name="prevstate">前回の状態。</param> /// <param name="timer">日時。</param> /// <returns>艦隊の状態を表す定数。</returns> public static FleetStates UpdateFleetState(FleetData fleet, ImageLabel label, ToolTip tooltip, FleetStates prevstate, ref DateTime timer) { KCDatabase db = KCDatabase.Instance; //初期化 tooltip.SetToolTip(label, null); label.BackColor = Color.Transparent; //所属艦なし if (fleet == null || fleet.Members.Count(id => id != -1) == 0) { label.Text = "所属艦なし"; label.ImageIndex = (int)ResourceManager.IconContent.FleetNoShip; return(FleetStates.NoShip); } { //入渠中 long ntime = db.Docks.Values.Max( dock => { if (dock.State == 1 && fleet.Members.Count((id => id == dock.ShipID)) > 0) { return(dock.CompletionTime.Ticks); } else { return(0); } } ); if (ntime > 0) //入渠中 { timer = new DateTime(ntime); label.Text = "入渠中 " + DateTimeHelper.ToTimeRemainString(timer); label.ImageIndex = (int)ResourceManager.IconContent.FleetDocking; tooltip.SetToolTip(label, "完了日時 : " + timer); return(FleetStates.Docking); } } if (fleet.IsInSortie) { //大破出撃中 if (fleet.MembersInstance.Count(s => (s != null && !fleet.EscapedShipList.Contains(s.MasterID) && (double)s.HPCurrent / s.HPMax <= 0.25) ) > 0) { label.Text = "!!大破進撃中!!"; label.ImageIndex = (int)ResourceManager.IconContent.FleetSortieDamaged; return(FleetStates.SortieDamaged); } else //出撃中 { label.Text = "出撃中"; label.ImageIndex = (int)ResourceManager.IconContent.FleetSortie; return(FleetStates.Sortie); } } //遠征中 if (fleet.ExpeditionState != 0) { timer = fleet.ExpeditionTime; label.Text = "遠征中 " + DateTimeHelper.ToTimeRemainString(timer); label.ImageIndex = (int)ResourceManager.IconContent.FleetExpedition; tooltip.SetToolTip(label, string.Format("{0} : {1}\r\n完了日時 : {2}", KCDatabase.Instance.Mission[fleet.ExpeditionDestination].ID, KCDatabase.Instance.Mission[fleet.ExpeditionDestination].Name, timer)); return(FleetStates.Expedition); } //大破艦あり if (fleet.MembersInstance.Count(s => (s != null && !fleet.EscapedShipList.Contains(s.MasterID) && (double)s.HPCurrent / s.HPMax <= 0.25) ) > 0) { label.Text = "大破艦あり!"; label.ImageIndex = (int)ResourceManager.IconContent.FleetDamaged; //label.BackColor = Color.LightCoral; return(FleetStates.Damaged); } //泊地修理中 { if (fleet.IsAnchorageRepairing) { label.Text = "泊地修理中 " + DateTimeHelper.ToTimeElapsedString(KCDatabase.Instance.Fleet.AnchorageRepairingTimer); label.ImageIndex = (int)ResourceManager.IconContent.FleetAnchorageRepairing; tooltip.SetToolTip(label, string.Format("開始日時 : {0}", KCDatabase.Instance.Fleet.AnchorageRepairingTimer)); return(FleetStates.AnchorageRepairing); } } //未補給 { int fuel = fleet.MembersInstance.Sum(ship => ship == null ? 0 : (int)((ship.MasterShip.Fuel - ship.Fuel) * (ship.IsMarried ? 0.85 : 1.00))); int ammo = fleet.MembersInstance.Sum(ship => ship == null ? 0 : (int)((ship.MasterShip.Ammo - ship.Ammo) * (ship.IsMarried ? 0.85 : 1.00))); int aircraft = fleet.MembersInstance.Sum( ship => { if (ship == null) { return(0); } else { int c = 0; for (int i = 0; i < ship.Slot.Count; i++) { c += ship.MasterShip.Aircraft[i] - ship.Aircraft[i]; } return(c); } }); int bauxite = aircraft * 5; if (fuel > 0 || ammo > 0 || bauxite > 0) { label.Text = "未補給"; label.ImageIndex = (int)ResourceManager.IconContent.FleetNotReplenished; tooltip.SetToolTip(label, string.Format("燃 : {0}\r\n弾 : {1}\r\nボ : {2} ({3}機)", fuel, ammo, bauxite, aircraft)); return(FleetStates.NotReplenished); } } //疲労 { int cond = fleet.MembersInstance.Min(s => s == null ? 100 : s.Condition); if (cond < Configuration.Config.Control.ConditionBorder && fleet.ConditionTime != null) { timer = (DateTime)fleet.ConditionTime; label.Text = "疲労 " + DateTimeHelper.ToTimeRemainString(timer); if (cond < 20) { label.ImageIndex = (int)ResourceManager.IconContent.ConditionVeryTired; } else if (cond < 30) { label.ImageIndex = (int)ResourceManager.IconContent.ConditionTired; } else { label.ImageIndex = (int)ResourceManager.IconContent.ConditionLittleTired; } tooltip.SetToolTip(label, string.Format("回復目安日時: {0}", timer)); return(FleetStates.Tired); } else if (cond >= 50) //戦意高揚 { label.Text = "戦意高揚!"; label.ImageIndex = (int)ResourceManager.IconContent.ConditionSparkle; tooltip.SetToolTip(label, string.Format("最低cond: {0}\r\nあと {1} 回遠征可能", cond, Math.Ceiling((cond - 49) / 3.0))); return(FleetStates.Sparkled); } } //出撃可能! { label.Text = "出撃可能!"; label.ImageIndex = (int)ResourceManager.IconContent.FleetReady; return(FleetStates.Ready); } }
/// <summary> /// 艦隊の状態の情報をラベルに適用します。 /// </summary> /// <param name="fleet">艦隊データ。</param> /// <param name="label">適用するラベル。</param> /// <param name="tooltip">適用するツールチップ。</param> /// <param name="prevstate">前回の状態。</param> /// <param name="timer">日時。</param> /// <returns>艦隊の状態を表す定数。</returns> public static FleetStates UpdateFleetState(FleetData fleet, ImageLabel label, ToolTip tooltip, FleetStates prevstate, ref DateTime timer) { KCDatabase db = KCDatabase.Instance; //初期化 tooltip.SetToolTip(label, null); label.BackColor = Color.Transparent; //所属艦なし if (fleet == null || fleet.Members.Count(id => id != -1) == 0) { label.Text = FleetRes.NoShips; label.ImageIndex = (int)ResourceManager.IconContent.FleetNoShip; return(FleetStates.NoShip); } { //入渠中 long ntime = db.Docks.Values.Max( dock => { if (dock.State == 1 && fleet.Members.Count((id => id == dock.ShipID)) > 0) { return(dock.CompletionTime.Ticks); } else { return(0); } } ); if (ntime > 0) //入渠中 { timer = new DateTime(ntime); label.Text = FleetRes.Docking + DateTimeHelper.ToTimeRemainString(timer); label.ImageIndex = (int)ResourceManager.IconContent.FleetDocking; tooltip.SetToolTip(label, FleetRes.CompletionTime + ": " + timer); return(FleetStates.Docking); } } if (fleet.IsInSortie) { //大破出撃中 if (fleet.MembersInstance.Count(s => (s != null && !fleet.EscapedShipList.Contains(s.MasterID) && (double)s.HPCurrent / s.HPMax <= 0.25) ) > 0) { label.Text = FleetRes.CriticalDamageAdvance; label.ImageIndex = (int)ResourceManager.IconContent.FleetSortieDamaged; return(FleetStates.SortieDamaged); } else //出撃中 { label.Text = FleetRes.OnSortie; label.ImageIndex = (int)ResourceManager.IconContent.FleetSortie; return(FleetStates.Sortie); } } //遠征中 if (fleet.ExpeditionState != 0) { timer = fleet.ExpeditionTime; label.Text = FleetRes.OnExped + DateTimeHelper.ToTimeRemainString(timer); label.ImageIndex = (int)ResourceManager.IconContent.FleetExpedition; tooltip.SetToolTip(label, string.Format("{0} : {1}\r\n" + FleetRes.CompletionTime + " : {2}", KCDatabase.Instance.Mission[fleet.ExpeditionDestination].ID, KCDatabase.Instance.Mission[fleet.ExpeditionDestination].Name, timer)); return(FleetStates.Expedition); } //大破艦あり if (fleet.MembersInstance.Count(s => (s != null && !fleet.EscapedShipList.Contains(s.MasterID) && (double)s.HPCurrent / s.HPMax <= 0.25) ) > 0) { label.Text = FleetRes.CriticallyDamagedShip; label.ImageIndex = (int)ResourceManager.IconContent.FleetDamaged; //label.BackColor = Color.LightCoral; return(FleetStates.Damaged); } //泊地修理中 { if (fleet.CanAnchorageRepairing && fleet.MembersInstance.Take(2 + KCDatabase.Instance.Ships[fleet[0]].SlotInstanceMaster.Count(eq => eq != null && eq.CategoryType == 31)) .Any(s => s != null && s.HPRate <1.0 && s.HPRate> 0.5 && s.RepairingDockID == -1)) { label.Text = FleetRes.AnchorageRepairing + DateTimeHelper.ToTimeElapsedString(KCDatabase.Instance.Fleet.AnchorageRepairingTimer); label.ImageIndex = (int)ResourceManager.IconContent.FleetAnchorageRepairing; tooltip.SetToolTip(label, string.Format(FleetRes.StartTime + ": {0}", KCDatabase.Instance.Fleet.AnchorageRepairingTimer)); return(FleetStates.AnchorageRepairing); } } //未補給 { int fuel = fleet.MembersInstance.Sum(ship => ship == null ? 0 : (int)((ship.FuelMax - ship.Fuel) * (ship.IsMarried ? 0.85 : 1.00))); int ammo = fleet.MembersInstance.Sum(ship => ship == null ? 0 : (int)((ship.AmmoMax - ship.Ammo) * (ship.IsMarried ? 0.85 : 1.00))); int aircraft = fleet.MembersInstance.Sum( ship => { if (ship == null) { return(0); } else { int c = 0; for (int i = 0; i < ship.Slot.Count; i++) { c += ship.MasterShip.Aircraft[i] - ship.Aircraft[i]; } return(c); } }); int bauxite = aircraft * 5; if (fuel > 0 || ammo > 0 || bauxite > 0) { label.Text = FleetRes.SupplyNeeded; label.ImageIndex = (int)ResourceManager.IconContent.FleetNotReplenished; tooltip.SetToolTip(label, string.Format(FleetRes.ResupplyTooltip, fuel, ammo, bauxite, aircraft)); return(FleetStates.NotReplenished); } } //疲労 { int cond = fleet.MembersInstance.Min(s => s == null ? 100 : s.Condition); if (cond < Configuration.Config.Control.ConditionBorder && fleet.ConditionTime != null) { timer = (DateTime)fleet.ConditionTime; label.Text = FleetRes.Fatigued + DateTimeHelper.ToTimeRemainString(timer); if (cond < 20) { label.ImageIndex = (int)ResourceManager.IconContent.ConditionVeryTired; } else if (cond < 30) { label.ImageIndex = (int)ResourceManager.IconContent.ConditionTired; } else { label.ImageIndex = (int)ResourceManager.IconContent.ConditionLittleTired; } tooltip.SetToolTip(label, string.Format(FleetRes.EstimatedRecoveryTime + ": {0}", timer)); return(FleetStates.Tired); } else if (cond >= 50) //戦意高揚 { label.Text = FleetRes.FightingSpiritHigh; label.ImageIndex = (int)ResourceManager.IconContent.ConditionSparkle; tooltip.SetToolTip(label, string.Format(FleetRes.SparkledTooltip, cond, Math.Ceiling((cond - 49) / 3.0))); return(FleetStates.Sparkled); } } //出撃可能! { label.Text = FleetRes.ReadyToSortie; label.ImageIndex = (int)ResourceManager.IconContent.FleetReady; return(FleetStates.Ready); } }
public Tuple<int, String> Predict(FleetData f) { if (f?.MembersInstance?[0] == null // 0隻 || f.IsInSortie // 出撃中 ) { // 現在、遠征に出せない return new Tuple<int, string>(-1, "遠征に出せません"); } else if (!Requirements.All(c => c.Predicate(f))) { // 失敗 return new Tuple<int, string>(0, Requirements .Where(c => !(c.Predicate(f))) .Select(c => c.Description) .Aggregate((s1, s2) => s1 + Environment.NewLine + s2)); } else if (!GreatSuccessRequirements.All(c => c.Predicate(f))) { // 成功 return new Tuple<int, string>(1, GreatSuccessRequirements .Where(c => !(c.Predicate(f))) .Select(c => c.Description) .Aggregate((s1, s2) => s1 + Environment.NewLine + s2)); } else { // 大成功 return new Tuple<int, string>(2, ""); } }
/// <summary> /// 索敵能力を求めます。「2-5式(秋)」です。 /// </summary> /// <param name="fleet">対象の艦隊。</param> public static double GetSearchingAbility_Autumn( FleetData fleet ) { double ret = 0.0; foreach ( var ship in fleet.MembersWithoutEscaped ) { if ( ship == null ) continue; ret += Math.Sqrt( ship.LOSBase ) * 1.6841056; foreach ( var eq in ship.SlotInstanceMaster ) { if ( eq == null ) continue; switch ( eq.CategoryType ) { case 7: //艦爆 ret += eq.LOS * 1.0376255; break; case 8: //艦攻 ret += eq.LOS * 1.3677954; break; case 9: //艦偵 ret += eq.LOS * 1.6592780; break; case 10: //水偵 ret += eq.LOS * 2.0000000; break; case 11: //水爆 ret += eq.LOS * 1.7787282; break; case 12: //小型電探 ret += eq.LOS * 1.0045358; break; case 13: //大型電探 ret += eq.LOS * 0.9906638; break; case 29: //探照灯 ret += eq.LOS * 0.9067950; break; } } } ret -= Math.Ceiling( KCDatabase.Instance.Admiral.Level / 5.0 ) * 5.0 * 0.6142467; return Math.Round( ret, 1 ); }
/// <summary> /// 遠征に成功する編成かどうかを判定します。 /// </summary> /// <param name="missionID">遠征ID。</param> /// <param name="fleet">対象となる艦隊。達成条件を確認したい場合は null を指定します。</param> public static MissionClearConditionResult Check(int missionID, FleetData fleet) { var result = new MissionClearConditionResult(fleet); switch (missionID) { case 1: // 練習航海 return(result .CheckFlagshipLevel(1) .CheckShipCount(2)); case 2: // 長距離練習航海 return(result .CheckFlagshipLevel(2) .CheckShipCount(4)); case 3: // 警備任務 return(result .CheckFlagshipLevel(3) .CheckShipCount(3)); case 4: // 対潜警戒任務 return(result .CheckFlagshipLevel(3) .CheckEscortFleet()); case 5: // 海上護衛任務 return(result .CheckFlagshipLevel(3) .CheckShipCount(4) .CheckEscortFleet()); case 6: // 防空射撃演習 return(result .CheckFlagshipLevel(5) .CheckShipCount(4)); case 7: // 観艦式予行 return(result .CheckFlagshipLevel(5) .CheckShipCount(6)); case 8: // 観艦式 return(result .CheckFlagshipLevel(6) .CheckShipCount(6)); case 100: // 兵站強化任務 return(result .CheckFlagshipLevel(15) .CheckShipCount(4) .CheckSmallShipCount(3)); case 101: // 海峡警備行動 return(result .CheckFlagshipLevel(20) .CheckLevelSum(144) .CheckSmallShipCount(4) .CheckAA(70) .CheckASW(180) .CheckLOS(73)); case 102: // 長時間対潜警戒 return(result .CheckFlagshipLevel(35) .CheckLevelSum(185) .CheckShipCount(5) .CheckEscortFleet() .CheckAA(162) .CheckASW(280) .CheckLOS(60)); case 9: // タンカー護衛任務 return(result .CheckFlagshipLevel(3) .CheckShipCount(4) .CheckEscortFleet()); case 10: // 強行偵察任務 return(result .CheckFlagshipLevel(3) .CheckShipCount(3) .CheckShipCountByType(ShipTypes.LightCruiser, 2)); case 11: // ボーキサイト輸送任務 return(result .CheckFlagshipLevel(6) .CheckShipCount(4) .CheckShipCountByType(ShipTypes.Destroyer, 2)); case 12: // 資源輸送任務 return(result .CheckFlagshipLevel(4) .CheckShipCount(4) .CheckShipCountByType(ShipTypes.Destroyer, 2)); case 13: // 鼠輸送作戦 return(result .CheckFlagshipLevel(5) .CheckShipCount(6) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 4)); case 14: // 包囲陸戦隊撤収作戦 return(result .CheckFlagshipLevel(6) .CheckShipCount(6) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 3)); case 15: // 囮機動部隊支援作戦 return(result .CheckFlagshipLevel(8) .CheckShipCount(6) .CheckAircraftCarrierCount(2) .CheckShipCountByType(ShipTypes.Destroyer, 2)); case 16: // 艦隊決戦援護作戦 return(result .CheckFlagshipLevel(10) .CheckShipCount(6) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 2)); case 110: // 南西方面航空偵察作戦 return(result .CheckFlagshipLevel(40) .CheckLevelSum(150) .CheckShipCount(6) .CheckShipCountByType(ShipTypes.SeaplaneTender, 1) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 2) .CheckAA(200) .CheckASW(200) .CheckLOS(140)); case 111: // 敵泊地強襲反撃作戦 return(result .CheckFlagshipLevel(50) .CheckShipCount(6) .CheckShipCountByType(ShipTypes.HeavyCruiser, 1) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 3) .CheckFirepower(360)); case 17: // 敵地偵察作戦 return(result .CheckFlagshipLevel(20) .CheckShipCount(6) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 3)); case 18: // 航空機輸送作戦 return(result .CheckFlagshipLevel(15) .CheckShipCount(6) .CheckAircraftCarrierCount(3) .CheckShipCountByType(ShipTypes.Destroyer, 2)); case 19: // 北号作戦 return(result .CheckFlagshipLevel(20) .CheckShipCount(6) .CheckShipCountByType(ShipTypes.AviationBattleship, 2) .CheckShipCountByType(ShipTypes.Destroyer, 2)); case 20: // 潜水艦哨戒任務 return(result .CheckFlagshipLevel(1) .CheckSubmarineCount(1) .CheckShipCountByType(ShipTypes.LightCruiser, 1)); case 21: // 北方鼠輸送作戦 return(result .CheckFlagshipLevel(15) .CheckLevelSum(30) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 4) .CheckEquippedShipCount(EquipmentTypes.TransportContainer, 3)); case 22: // 艦隊演習 return(result .CheckFlagshipLevel(30) .CheckLevelSum(45) .CheckShipCount(6) .CheckShipCountByType(ShipTypes.HeavyCruiser, 1) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 2)); case 23: // 航空戦艦運用演習 return(result .CheckFlagshipLevel(50) .CheckLevelSum(200) .CheckShipCount(6) .CheckShipCountByType(ShipTypes.AviationBattleship, 2) .CheckShipCountByType(ShipTypes.Destroyer, 2)); case 24: // 北方航路海上護衛 return(result .CheckFlagshipLevel(50) .CheckLevelSum(200) .CheckShipCount(6) .CheckFlagshipType(ShipTypes.LightCruiser) .CheckShipCountByType(ShipTypes.Destroyer, 4)); case 25: // 通商破壊作戦 return(result .CheckFlagshipLevel(25) .CheckShipCountByType(ShipTypes.HeavyCruiser, 2) .CheckShipCountByType(ShipTypes.Destroyer, 2)); case 26: // 敵母港空襲作戦 return(result .CheckFlagshipLevel(30) .CheckAircraftCarrierCount(1) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 2)); case 27: // 潜水艦通商破壊作戦 return(result .CheckFlagshipLevel(1) .CheckSubmarineCount(2)); case 28: // 潜水艦通商破壊作戦 return(result .CheckFlagshipLevel(30) .CheckSubmarineCount(3)); case 29: // 潜水艦派遣演習 return(result .CheckFlagshipLevel(50) .CheckSubmarineCount(3)); case 30: // 潜水艦派遣作戦 return(result .CheckFlagshipLevel(55) .CheckSubmarineCount(4)); case 31: // 海外艦との接触 return(result .CheckFlagshipLevel(60) .CheckLevelSum(200) .CheckSubmarineCount(4)); case 32: // 遠洋練習航海 return(result .CheckFlagshipLevel(5) .CheckFlagshipType(ShipTypes.TrainingCruiser) .CheckShipCountByType(ShipTypes.Destroyer, 2)); case 33: // 前衛支援任務 return(result .CheckShipCountByType(ShipTypes.Destroyer, 2)); case 34: // 艦隊決戦支援任務 return(result .CheckShipCountByType(ShipTypes.Destroyer, 2)); case 35: // MO作戦 return(result .CheckFlagshipLevel(40) .CheckShipCount(6) .CheckAircraftCarrierCount(2) .CheckShipCountByType(ShipTypes.HeavyCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 1)); case 36: // 水上機基地建設 return(result .CheckFlagshipLevel(30) .CheckShipCount(6) .CheckShipCountByType(ShipTypes.SeaplaneTender, 2) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 1)); case 37: // 東京急行 return(result .CheckFlagshipLevel(50) .CheckLevelSum(200) .CheckShipCountByType(ShipTypes.LightCruiser, 1) .CheckShipCountByType(ShipTypes.Destroyer, 5) .CheckEquippedShipCount(EquipmentTypes.TransportContainer, 3) .CheckEquipmentCount(EquipmentTypes.TransportContainer, 4)); case 38: // 東京急行(弐) return(result .CheckFlagshipLevel(65) .CheckLevelSum(240) .CheckShipCount(6) .CheckShipCountByType(ShipTypes.Destroyer, 5) .CheckEquippedShipCount(EquipmentTypes.TransportContainer, 4) .CheckEquipmentCount(EquipmentTypes.TransportContainer, 8)); case 39: // 遠洋潜水艦作戦 return(result .CheckFlagshipLevel(3) .CheckLevelSum(180) .CheckShipCountByType(ShipTypes.SubmarineTender, 1) .CheckSubmarineCount(4)); case 40: // 水上機前線輸送 return(result .CheckFlagshipLevel(25) .CheckLevelSum(150) .CheckShipCount(6) .CheckFlagshipType(ShipTypes.LightCruiser) .CheckShipCountByType(ShipTypes.SeaplaneTender, 2) .CheckShipCountByType(ShipTypes.Destroyer, 2)); default: { // イベント海域での支援遠征への対応 var mission = KCDatabase.Instance.Mission[missionID]; if (mission != null && (mission.Name == "前衛支援任務" || mission.Name == "艦隊決戦支援任務")) { return(result .CheckShipCountByType(ShipTypes.Destroyer, 2)); } return(result .AddMessage($"未対応(ID:{missionID})")); } } }
/// <summary> /// 索敵能力を求めます。「2-5式(秋)簡易式」です。 /// </summary> /// <param name="fleet">対象の艦隊。</param> public static double GetSearchingAbility_TinyAutumn( FleetData fleet ) { double ret = 0.0; foreach ( var ship in fleet.MembersWithoutEscaped ) { if ( ship == null ) continue; double cur = Math.Sqrt( ship.LOSBase ); foreach ( var eq in ship.SlotInstanceMaster ) { if ( eq == null ) continue; switch ( eq.CategoryType ) { case 7: //艦爆 cur += eq.LOS * 0.6; break; case 8: //艦攻 cur += eq.LOS * 0.8; break; case 9: //艦偵 cur += eq.LOS * 1.0; break; case 10: //水偵 cur += eq.LOS * 1.2; break; case 11: //水爆 cur += eq.LOS * 1.0; break; case 12: //小型電探 cur += eq.LOS * 0.6; break; case 13: //大型電探 cur += eq.LOS * 0.6; break; case 29: //探照灯 cur += eq.LOS * 0.5; break; default: //その他 cur += eq.LOS * 0.5; break; } } ret += Math.Floor( cur ); } ret -= Math.Floor( KCDatabase.Instance.Admiral.Level * 0.4 ); return Math.Round( ret, 1 ); }
public void Update( FleetData fleet ) { KCDatabase db = KCDatabase.Instance; if ( fleet == null ) return; Name.Text = fleet.Name; { int levelSum = fleet.MembersInstance.Sum( s => s != null ? s.Level : 0 ); int fueltotal = fleet.MembersInstance.Sum( s => s == null ? 0 : (int)Math.Floor( s.FuelMax * ( s.IsMarried ? 0.85 : 1.00 ) ) ); int ammototal = fleet.MembersInstance.Sum( s => s == null ? 0 : (int)Math.Floor( s.AmmoMax * ( s.IsMarried ? 0.85 : 1.00 ) ) ); int fuelunit = fleet.MembersInstance.Sum( s => s == null ? 0 : (int)Math.Floor( s.MasterShip.Fuel * 0.2 * ( s.IsMarried ? 0.85 : 1.00 ) ) ); int ammounit = fleet.MembersInstance.Sum( s => s == null ? 0 : (int)Math.Floor( s.MasterShip.Ammo * 0.2 * ( s.IsMarried ? 0.85 : 1.00 ) ) ); int speed = fleet.MembersWithoutEscaped.Min( s => s == null ? 10 : s.MasterShip.Speed ); var slots = fleet.MembersWithoutEscaped .Where( s => s != null ) .SelectMany( s => s.SlotInstance ) .Where( e => e != null ); var daihatsu = slots.Where( e => e.EquipmentID == 68 ); var daihatsu_tank = slots.Where( e => e.EquipmentID == 166 ); var landattacker = slots.Where( e => e.EquipmentID == 167 ); double expeditionBonus = Math.Min( daihatsu.Count() * 0.05 + daihatsu_tank.Count() * 0.02 + landattacker.Count() * 0.01, 0.20 ); ToolTipInfo.SetToolTip( Name, string.Format( GeneralRes.FleetTooltip, levelSum, (double)levelSum / Math.Max( fleet.Members.Count( id => id != -1 ), 1 ), Constants.GetSpeed( speed ), fleet.MembersInstance.Sum( s => s == null ? 0 : s.SlotInstanceMaster.Count( q => q == null ? false : q.CategoryType == 30 ) ), fleet.MembersInstance.Count( s => s == null ? false : s.SlotInstanceMaster.Any( q => q == null ? false : q.CategoryType == 30 ) ), daihatsu.Count() + daihatsu_tank.Count() + landattacker.Count(), fleet.MembersInstance.Count( s => s == null ? false : s.SlotInstanceMaster.Any( q => q == null ? false : q.CategoryType == 24 || q.CategoryType == 46 ) ), expeditionBonus + 0.01 * expeditionBonus * ( daihatsu.Sum( e => e.Level ) + daihatsu_tank.Sum( e => e.Level ) + landattacker.Sum( e => e.Level ) ) / Math.Max( daihatsu.Count() + daihatsu_tank.Count() + landattacker.Count(), 1 ), fueltotal, ammototal, fuelunit, ammounit ) ); } State = FleetData.UpdateFleetState( fleet, StateMain, ToolTipInfo, State, ref Timer ); //制空戦力計算 { int airSuperiority = fleet.GetAirSuperiority(); AirSuperiority.Text = airSuperiority.ToString(); ToolTipInfo.SetToolTip( AirSuperiority, string.Format( GeneralRes.ASTooltip, (int)( airSuperiority / 3.0 ), (int)( airSuperiority / 1.5 ), (int)( airSuperiority * 1.5 - 1 ), (int)( airSuperiority * 3.0 - 1 ) ) ); } //索敵能力計算 SearchingAbility.Text = fleet.GetSearchingAbilityString(); { StringBuilder sb = new StringBuilder(); double probStart = fleet.GetContactProbability(); var probSelect = fleet.GetContactSelectionProbability(); sb.AppendFormat( GeneralRes.LoSTooltip, fleet.GetSearchingAbilityString( 0 ), fleet.GetSearchingAbilityString( 1 ), fleet.GetSearchingAbilityString( 2 ), fleet.GetSearchingAbilityString( 3 ), probStart, probStart * 0.6 ); if ( probSelect.Count > 0 ) { sb.AppendLine( GeneralRes.SelectionRate ); foreach ( var p in probSelect.OrderBy( p => p.Key ) ) { sb.AppendFormat( " " + EncycloRes.Accuracy + "+{0} : {1:p1}\r\n", p.Key, p.Value ); } } ToolTipInfo.SetToolTip( SearchingAbility, sb.ToString() ); } }