diff --git a/Console/TeslaConsole.BattleTech/BTDamagedEvent.cs b/Console/TeslaConsole.BattleTech/BTDamagedEvent.cs
new file mode 100644
index 0000000..2f8f3a5
--- /dev/null
+++ b/Console/TeslaConsole.BattleTech/BTDamagedEvent.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+
+namespace TeslaConsole.BattleTech;
+
+///
+/// A mech took damage (MechDamagedMessage). Carries the Red Planet
+/// damage fields plus BT's damage-matrix extras: which zone was hit, whether it
+/// was destroyed, and the weapon that did it.
+///
+[Serializable]
+internal class BTDamagedEvent : BTMissionEvent
+{
+ public readonly BTPlayer Damager;
+
+ public readonly int DamageLoss;
+
+ public readonly int PointsTransfered;
+
+ public readonly int DamageZoneIndex;
+
+ public readonly bool DamageZoneDestroyed;
+
+ public readonly int WeaponIndex;
+
+ public override IEnumerable InvolvedPilots => new BTPlayer[2] { ReportingPilot, Damager };
+
+ public BTDamagedEvent(BTPlayer reportingPilot, TimeSpan missionTime, BTPlayer damager, int damageLoss, int pointsTransfered, int damageZoneIndex, bool damageZoneDestroyed, int weaponIndex)
+ : base(reportingPilot, missionTime)
+ {
+ Damager = damager;
+ DamageLoss = damageLoss;
+ PointsTransfered = pointsTransfered;
+ DamageZoneIndex = damageZoneIndex;
+ DamageZoneDestroyed = damageZoneDestroyed;
+ WeaponIndex = weaponIndex;
+ }
+
+ private BTDamagedEvent()
+ {
+ }
+}
diff --git a/Console/TeslaConsole.BattleTech/BTDeathWithoutHonorEvent.cs b/Console/TeslaConsole.BattleTech/BTDeathWithoutHonorEvent.cs
new file mode 100644
index 0000000..4e88f0c
--- /dev/null
+++ b/Console/TeslaConsole.BattleTech/BTDeathWithoutHonorEvent.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+
+namespace TeslaConsole.BattleTech;
+
+///
+/// A mech died without a killer to credit — overheating, terrain, or
+/// self-destruction (MechDeathWithoutHonorMessage).
+///
+[Serializable]
+internal class BTDeathWithoutHonorEvent : BTMissionEvent
+{
+ public override IEnumerable InvolvedPilots => new BTPlayer[1] { ReportingPilot };
+
+ public BTDeathWithoutHonorEvent(BTPlayer reportingPilot, TimeSpan missionTime)
+ : base(reportingPilot, missionTime)
+ {
+ }
+
+ private BTDeathWithoutHonorEvent()
+ {
+ }
+}
diff --git a/Console/TeslaConsole.BattleTech/BTDefaults.cs b/Console/TeslaConsole.BattleTech/BTDefaults.cs
new file mode 100644
index 0000000..939f7a0
--- /dev/null
+++ b/Console/TeslaConsole.BattleTech/BTDefaults.cs
@@ -0,0 +1,347 @@
+using System;
+using System.IO;
+using System.Windows.Forms;
+using System.Xml;
+
+namespace TeslaConsole.BattleTech;
+
+///
+/// Operator defaults for the two BattleTech game modes, persisted to
+/// BTDefaults.btd in the common app-data directory (mirrors
+/// RPDefaults/.rpd). Both modes share one defaults shape — they differ
+/// only by role, which comes from the mode, not from a default. There is no
+/// defaults dialog yet (RPDefaultsDialog's counterpart is a later phase); the
+/// file is import/export round-trippable in the meantime.
+///
+internal static class BTDefaults
+{
+ public class BattleDefaults
+ {
+ private readonly string mNodeName;
+
+ private bool mAdvancedDamage = true;
+
+ private TimeSpan mMissionLength = new TimeSpan(0, 10, 0);
+
+ private string mMapKey;
+
+ private string mVehicleKey;
+
+ private string mTimeOfDayKey;
+
+ private string mWeatherKey;
+
+ private string mExperienceKey;
+
+ private string mCamoKey;
+
+ private string mPatchKey;
+
+ private string mEmblemKey;
+
+ private int mLaunchDelay = 15;
+
+ public bool AdvancedDamage
+ {
+ get
+ {
+ return mAdvancedDamage;
+ }
+ set
+ {
+ mAdvancedDamage = value;
+ }
+ }
+
+ public TimeSpan MissionLength
+ {
+ get
+ {
+ return mMissionLength;
+ }
+ set
+ {
+ mMissionLength = value;
+ }
+ }
+
+ public string MapKey
+ {
+ get
+ {
+ return mMapKey;
+ }
+ set
+ {
+ mMapKey = value;
+ }
+ }
+
+ public string VehicleKey
+ {
+ get
+ {
+ return mVehicleKey;
+ }
+ set
+ {
+ mVehicleKey = value;
+ }
+ }
+
+ public string TimeOfDayKey
+ {
+ get
+ {
+ return mTimeOfDayKey;
+ }
+ set
+ {
+ mTimeOfDayKey = value;
+ }
+ }
+
+ public string WeatherKey
+ {
+ get
+ {
+ return mWeatherKey;
+ }
+ set
+ {
+ mWeatherKey = value;
+ }
+ }
+
+ public string ExperienceKey
+ {
+ get
+ {
+ return mExperienceKey;
+ }
+ set
+ {
+ mExperienceKey = value;
+ }
+ }
+
+ public string CamoKey
+ {
+ get
+ {
+ return mCamoKey;
+ }
+ set
+ {
+ mCamoKey = value;
+ }
+ }
+
+ public string PatchKey
+ {
+ get
+ {
+ return mPatchKey;
+ }
+ set
+ {
+ mPatchKey = value;
+ }
+ }
+
+ public string EmblemKey
+ {
+ get
+ {
+ return mEmblemKey;
+ }
+ set
+ {
+ mEmblemKey = value;
+ }
+ }
+
+ public int LaunchDelay
+ {
+ get
+ {
+ return mLaunchDelay;
+ }
+ set
+ {
+ mLaunchDelay = value;
+ }
+ }
+
+ internal BattleDefaults(string nodeName)
+ {
+ mNodeName = nodeName;
+ }
+
+ public void Save(XmlNode parrentNode)
+ {
+ XmlNode xmlNode = parrentNode.AppendChild(parrentNode.OwnerDocument.CreateElement(mNodeName));
+ xmlNode.AppendChild(xmlNode.OwnerDocument.CreateElement("AdvancedDamage")).InnerText = mAdvancedDamage.ToString();
+ xmlNode.AppendChild(xmlNode.OwnerDocument.CreateElement("MissionLength")).InnerText = mMissionLength.ToString();
+ SaveKey(xmlNode, "MapKey", mMapKey);
+ SaveKey(xmlNode, "VehicleKey", mVehicleKey);
+ SaveKey(xmlNode, "TimeOfDayKey", mTimeOfDayKey);
+ SaveKey(xmlNode, "WeatherKey", mWeatherKey);
+ SaveKey(xmlNode, "ExperienceKey", mExperienceKey);
+ SaveKey(xmlNode, "CamoKey", mCamoKey);
+ SaveKey(xmlNode, "PatchKey", mPatchKey);
+ SaveKey(xmlNode, "EmblemKey", mEmblemKey);
+ xmlNode.AppendChild(xmlNode.OwnerDocument.CreateElement("LaunchDelay")).InnerText = mLaunchDelay.ToString();
+ }
+
+ private static void SaveKey(XmlNode parentNode, string elementName, string value)
+ {
+ if (!string.IsNullOrEmpty(value))
+ {
+ parentNode.AppendChild(parentNode.OwnerDocument.CreateElement(elementName)).InnerText = value;
+ }
+ }
+
+ public void Parse(XmlNode scenarioNode)
+ {
+ foreach (XmlNode childNode in scenarioNode.ChildNodes)
+ {
+ switch (childNode.Name)
+ {
+ case "AdvancedDamage":
+ {
+ if (bool.TryParse(childNode.InnerText, out var result2))
+ {
+ mAdvancedDamage = result2;
+ }
+ break;
+ }
+ case "MissionLength":
+ {
+ if (TimeSpan.TryParse(childNode.InnerText, out var result3))
+ {
+ mMissionLength = result3;
+ }
+ break;
+ }
+ case "MapKey":
+ ParseKey(childNode, ref mMapKey);
+ break;
+ case "VehicleKey":
+ ParseKey(childNode, ref mVehicleKey);
+ break;
+ case "TimeOfDayKey":
+ ParseKey(childNode, ref mTimeOfDayKey);
+ break;
+ case "WeatherKey":
+ ParseKey(childNode, ref mWeatherKey);
+ break;
+ case "ExperienceKey":
+ ParseKey(childNode, ref mExperienceKey);
+ break;
+ case "CamoKey":
+ ParseKey(childNode, ref mCamoKey);
+ break;
+ case "PatchKey":
+ ParseKey(childNode, ref mPatchKey);
+ break;
+ case "EmblemKey":
+ ParseKey(childNode, ref mEmblemKey);
+ break;
+ case "LaunchDelay":
+ {
+ if (int.TryParse(childNode.InnerText, out var result))
+ {
+ mLaunchDelay = result;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ private static void ParseKey(XmlNode node, ref string field)
+ {
+ if (!string.IsNullOrEmpty(node.InnerText))
+ {
+ field = node.InnerText;
+ }
+ }
+ }
+
+ public const string FreeForAllNode = "FreeForAllDefaults";
+
+ public const string NoReturnNode = "NoReturnDefaults";
+
+ private static readonly string sDefaultsFilePath;
+
+ private static readonly BattleDefaults sFreeForAll;
+
+ private static readonly BattleDefaults sNoReturn;
+
+ public static BattleDefaults FreeForAll => sFreeForAll;
+
+ public static BattleDefaults NoReturn => sNoReturn;
+
+ static BTDefaults()
+ {
+ sDefaultsFilePath = Path.Combine(Program.GetCommonAppDataDirectory(), "BTDefaults.btd");
+ sFreeForAll = new BattleDefaults("FreeForAllDefaults");
+ sNoReturn = new BattleDefaults("NoReturnDefaults");
+ if (File.Exists(sDefaultsFilePath))
+ {
+ try
+ {
+ Import(sDefaultsFilePath);
+ }
+ catch (Exception)
+ {
+ MessageBox.Show("The BattleTech defaults file appears to be corrupt. Please delete it or export a new one to replace it.", "Error Loading BattleTech Defaults!", MessageBoxButtons.OK);
+ }
+ }
+ }
+
+ public static void Import(string fileName)
+ {
+ XmlDocument xmlDocument = new XmlDocument();
+ xmlDocument.Load(fileName);
+ foreach (XmlNode childNode in xmlDocument.DocumentElement.ChildNodes)
+ {
+ switch (childNode.Name)
+ {
+ case "FreeForAllDefaults":
+ sFreeForAll.Parse(childNode);
+ break;
+ case "NoReturnDefaults":
+ sNoReturn.Parse(childNode);
+ break;
+ }
+ }
+ }
+
+ public static void Save()
+ {
+ try
+ {
+ Export(sDefaultsFilePath);
+ }
+ catch (Exception)
+ {
+ MessageBox.Show("The BattleTech defaults file could not be saved. These defaults will only be remembered until the application is closed.", "Error Saving BattleTech Defaults!", MessageBoxButtons.OK);
+ }
+ }
+
+ public static void Export(string filePath)
+ {
+ XmlDocument xmlDocument = new XmlDocument();
+ xmlDocument.AppendChild(xmlDocument.CreateElement("BTDefaults"));
+ sFreeForAll.Save(xmlDocument.DocumentElement);
+ sNoReturn.Save(xmlDocument.DocumentElement);
+ string directoryName = Path.GetDirectoryName(filePath);
+ if (!Directory.Exists(directoryName))
+ {
+ Directory.CreateDirectory(directoryName);
+ }
+ xmlDocument.Save(filePath);
+ }
+}
diff --git a/Console/TeslaConsole.BattleTech/BTGame.cs b/Console/TeslaConsole.BattleTech/BTGame.cs
new file mode 100644
index 0000000..7ed9911
--- /dev/null
+++ b/Console/TeslaConsole.BattleTech/BTGame.cs
@@ -0,0 +1,1591 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+using Munga.Net;
+using WeifenLuo.WinFormsUI.Docking;
+
+namespace TeslaConsole.BattleTech;
+
+///
+/// The BattleTech game pane: mission-configuration UI plus the run/stop state
+/// loop that drives each pod's . A close mirror of
+/// TeslaConsole.RedPlanet.RPGame — same GameStateData/state machine/
+/// NetworkScan engine — with the BT differences: the pod app is
+/// , the grid carries the BT pilot fields
+/// (mech/camo/patch/badge/experience), Advanced Damage replaces Score
+/// Compression, and the in-match events are the Mech* messages. Free For All
+/// and No Return share this one pane; the mode only selects the pilots' role.
+/// The score-sheet printing controls (RPGame's Auto Print / Print Last
+/// Mission) are deferred until a BT print document exists; results are still
+/// recorded and saved as .btm files.
+///
+internal class BTGame : DockContent
+{
+ private class DragDropData
+ {
+ public int StartRow;
+
+ public int EndRow;
+
+ public bool RightClick;
+
+ public DragDropData(int startRow, bool rightClick)
+ {
+ StartRow = startRow;
+ RightClick = rightClick;
+ }
+ }
+
+ private class GameStateData
+ {
+ public bool EggMessageSent;
+
+ public bool RunMessageSent;
+
+ public bool AbortMessageSent;
+
+ public bool StopMessageSent;
+
+ public bool PodAppearsReset;
+
+ public void Reset()
+ {
+ EggMessageSent = (RunMessageSent = (AbortMessageSent = (StopMessageSent = (PodAppearsReset = false))));
+ }
+ }
+
+ private enum BTGameState
+ {
+ Idle,
+ Load,
+ AutoTransCount,
+ Run,
+ Reset
+ }
+
+ private static readonly Color sDataLockedColor = Color.LightGray;
+
+ private static readonly Random sRand = new Random();
+
+ private Site mSite;
+
+ private readonly bool mNoReturnMode;
+
+ private readonly string mGameName;
+
+ private EggFileMessage[] mEggFileMessages;
+
+ private BTGameState mCurrentState;
+
+ private BTGameState mRequestedState;
+
+ private TimeSpan mMissionLength;
+
+ private DateTime mGameStart;
+
+ private bool mNormalMissionEnd;
+
+ private bool mProcessingMissionEndStateChangeReq;
+
+ private int mRemainingUntilTranslocate;
+
+ private Dictionary mGameStateData = new Dictionary();
+
+ private BTMissionRecorder mMissionRecorder;
+
+ private Dictionary mMissionPlayers;
+
+ private LogOutputWindow mLogWindow;
+
+ private BTMissionResults mLastMissionResults;
+
+ private IContainer components;
+
+ private GroupBox mMissionPropertiesGroupBox;
+
+ private Label mIssuesLabel;
+
+ private Label mMissionLengthDisplayLabel;
+
+ private Label mMissionLengthTextLabel;
+
+ private CheckBox mAdvancedDamage;
+
+ private ComboBox mWeather;
+
+ private ComboBox mMap;
+
+ private ComboBox mTimeOfDay;
+
+ private Label mTimeOfDayLabel;
+
+ private Label mWeatherLabel;
+
+ private Label mMapLabel;
+
+ private GroupBox mPilotsGroupBox;
+
+ private TableLayoutPanel mMissionPropertiesTable;
+
+ private DataGridView mPilotsDataGrid;
+
+ private Button mGoButton;
+
+ private ContextMenuStrip mDragDropContextMenu;
+
+ private ToolStripMenuItem mSwapPilots;
+
+ private ToolStripMenuItem mShiftPilots;
+
+ private Timer mNetworkTimer;
+
+ private DataGridViewCheckBoxColumn mEnabledColumn;
+
+ private DataGridViewImageColumn mStatusIconColumn;
+
+ private DataGridViewTextBoxColumn mStatusTextColumn;
+
+ private DataGridViewTextBoxColumn mPilotColumn;
+
+ private DataGridViewComboBoxColumn mVehicleColumn;
+
+ private DataGridViewComboBoxColumn mColorColumn;
+
+ private DataGridViewComboBoxColumn mPatchColumn;
+
+ private DataGridViewComboBoxColumn mBadgeColumn;
+
+ private DataGridViewComboBoxColumn mExperienceColumn;
+
+ private ContextMenuStrip mResetContextMenu;
+
+ private ToolStripMenuItem resetToolStripMenuItem;
+
+ private CheckBox mAutoTranslocateCheckbox;
+
+ private Button mRandomMap;
+
+ private Button mRandomWeather;
+
+ private Button mRandomTimeOfDay;
+
+ private TextBox mMissionLengthTextBox;
+
+ private Timer tmrAutoTranslocate;
+
+ private string GameStatusText
+ {
+ set
+ {
+ if (string.IsNullOrEmpty(value))
+ {
+ base.TabText = (Text = mGameName);
+ }
+ else
+ {
+ base.TabText = (Text = $"{mGameName} [{value}]");
+ }
+ }
+ }
+
+ private BTDefaults.BattleDefaults ModeDefaults => mNoReturnMode ? BTDefaults.NoReturn : BTDefaults.FreeForAll;
+
+ private BTRole ModeRole => BTConfig.FreeForAll.Roles[mNoReturnMode ? "NoReturn" : "Default"];
+
+ private BTGame()
+ {
+ InitializeComponent();
+ }
+
+ internal BTGame(Site site, bool noReturnMode)
+ : this()
+ {
+ mNoReturnMode = noReturnMode;
+ mSite = site;
+ SuspendLayout();
+ mGameName = (mNoReturnMode ? "BattleTech No Return" : "BattleTech Free For All");
+ GameStatusText = null;
+ BTScenario scenario = BTConfig.FreeForAll;
+ BTDefaults.BattleDefaults defaults = ModeDefaults;
+ int selectedIndex;
+ int num = (selectedIndex = 0);
+ string text = defaults.MapKey;
+ mMap.DisplayMember = "Name";
+ mMap.ValueMember = "Key";
+ foreach (BTMap item in scenario.Maps.Values)
+ {
+ mMap.Items.Add(item);
+ if (item.Key == text)
+ {
+ selectedIndex = num;
+ }
+ num++;
+ }
+ mMap.SelectedIndex = selectedIndex;
+ num = (selectedIndex = 0);
+ text = defaults.WeatherKey;
+ mWeather.DisplayMember = "Name";
+ mWeather.ValueMember = "Key";
+ foreach (BTWeather item2 in scenario.Weather.Values)
+ {
+ mWeather.Items.Add(item2);
+ if (item2.Key == text)
+ {
+ selectedIndex = num;
+ }
+ num++;
+ }
+ mWeather.SelectedIndex = selectedIndex;
+ num = (selectedIndex = 0);
+ text = defaults.TimeOfDayKey;
+ mTimeOfDay.DisplayMember = "Value";
+ mTimeOfDay.ValueMember = "Key";
+ foreach (KeyValuePair item3 in scenario.TimesOfDay)
+ {
+ mTimeOfDay.Items.Add(item3);
+ if (item3.Key == text)
+ {
+ selectedIndex = num;
+ }
+ num++;
+ }
+ mTimeOfDay.SelectedIndex = selectedIndex;
+ mAdvancedDamage.Checked = defaults.AdvancedDamage;
+ mMissionLengthTextBox.Text = defaults.MissionLength.TotalMinutes.ToString();
+ num = (selectedIndex = 0);
+ text = defaults.VehicleKey;
+ mVehicleColumn.DisplayMember = "Name";
+ mVehicleColumn.ValueMember = "Key";
+ foreach (BTVehicle item4 in scenario.Vehicles.Values)
+ {
+ mVehicleColumn.Items.Add(item4);
+ if (item4.Key == text)
+ {
+ selectedIndex = num;
+ }
+ num++;
+ }
+ mVehicleColumn.Tag = selectedIndex;
+ SetupKeyValueColumn(mColorColumn, scenario.Colors, defaults.CamoKey);
+ SetupKeyValueColumn(mPatchColumn, scenario.Patches, defaults.PatchKey);
+ SetupKeyValueColumn(mBadgeColumn, scenario.Badges, defaults.EmblemKey);
+ SetupKeyValueColumn(mExperienceColumn, scenario.Experiences, defaults.ExperienceKey);
+ List> list = new List>();
+ foreach (Squad squad in mSite.Squads)
+ {
+ foreach (Pod pod in squad.Pods)
+ {
+ if (pod.HostType == HostType.GameMachineHostType)
+ {
+ BuildPodRow(squad, pod);
+ }
+ else if (pod.HostType == HostType.MissionReviewHostType)
+ {
+ list.Add(new Tuple(squad, pod));
+ }
+ }
+ }
+ foreach (Tuple item5 in list)
+ {
+ BuildPodRow(item5.A, item5.B);
+ }
+ CheckAllValues();
+ ResumeLayout();
+ }
+
+ private static void SetupKeyValueColumn(DataGridViewComboBoxColumn column, Dictionary options, string defaultKey)
+ {
+ int num = 0;
+ int selectedIndex = 0;
+ column.DisplayMember = "Value";
+ column.ValueMember = "Key";
+ foreach (KeyValuePair option in options)
+ {
+ column.Items.Add(option);
+ if (option.Key == defaultKey)
+ {
+ selectedIndex = num;
+ }
+ num++;
+ }
+ column.Tag = selectedIndex;
+ }
+
+ private void BuildPodRow(Squad squad, Pod pod)
+ {
+ int index = mPilotsDataGrid.Rows.Add();
+ DataGridViewRow row = mPilotsDataGrid.Rows[index];
+ row.Tag = pod;
+ row.HeaderCell.Value = $"{squad.Name} - {pod.Name}";
+ row.Cells[mEnabledColumn.Index].Value = false;
+ if (pod.HostType == HostType.GameMachineHostType)
+ {
+ row.Cells[mVehicleColumn.Index].Value = mVehicleColumn.Items[(int)mVehicleColumn.Tag];
+ row.Cells[mColorColumn.Index].Value = mColorColumn.Items[(int)mColorColumn.Tag];
+ row.Cells[mPatchColumn.Index].Value = mPatchColumn.Items[(int)mPatchColumn.Tag];
+ row.Cells[mBadgeColumn.Index].Value = mBadgeColumn.Items[(int)mBadgeColumn.Tag];
+ row.Cells[mExperienceColumn.Index].Value = mExperienceColumn.Items[(int)mExperienceColumn.Tag];
+ }
+ else
+ {
+ row.Cells[mVehicleColumn.Index].Value = "";
+ row.Cells[mColorColumn.Index].Value = "";
+ row.Cells[mPatchColumn.Index].Value = "";
+ row.Cells[mBadgeColumn.Index].Value = "";
+ row.Cells[mExperienceColumn.Index].Value = "";
+ row.Cells[mPilotColumn.Index].ReadOnly = true;
+ row.Cells[mVehicleColumn.Index].ReadOnly = true;
+ row.Cells[mColorColumn.Index].ReadOnly = true;
+ row.Cells[mPatchColumn.Index].ReadOnly = true;
+ row.Cells[mBadgeColumn.Index].ReadOnly = true;
+ row.Cells[mExperienceColumn.Index].ReadOnly = true;
+ }
+ mGameStateData[pod.MungaGame] = new GameStateData();
+ SetPodStatus(row, pod.MungaGame);
+ pod.MungaGame.OnPodStatusUpdated += delegate(object sender, EventArgs e)
+ {
+ if (!base.IsDisposed)
+ {
+ SetPodStatus(row, (MungaGame)sender);
+ }
+ };
+ }
+
+ protected override void OnClosing(CancelEventArgs e)
+ {
+ if (mCurrentState != 0 && MessageBox.Show("A BattleTech game controlled by this window is currently in progress. If you choose to continue, the game will end immediately. Are you sure you wish to procede?", "Game Running", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
+ {
+ e.Cancel = true;
+ }
+ else
+ {
+ base.OnClosing(e);
+ }
+ }
+
+ protected override void OnClosed(EventArgs e)
+ {
+ foreach (Squad squad in mSite.Squads)
+ {
+ foreach (Pod pod in squad.Pods)
+ {
+ ForcePodRelease(pod.MungaGame);
+ pod.MungaGame.ReleaseRequest(this);
+ }
+ }
+ base.OnClosed(e);
+ }
+
+ private static string GetStringOrKey(DataGridViewCell cell)
+ {
+ if (cell.Value is string)
+ {
+ return (string)cell.Value;
+ }
+ return ((KeyValuePair)cell.Value).Key;
+ }
+
+ private void NetworkScan(object sender, EventArgs e)
+ {
+ if (mCurrentState == BTGameState.Run && mRequestedState == BTGameState.Run && !mProcessingMissionEndStateChangeReq)
+ {
+ mProcessingMissionEndStateChangeReq = true;
+ TimeSpan timeRemaining = mMissionLength - (DateTime.Now - mGameStart);
+ if (timeRemaining.Ticks < 0)
+ {
+ mNormalMissionEnd = true;
+ RequestState(BTGameState.Idle);
+ timeRemaining = new TimeSpan(0L);
+ }
+ string gameStatusText = FormatTimeRemaining(timeRemaining);
+ mMissionLengthDisplayLabel.Text = gameStatusText;
+ GameStatusText = gameStatusText;
+ mProcessingMissionEndStateChangeReq = false;
+ }
+ bool flag = true;
+ foreach (DataGridViewRow item in (IEnumerable)mPilotsDataGrid.Rows)
+ {
+ Pod pod = (Pod)item.Tag;
+ if (mRequestedState == BTGameState.Idle)
+ {
+ GetPodReleased(pod.MungaGame);
+ if (pod.MungaGame.IsOwner(this))
+ {
+ flag = false;
+ }
+ }
+ else if (!(bool)item.Cells[mEnabledColumn.Index].Value)
+ {
+ if (pod.MungaGame.IsOwner(this))
+ {
+ GetPodReleased(pod.MungaGame);
+ }
+ }
+ else
+ {
+ GameStateData gameStateData = mGameStateData[pod.MungaGame];
+ if (!gameStateData.PodAppearsReset)
+ {
+ if (!pod.MungaGame.IsOwned)
+ {
+ pod.MungaGame.TakeOwnership(this);
+ }
+ if (!pod.MungaGame.IsOwner(this))
+ {
+ flag = false;
+ }
+ else if (!pod.MungaGame.IsPodOperational(ApplicationID.BTL4))
+ {
+ flag = false;
+ }
+ else if (mRequestedState == BTGameState.Load)
+ {
+ switch (pod.MungaGame.AppState.Value)
+ {
+ case ApplicationState.RunningMission:
+ if (!gameStateData.AbortMessageSent)
+ {
+ pod.MungaGame.Send(0, 1, new AbortMissionMessage(0));
+ gameStateData.AbortMessageSent = true;
+ }
+ break;
+ case ApplicationState.WaitingForEgg:
+ if (!pod.MungaGame.EggAcknowledged && pod.MungaGame.EggDelayTimer < DateTime.Now && pod.MungaGame.EggSent.AddSeconds(5.0) < DateTime.Now)
+ {
+ LogMessage("Egg Sent.");
+ EggFileMessage[] array = mEggFileMessages;
+ foreach (EggFileMessage message in array)
+ {
+ pod.MungaGame.Send(0, 1, message);
+ }
+ pod.MungaGame.EggSent = DateTime.Now;
+ }
+ break;
+ }
+ if (!pod.MungaGame.IsPodAppState(ApplicationID.BTL4, ApplicationState.WaitingForLaunch))
+ {
+ flag = false;
+ }
+ }
+ else if (mRequestedState == BTGameState.Run)
+ {
+ switch (pod.MungaGame.AppState.Value)
+ {
+ case ApplicationState.WaitingForEgg:
+ gameStateData.PodAppearsReset = true;
+ GetPodReleased(pod.MungaGame);
+ break;
+ case ApplicationState.WaitingForLaunch:
+ if (!gameStateData.RunMessageSent)
+ {
+ pod.MungaGame.Send(0, 1, new RunMissionMessage());
+ gameStateData.RunMessageSent = true;
+ }
+ break;
+ }
+ if (!pod.MungaGame.IsPodAppState(ApplicationID.BTL4, ApplicationState.RunningMission))
+ {
+ flag = false;
+ }
+ }
+ }
+ }
+ if (!pod.MungaGame.IsOwner(this))
+ {
+ continue;
+ }
+ for (MetaMessage metaMessage = pod.MungaGame.Receive(); metaMessage != null; metaMessage = pod.MungaGame.Receive())
+ {
+ LogMessage(pod, metaMessage);
+ if (metaMessage.Message is MechDamagedMessage)
+ {
+ MechDamagedMessage mechDamagedMessage = (MechDamagedMessage)metaMessage.Message;
+ mMissionRecorder.PlayerDamaged(mMissionPlayers[mechDamagedMessage.PlayerHostID], mMissionPlayers[mechDamagedMessage.DamagerHostID], mechDamagedMessage.DamageLoss, mechDamagedMessage.PointsTransfered, mechDamagedMessage.DamageZoneIndex, mechDamagedMessage.DamageZoneDestroyed, mechDamagedMessage.WeaponIndex);
+ }
+ else if (metaMessage.Message is MechKilledMessage)
+ {
+ MechKilledMessage mechKilledMessage = (MechKilledMessage)metaMessage.Message;
+ mMissionRecorder.PlayerKilled(mMissionPlayers[mechKilledMessage.PlayerHostID], mMissionPlayers[mechKilledMessage.KillerHostID]);
+ }
+ else if (metaMessage.Message is MechDeathWithoutHonorMessage)
+ {
+ MechDeathWithoutHonorMessage mechDeathWithoutHonorMessage = (MechDeathWithoutHonorMessage)metaMessage.Message;
+ mMissionRecorder.PlayerDeathWithoutHonor(mMissionPlayers[mechDeathWithoutHonorMessage.PlayerHostID]);
+ }
+ else if (metaMessage.Message is MechScoreUpdateMessage)
+ {
+ MechScoreUpdateMessage mechScoreUpdateMessage = (MechScoreUpdateMessage)metaMessage.Message;
+ mMissionRecorder.PlayerScoreUpdate(mMissionPlayers[mechScoreUpdateMessage.PlayerHostID], mechScoreUpdateMessage.PlayerScore);
+ }
+ else if (metaMessage.Message is EndMissionMessage)
+ {
+ EndMissionMessage endMissionMessage = (EndMissionMessage)metaMessage.Message;
+ mMissionRecorder.PlayerFinalScore(mMissionPlayers[endMissionMessage.PlayerHostID], endMissionMessage.FinalScore);
+ }
+ }
+ }
+ if (mCurrentState != mRequestedState && flag)
+ {
+ StateChangeApproved();
+ }
+ }
+
+ private void LogMessage(string message)
+ {
+ if (mLogWindow != null && !mLogWindow.IsDisposed)
+ {
+ mLogWindow.LogMessage(message);
+ }
+ }
+
+ private void LogMessage(Pod pod, MetaMessage msg)
+ {
+ if (mLogWindow == null || mLogWindow.IsDisposed)
+ {
+ return;
+ }
+ if (msg.Message is AcknowledgeEggFileMessage)
+ {
+ mLogWindow.LogMessage("{0}: {1}: {2}: Egg ACK", pod.Name, msg.Header.ClientID, msg.Message.GetType().Name);
+ }
+ else if (msg.Message is EndMissionMessage)
+ {
+ EndMissionMessage endMissionMessage = (EndMissionMessage)msg.Message;
+ mLogWindow.LogMessage("{0}: {1}: {2}: Final Score {3}", pod.Name, msg.Header.ClientID, msg.Message.GetType().Name, endMissionMessage.FinalScore);
+ }
+ else if (msg.Message is ReadyToRunMessage)
+ {
+ mLogWindow.LogMessage("{0}: {1}: {2}", pod.Name, msg.Header.ClientID, msg.Message.GetType().Name);
+ }
+ else if (msg.Message is MechKilledMessage)
+ {
+ MechKilledMessage mechKilledMessage = (MechKilledMessage)msg.Message;
+ mLogWindow.LogMessage("{0}: {1}: {2}: {3} killed {4}", pod.Name, msg.Header.ClientID, msg.Message.GetType().Name, mechKilledMessage.KillerHostID, mechKilledMessage.PlayerHostID);
+ }
+ else if (msg.Message is MechDeathWithoutHonorMessage)
+ {
+ mLogWindow.LogMessage("{0}: {1}: {2}: {3} died without honor", pod.Name, msg.Header.ClientID, msg.Message.GetType().Name, ((MechDeathWithoutHonorMessage)msg.Message).PlayerHostID);
+ }
+ else if (msg.Message is MechScoreUpdateMessage)
+ {
+ mLogWindow.LogMessage("{0}: {1}: {2}: {3} Score = {4}", pod.Name, msg.Header.ClientID, msg.Message.GetType().Name, ((MechScoreUpdateMessage)msg.Message).PlayerHostID, ((MechScoreUpdateMessage)msg.Message).PlayerScore);
+ }
+ else if (msg.Message is BTTeamScoreUpdateMessage)
+ {
+ mLogWindow.LogMessage("{0}: {1}: {2}: Team {3} Score = {4}", pod.Name, msg.Header.ClientID, msg.Message.GetType().Name, ((BTTeamScoreUpdateMessage)msg.Message).TeamID, ((BTTeamScoreUpdateMessage)msg.Message).TeamScore);
+ }
+ else if (msg.Message is MechDamagedMessage)
+ {
+ MechDamagedMessage mechDamagedMessage = (MechDamagedMessage)msg.Message;
+ if (mechDamagedMessage.DamageLoss != 0)
+ {
+ mLogWindow.LogMessage("{0}: {1}: {2}: {3} Damaged {4} For {5} Points.", pod.Name, msg.Header.ClientID, msg.Message.GetType().Name, mechDamagedMessage.DamagerHostID, mechDamagedMessage.PlayerHostID, mechDamagedMessage.PointsTransfered);
+ }
+ }
+ }
+
+ private string FormatTimeRemaining(TimeSpan timeRemaining)
+ {
+ long num = (long)timeRemaining.TotalMinutes;
+ long num2 = (long)(timeRemaining.TotalSeconds - (double)(num * 60));
+ return $"{num:00}:{num2:00}";
+ }
+
+ private void ForcePodRelease(MungaGame munga)
+ {
+ GetPodReleased(munga);
+ munga.ReleaseOwnership(this);
+ }
+
+ private void GetPodReleased(MungaGame munga)
+ {
+ if (!munga.IsOwner(this))
+ {
+ return;
+ }
+ if (!munga.IsPodOperational(ApplicationID.BTL4))
+ {
+ munga.ReleaseOwnership(this);
+ return;
+ }
+ GameStateData gameStateData = mGameStateData[munga];
+ switch (munga.AppState.Value)
+ {
+ case ApplicationState.WaitingForLaunch:
+ if (!gameStateData.AbortMessageSent)
+ {
+ munga.Send(0, 1, new AbortMissionMessage(0));
+ gameStateData.AbortMessageSent = true;
+ }
+ break;
+ case ApplicationState.RunningMission:
+ if (!gameStateData.StopMessageSent)
+ {
+ munga.Send(0, 1, new StopMissionMessage(0));
+ gameStateData.StopMessageSent = true;
+ }
+ break;
+ case ApplicationState.WaitingForEgg:
+ munga.ReleaseOwnership(this);
+ break;
+ case ApplicationState.LoadingMission:
+ case ApplicationState.LaunchingMission:
+ break;
+ }
+ }
+
+ private void StateChangeApproved()
+ {
+ switch (mRequestedState)
+ {
+ case BTGameState.Idle:
+ EndMission();
+ GameStatusText = null;
+ mGoButton.Text = "Load";
+ mEggFileMessages = null;
+ SwitchControlsMode(editMode: true);
+ CheckAllValues();
+ mCurrentState = BTGameState.Idle;
+ break;
+ case BTGameState.Load:
+ GameStatusText = "Loaded";
+ mGoButton.Text = "Run Mission";
+ mGoButton.Enabled = true;
+ foreach (GameStateData value in mGameStateData.Values)
+ {
+ value.Reset();
+ }
+ mCurrentState = BTGameState.Load;
+ if (mAutoTranslocateCheckbox.Checked)
+ {
+ int num = ModeDefaults.LaunchDelay;
+ if (num == 0)
+ {
+ mGoButton.Text = "Launching...";
+ GameStatusText = "Launching...";
+ mGoButton.Enabled = false;
+ RequestState(BTGameState.Run);
+ }
+ else
+ {
+ mGoButton.Text = $"Launching in {num}...";
+ GameStatusText = mGoButton.Text;
+ mRemainingUntilTranslocate = num;
+ tmrAutoTranslocate.Start();
+ }
+ }
+ break;
+ case BTGameState.Run:
+ mGameStart = DateTime.Now;
+ mGoButton.Text = "Stop Mission";
+ mGoButton.Enabled = true;
+ mCurrentState = BTGameState.Run;
+ mMissionRecorder.SetMissionStart();
+ mMissionLengthDisplayLabel.ForeColor = Color.DarkGreen;
+ break;
+ case BTGameState.AutoTransCount:
+ break;
+ }
+ }
+
+ private void mGoButton_Click(object sender, EventArgs e)
+ {
+ switch (mCurrentState)
+ {
+ case BTGameState.Idle:
+ RequestState(BTGameState.Load);
+ break;
+ case BTGameState.Load:
+ tmrAutoTranslocate.Stop();
+ RequestState(BTGameState.Run);
+ break;
+ case BTGameState.Run:
+ mNormalMissionEnd = false;
+ RequestState(BTGameState.Idle);
+ break;
+ case BTGameState.AutoTransCount:
+ break;
+ }
+ }
+
+ private void resetToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ RequestState(BTGameState.Reset);
+ }
+
+ private void RequestState(BTGameState state)
+ {
+ switch (state)
+ {
+ case BTGameState.Load:
+ {
+ mMissionLength = ParseMissionLength();
+ string key = ((BTMap)mMap.SelectedItem).Key;
+ string key2 = ((KeyValuePair)mTimeOfDay.SelectedItem).Key;
+ BTWeather bTWeather = (BTWeather)mWeather.SelectedItem;
+ BTFreeForAllMission bTMission = new BTFreeForAllMission(key, key2, bTWeather.Key, bTWeather.Temperature, mMissionLength);
+ BTRole role = ModeRole;
+ mMissionRecorder = new BTMissionRecorder(bTMission);
+ mMissionPlayers = new Dictionary();
+ int num = 2;
+ foreach (DataGridViewRow item in (IEnumerable)mPilotsDataGrid.Rows)
+ {
+ if (!(bool)item.Cells[mEnabledColumn.Index].Value)
+ {
+ continue;
+ }
+ Pod pod = (Pod)item.Tag;
+ if (pod.HostType == HostType.GameMachineHostType)
+ {
+ string value = (string)item.Cells[mPilotColumn.Index].Value;
+ BTPlayer bTPlayer = new BTPlayer(pod.IPAddress.ToString(), value, (item.Cells[mVehicleColumn.Index].Value is string) ? ((string)item.Cells[mVehicleColumn.Index].Value) : ((BTVehicle)item.Cells[mVehicleColumn.Index].Value).Key, GetStringOrKey(item.Cells[mColorColumn.Index]), GetStringOrKey(item.Cells[mPatchColumn.Index]), GetStringOrKey(item.Cells[mBadgeColumn.Index]), GetStringOrKey(item.Cells[mExperienceColumn.Index]), role, mAdvancedDamage.Checked);
+ bTMission.BattlePlayers.Add(bTPlayer);
+ mMissionPlayers.Add(num++, bTPlayer);
+ PilotNameCache.PilotNames.Add(value);
+ }
+ else
+ {
+ bTMission.Cameras.Add(new BTCamera(pod.IPAddress.ToString(), pod.HostType));
+ }
+ }
+ mEggFileMessages = bTMission.ToEggFileMessages();
+ mRequestedState = BTGameState.Load;
+ SwitchControlsMode(editMode: false);
+ GameStatusText = "Loading...";
+ mGoButton.Text = "Loading...";
+ mGoButton.Enabled = false;
+ break;
+ }
+ case BTGameState.Run:
+ mRequestedState = BTGameState.Run;
+ GameStatusText = "Launching...";
+ mGoButton.Text = "Launching...";
+ mGoButton.Enabled = false;
+ break;
+ case BTGameState.Idle:
+ mRequestedState = BTGameState.Idle;
+ mMissionLengthDisplayLabel.ForeColor = Color.Red;
+ GameStatusText = "Stopping Game...";
+ mGoButton.Text = "Stopping Game...";
+ mGoButton.Enabled = false;
+ break;
+ case BTGameState.Reset:
+ foreach (Squad squad in mSite.Squads)
+ {
+ foreach (Pod pod2 in squad.Pods)
+ {
+ ForcePodRelease(pod2.MungaGame);
+ }
+ }
+ mRequestedState = BTGameState.Idle;
+ StateChangeApproved();
+ break;
+ case BTGameState.AutoTransCount:
+ break;
+ }
+ }
+
+ private void EndMission()
+ {
+ try
+ {
+ mLastMissionResults = mMissionRecorder.EndMission(mNormalMissionEnd ? mMissionLength : (DateTime.Now - mGameStart));
+ try
+ {
+ mLastMissionResults.Save();
+ }
+ catch (Exception ex)
+ {
+ if (Debugger.IsAttached)
+ {
+ throw;
+ }
+ Program.LogExceptionAndShowDialog(ex, "Mission results failed to save.", "Error Saving Mission Results");
+ }
+ }
+ catch (Exception ex2)
+ {
+ if (Debugger.IsAttached)
+ {
+ throw;
+ }
+ Program.LogExceptionAndShowDialog(ex2, "Failed to create mission results.", "Error Creating Mission Results");
+ }
+ mMissionRecorder = null;
+ mMissionPlayers = null;
+ }
+
+ private void SwitchControlsMode(bool editMode)
+ {
+ mMap.Enabled = editMode;
+ mWeather.Enabled = editMode;
+ mTimeOfDay.Enabled = editMode;
+ mAdvancedDamage.Enabled = editMode;
+ mRandomMap.Enabled = editMode;
+ mRandomWeather.Enabled = editMode;
+ mRandomTimeOfDay.Enabled = editMode;
+ mMissionLengthDisplayLabel.Text = FormatTimeRemaining(mMissionLength);
+ mMissionLengthDisplayLabel.ForeColor = Color.Orange;
+ mMissionLengthTextBox.Visible = editMode;
+ mMissionLengthDisplayLabel.Visible = !editMode;
+ int column = mMissionPropertiesTable.GetColumn(mMissionLengthTextBox);
+ mMissionPropertiesTable.ColumnStyles[column].Width = 0f;
+ mMissionPropertiesTable.ColumnStyles[column].SizeType = ((!editMode) ? SizeType.Absolute : SizeType.AutoSize);
+ int column2 = mMissionPropertiesTable.GetColumn(mMissionLengthDisplayLabel);
+ mMissionPropertiesTable.ColumnStyles[column2].Width = 0f;
+ mMissionPropertiesTable.ColumnStyles[column2].SizeType = (editMode ? SizeType.Absolute : SizeType.AutoSize);
+ mPilotsDataGrid.EditMode = (editMode ? DataGridViewEditMode.EditOnKeystrokeOrF2 : DataGridViewEditMode.EditProgrammatically);
+ Color backColor = (editMode ? Color.White : sDataLockedColor);
+ foreach (DataGridViewRow item in (IEnumerable)mPilotsDataGrid.Rows)
+ {
+ item.Cells[mEnabledColumn.Index].Style.BackColor = backColor;
+ if (((Pod)item.Tag).HostType == HostType.GameMachineHostType)
+ {
+ Color foreColor = (((bool)item.Cells[mEnabledColumn.Index].Value) ? Color.Black : Color.DarkGray);
+ foreach (DataGridViewColumn pilotColumn in PilotDataColumns())
+ {
+ item.Cells[pilotColumn.Index].Style.BackColor = backColor;
+ item.Cells[pilotColumn.Index].Style.ForeColor = foreColor;
+ }
+ }
+ }
+ if (editMode)
+ {
+ CheckAllValues();
+ }
+ }
+
+ private DataGridViewColumn[] PilotDataColumns()
+ {
+ return new DataGridViewColumn[6] { mPilotColumn, mVehicleColumn, mColorColumn, mPatchColumn, mBadgeColumn, mExperienceColumn };
+ }
+
+ private void SetPodStatus(DataGridViewRow row, MungaGame munga)
+ {
+ if (munga.IsOwned && !munga.IsOwner(this))
+ {
+ row.Cells[mStatusIconColumn.Index].Value = ImageCache.PodQuestion16;
+ row.Cells[mStatusTextColumn.Index].Value = "In Use";
+ }
+ else
+ {
+ row.Cells[mStatusIconColumn.Index].Value = munga.Image;
+ row.Cells[mStatusTextColumn.Index].Value = munga.StatusMessage;
+ }
+ if (mCurrentState == BTGameState.Idle && mRequestedState == BTGameState.Idle)
+ {
+ CheckAllValues();
+ }
+ }
+
+ private void CheckAllValues()
+ {
+ foreach (DataGridViewRow item in (IEnumerable)mPilotsDataGrid.Rows)
+ {
+ item.Cells[mPilotColumn.Index].ErrorText = "";
+ }
+ uint num = 0u;
+ uint num2 = 0u;
+ uint num3 = 0u;
+ bool flag = false;
+ for (int i = 0; i < mPilotsDataGrid.Rows.Count; i++)
+ {
+ DataGridViewRow dataGridViewRow = mPilotsDataGrid.Rows[i];
+ Pod pod = (Pod)dataGridViewRow.Tag;
+ if (!(bool)dataGridViewRow.Cells[mEnabledColumn.Index].Value)
+ {
+ GreyOutRow(dataGridViewRow);
+ continue;
+ }
+ if (!pod.MungaGame.IsPodAppState(ApplicationID.BTL4, ApplicationState.WaitingForEgg))
+ {
+ num++;
+ }
+ if (pod.HostType == HostType.GameMachineHostType)
+ {
+ num2++;
+ DataGridViewCell dataGridViewCell = dataGridViewRow.Cells[mPilotColumn.Index];
+ foreach (DataGridViewColumn pilotColumn in PilotDataColumns())
+ {
+ dataGridViewRow.Cells[pilotColumn.Index].Style.ForeColor = pilotColumn.DefaultCellStyle.ForeColor;
+ if (pilotColumn != mPilotColumn)
+ {
+ dataGridViewRow.Cells[pilotColumn.Index].Style.BackColor = pilotColumn.DefaultCellStyle.BackColor;
+ }
+ }
+ if (dataGridViewCell.ErrorText == "")
+ {
+ if (dataGridViewCell.Value == null || (string)dataGridViewCell.Value == "")
+ {
+ dataGridViewCell.ErrorText = "Pilot name can not be blank.";
+ num3++;
+ continue;
+ }
+ for (int j = i + 1; j < mPilotsDataGrid.Rows.Count; j++)
+ {
+ DataGridViewRow dataGridViewRow2 = mPilotsDataGrid.Rows[j];
+ DataGridViewCell dataGridViewCell2 = dataGridViewRow2.Cells[mPilotColumn.Index];
+ if (((Pod)dataGridViewRow2.Tag).HostType == HostType.GameMachineHostType && (bool)dataGridViewRow2.Cells[mEnabledColumn.Index].Value && dataGridViewCell2.ErrorText == "" && dataGridViewCell.Value.Equals(dataGridViewCell2.Value))
+ {
+ dataGridViewCell.ErrorText = (dataGridViewCell2.ErrorText = "A pilot with this name already exists.");
+ flag = true;
+ }
+ }
+ }
+ }
+ else
+ {
+ GreyOutRow(dataGridViewRow);
+ }
+ }
+ StringBuilder stringBuilder = new StringBuilder();
+ if (num2 < 1)
+ {
+ stringBuilder.AppendLine("You should put at least one player in the game.");
+ }
+ if (num2 > 8)
+ {
+ stringBuilder.AppendLine("BattleTech only supports 8 players in a game.");
+ }
+ if (num3 != 0)
+ {
+ stringBuilder.AppendLine((num3 > 1) ? "Some pilots have a blank name." : "A pilot has a blank name.");
+ }
+ if (flag)
+ {
+ stringBuilder.AppendLine("Some pilots have duplicate names.");
+ }
+ if (num != 0)
+ {
+ stringBuilder.AppendLine((num > 1) ? "Some pods are not ready." : "A pod is not ready.");
+ }
+ if (ParseMissionLength() == TimeSpan.MinValue)
+ {
+ stringBuilder.AppendLine("The mission length is not valid.");
+ }
+ else if (ParseMissionLength() < TimeSpan.FromSeconds(10.0))
+ {
+ stringBuilder.AppendLine("The mission length must be at least 10 seconds.");
+ }
+ mGoButton.Enabled = stringBuilder.Length <= 0;
+ mIssuesLabel.Text = stringBuilder.ToString();
+ }
+
+ private void GreyOutRow(DataGridViewRow row)
+ {
+ foreach (DataGridViewColumn pilotColumn in PilotDataColumns())
+ {
+ row.Cells[pilotColumn.Index].Style.ForeColor = Color.DarkGray;
+ if (pilotColumn != mPilotColumn || ((Pod)row.Tag).HostType != 0)
+ {
+ row.Cells[pilotColumn.Index].Style.BackColor = sDataLockedColor;
+ }
+ }
+ }
+
+ private void mMissionLengthTextBox_TextChanged(object sender, EventArgs e)
+ {
+ CheckAllValues();
+ }
+
+ private TimeSpan ParseMissionLength()
+ {
+ if (!double.TryParse(mMissionLengthTextBox.Text, out var result))
+ {
+ return TimeSpan.MinValue;
+ }
+ try
+ {
+ return TimeSpan.FromMinutes(result);
+ }
+ catch (OverflowException)
+ {
+ return TimeSpan.MinValue;
+ }
+ }
+
+ private void mPilotsDataGrid_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
+ {
+ if (e.ColumnIndex == mPilotColumn.Index && !(bool)mPilotsDataGrid.Rows[e.RowIndex].Cells[mEnabledColumn.Index].Value)
+ {
+ mPilotsDataGrid.Rows[e.RowIndex].Cells[mPilotColumn.Index].Style.ForeColor = mPilotColumn.DefaultCellStyle.ForeColor;
+ }
+ }
+
+ private void mPilotsDataGrid_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
+ {
+ if (mPilotsDataGrid.EditingControl is TextBox textBox)
+ {
+ textBox.AutoCompleteCustomSource = PilotNameCache.PilotNames;
+ textBox.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
+ textBox.AutoCompleteSource = AutoCompleteSource.CustomSource;
+ }
+ }
+
+ private void mPilotsDataGrid_CellEndEdit(object sender, DataGridViewCellEventArgs e)
+ {
+ bool? flag = null;
+ DataGridViewRow dataGridViewRow = mPilotsDataGrid.Rows[e.RowIndex];
+ if (e.ColumnIndex == mPilotColumn.Index)
+ {
+ if (dataGridViewRow.Cells[mPilotColumn.Index].Value != null && (string)dataGridViewRow.Cells[mPilotColumn.Index].Value != "")
+ {
+ dataGridViewRow.Cells[mEnabledColumn.Index].Value = true;
+ flag = true;
+ }
+ else
+ {
+ dataGridViewRow.Cells[mEnabledColumn.Index].Value = false;
+ flag = false;
+ }
+ }
+ else if (e.ColumnIndex == mEnabledColumn.Index)
+ {
+ flag = ((!(bool)dataGridViewRow.Cells[mEnabledColumn.Index].Value) ? new bool?(false) : new bool?(true));
+ }
+ if (flag.HasValue)
+ {
+ if (flag.Value)
+ {
+ ((Pod)dataGridViewRow.Tag).MungaGame.MakeRequested(this);
+ }
+ else
+ {
+ ((Pod)dataGridViewRow.Tag).MungaGame.ReleaseRequest(this);
+ }
+ }
+ CheckAllValues();
+ }
+
+ private void mPilotsDataGrid_KeyUp(object sender, KeyEventArgs e)
+ {
+ if ((e.KeyCode == Keys.Delete || e.KeyCode == Keys.Back) && mPilotsDataGrid.SelectedCells.Count == 1 && mPilotsDataGrid.SelectedCells[0].ColumnIndex == mPilotColumn.Index)
+ {
+ mPilotsDataGrid.SelectedCells[0].Value = "";
+ DataGridViewRow dataGridViewRow = mPilotsDataGrid.Rows[mPilotsDataGrid.SelectedCells[0].RowIndex];
+ dataGridViewRow.Cells[mEnabledColumn.Index].Value = false;
+ ((Pod)dataGridViewRow.Tag).MungaGame.ReleaseRequest(this);
+ CheckAllValues();
+ }
+ }
+
+ private void mPilotsDataGrid_MouseDown(object sender, MouseEventArgs e)
+ {
+ if (mPilotsDataGrid.FirstDisplayedScrollingRowIndex < 0)
+ {
+ return;
+ }
+ for (int i = mPilotsDataGrid.FirstDisplayedScrollingRowIndex; i < mPilotsDataGrid.Rows.Count && ((Pod)mPilotsDataGrid.Rows[i].Tag).HostType == HostType.GameMachineHostType; i++)
+ {
+ if (mPilotsDataGrid.GetCellDisplayRectangle(-1, i, cutOverflow: true).Contains(e.Location))
+ {
+ mPilotsDataGrid.DoDragDrop(new DragDropData(i, e.Button == MouseButtons.Right), DragDropEffects.Move);
+ break;
+ }
+ }
+ }
+
+ private void mPilotsDataGrid_DragOver(object sender, DragEventArgs e)
+ {
+ if (mPilotsDataGrid.FirstDisplayedScrollingRowIndex >= 0)
+ {
+ for (int i = mPilotsDataGrid.FirstDisplayedScrollingRowIndex; i < mPilotsDataGrid.Rows.Count && ((Pod)mPilotsDataGrid.Rows[i].Tag).HostType == HostType.GameMachineHostType; i++)
+ {
+ if (!mPilotsDataGrid.GetCellDisplayRectangle(-1, i, cutOverflow: true).Contains(mPilotsDataGrid.PointToClient(new Point(e.X, e.Y))))
+ {
+ continue;
+ }
+ if (e.Data.GetDataPresent(typeof(DragDropData)))
+ {
+ DragDropData dragDropData = (DragDropData)e.Data.GetData(typeof(DragDropData));
+ if (dragDropData.StartRow != i)
+ {
+ e.Effect = DragDropEffects.Move;
+ }
+ else
+ {
+ e.Effect = DragDropEffects.None;
+ }
+ }
+ return;
+ }
+ }
+ e.Effect = DragDropEffects.None;
+ }
+
+ private void mPilotsDataGrid_DragDrop(object sender, DragEventArgs e)
+ {
+ for (int i = mPilotsDataGrid.FirstDisplayedScrollingRowIndex; i < mPilotsDataGrid.Rows.Count; i++)
+ {
+ if (!mPilotsDataGrid.GetCellDisplayRectangle(-1, i, cutOverflow: true).Contains(mPilotsDataGrid.PointToClient(new Point(e.X, e.Y))))
+ {
+ continue;
+ }
+ if (!e.Data.GetDataPresent(typeof(DragDropData)))
+ {
+ break;
+ }
+ DragDropData dragDropData = (DragDropData)e.Data.GetData(typeof(DragDropData));
+ if (dragDropData.StartRow != i)
+ {
+ if (dragDropData.RightClick)
+ {
+ dragDropData.EndRow = i;
+ mDragDropContextMenu.Tag = dragDropData;
+ mDragDropContextMenu.Show(e.X, e.Y);
+ }
+ else
+ {
+ SwapPilots(i, dragDropData.StartRow, update: true);
+ }
+ }
+ break;
+ }
+ }
+
+ private void swapToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (mDragDropContextMenu.Tag is DragDropData)
+ {
+ DragDropData dragDropData = (DragDropData)mDragDropContextMenu.Tag;
+ SwapPilots(dragDropData.StartRow, dragDropData.EndRow, update: true);
+ }
+ }
+
+ private void shiftToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (!(mDragDropContextMenu.Tag is DragDropData))
+ {
+ return;
+ }
+ DragDropData dragDropData = (DragDropData)mDragDropContextMenu.Tag;
+ if (dragDropData.StartRow < dragDropData.EndRow)
+ {
+ for (int i = dragDropData.StartRow; i < dragDropData.EndRow; i++)
+ {
+ SwapPilots(i, i + 1, i + 1 == dragDropData.EndRow);
+ }
+ return;
+ }
+ for (int num = dragDropData.StartRow; num > dragDropData.EndRow; num--)
+ {
+ SwapPilots(num, num - 1, num - 1 == dragDropData.EndRow);
+ }
+ }
+
+ private void SwapPilots(int row1, int row2, bool update)
+ {
+ foreach (DataGridViewColumn column in mPilotsDataGrid.Columns)
+ {
+ if (column != mStatusIconColumn && column != mStatusTextColumn && column != mEnabledColumn)
+ {
+ object value = mPilotsDataGrid[column.Index, row1].Value;
+ mPilotsDataGrid[column.Index, row1].Value = mPilotsDataGrid[column.Index, row2].Value;
+ mPilotsDataGrid[column.Index, row2].Value = value;
+ }
+ }
+ if (update)
+ {
+ CheckAllValues();
+ mPilotsDataGrid.Refresh();
+ }
+ }
+
+ protected override void OnKeyDown(KeyEventArgs e)
+ {
+ if (e.Modifiers == Keys.Control && e.KeyCode == Keys.L)
+ {
+ if (mLogWindow == null || mLogWindow.IsDisposed)
+ {
+ mLogWindow = new LogOutputWindow();
+ }
+ mLogWindow.Show();
+ e.Handled = true;
+ }
+ base.OnKeyDown(e);
+ }
+
+ private void mRandomMap_Click(object sender, EventArgs e)
+ {
+ mMap.SelectedIndex = sRand.Next(mMap.Items.Count);
+ }
+
+ private void mRandomWeather_Click(object sender, EventArgs e)
+ {
+ mWeather.SelectedIndex = sRand.Next(mWeather.Items.Count);
+ }
+
+ private void mRandomTimeOfDay_Click(object sender, EventArgs e)
+ {
+ mTimeOfDay.SelectedIndex = sRand.Next(mTimeOfDay.Items.Count);
+ }
+
+ private void tmrAutoTranslocate_Tick(object sender, EventArgs e)
+ {
+ mRemainingUntilTranslocate--;
+ if (mRemainingUntilTranslocate < 1)
+ {
+ RequestState(BTGameState.Run);
+ tmrAutoTranslocate.Stop();
+ }
+ else
+ {
+ string text2 = (GameStatusText = $"Launching in {mRemainingUntilTranslocate}...");
+ mGoButton.Text = text2;
+ }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && components != null)
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ this.mMissionPropertiesGroupBox = new System.Windows.Forms.GroupBox();
+ this.mMissionPropertiesTable = new System.Windows.Forms.TableLayoutPanel();
+ this.mIssuesLabel = new System.Windows.Forms.Label();
+ this.mMissionLengthTextLabel = new System.Windows.Forms.Label();
+ this.mMap = new System.Windows.Forms.ComboBox();
+ this.mMissionLengthDisplayLabel = new System.Windows.Forms.Label();
+ this.mWeather = new System.Windows.Forms.ComboBox();
+ this.mTimeOfDay = new System.Windows.Forms.ComboBox();
+ this.mMapLabel = new System.Windows.Forms.Label();
+ this.mWeatherLabel = new System.Windows.Forms.Label();
+ this.mTimeOfDayLabel = new System.Windows.Forms.Label();
+ this.mAdvancedDamage = new System.Windows.Forms.CheckBox();
+ this.mGoButton = new System.Windows.Forms.Button();
+ this.mResetContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.resetToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.mAutoTranslocateCheckbox = new System.Windows.Forms.CheckBox();
+ this.mRandomMap = new System.Windows.Forms.Button();
+ this.mRandomWeather = new System.Windows.Forms.Button();
+ this.mRandomTimeOfDay = new System.Windows.Forms.Button();
+ this.mMissionLengthTextBox = new System.Windows.Forms.TextBox();
+ this.mPilotsGroupBox = new System.Windows.Forms.GroupBox();
+ this.mPilotsDataGrid = new System.Windows.Forms.DataGridView();
+ this.mEnabledColumn = new System.Windows.Forms.DataGridViewCheckBoxColumn();
+ this.mStatusIconColumn = new System.Windows.Forms.DataGridViewImageColumn();
+ this.mStatusTextColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.mPilotColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.mVehicleColumn = new System.Windows.Forms.DataGridViewComboBoxColumn();
+ this.mColorColumn = new System.Windows.Forms.DataGridViewComboBoxColumn();
+ this.mPatchColumn = new System.Windows.Forms.DataGridViewComboBoxColumn();
+ this.mBadgeColumn = new System.Windows.Forms.DataGridViewComboBoxColumn();
+ this.mExperienceColumn = new System.Windows.Forms.DataGridViewComboBoxColumn();
+ this.mDragDropContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.mSwapPilots = new System.Windows.Forms.ToolStripMenuItem();
+ this.mShiftPilots = new System.Windows.Forms.ToolStripMenuItem();
+ this.mNetworkTimer = new System.Windows.Forms.Timer(this.components);
+ this.tmrAutoTranslocate = new System.Windows.Forms.Timer(this.components);
+ this.mMissionPropertiesGroupBox.SuspendLayout();
+ this.mMissionPropertiesTable.SuspendLayout();
+ this.mResetContextMenu.SuspendLayout();
+ this.mPilotsGroupBox.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)this.mPilotsDataGrid).BeginInit();
+ this.mDragDropContextMenu.SuspendLayout();
+ base.SuspendLayout();
+ this.mMissionPropertiesGroupBox.Controls.Add(this.mMissionPropertiesTable);
+ this.mMissionPropertiesGroupBox.Dock = System.Windows.Forms.DockStyle.Top;
+ this.mMissionPropertiesGroupBox.Location = new System.Drawing.Point(8, 8);
+ this.mMissionPropertiesGroupBox.Name = "mMissionPropertiesGroupBox";
+ this.mMissionPropertiesGroupBox.Padding = new System.Windows.Forms.Padding(5);
+ this.mMissionPropertiesGroupBox.Size = new System.Drawing.Size(1040, 105);
+ this.mMissionPropertiesGroupBox.TabIndex = 10;
+ this.mMissionPropertiesGroupBox.TabStop = false;
+ this.mMissionPropertiesGroupBox.Text = "Mission Properties";
+ this.mMissionPropertiesTable.AutoSize = true;
+ this.mMissionPropertiesTable.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+ this.mMissionPropertiesTable.ColumnCount = 8;
+ this.mMissionPropertiesTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
+ this.mMissionPropertiesTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
+ this.mMissionPropertiesTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
+ this.mMissionPropertiesTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
+ this.mMissionPropertiesTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
+ this.mMissionPropertiesTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 0f));
+ this.mMissionPropertiesTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
+ this.mMissionPropertiesTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
+ this.mMissionPropertiesTable.Controls.Add(this.mIssuesLabel, 7, 0);
+ this.mMissionPropertiesTable.Controls.Add(this.mMissionLengthTextLabel, 3, 1);
+ this.mMissionPropertiesTable.Controls.Add(this.mMap, 1, 0);
+ this.mMissionPropertiesTable.Controls.Add(this.mMissionLengthDisplayLabel, 5, 1);
+ this.mMissionPropertiesTable.Controls.Add(this.mWeather, 1, 1);
+ this.mMissionPropertiesTable.Controls.Add(this.mTimeOfDay, 1, 2);
+ this.mMissionPropertiesTable.Controls.Add(this.mMapLabel, 0, 0);
+ this.mMissionPropertiesTable.Controls.Add(this.mWeatherLabel, 0, 1);
+ this.mMissionPropertiesTable.Controls.Add(this.mTimeOfDayLabel, 0, 2);
+ this.mMissionPropertiesTable.Controls.Add(this.mAdvancedDamage, 3, 0);
+ this.mMissionPropertiesTable.Controls.Add(this.mGoButton, 3, 2);
+ this.mMissionPropertiesTable.Controls.Add(this.mAutoTranslocateCheckbox, 6, 0);
+ this.mMissionPropertiesTable.Controls.Add(this.mRandomMap, 2, 0);
+ this.mMissionPropertiesTable.Controls.Add(this.mRandomWeather, 2, 1);
+ this.mMissionPropertiesTable.Controls.Add(this.mRandomTimeOfDay, 2, 2);
+ this.mMissionPropertiesTable.Controls.Add(this.mMissionLengthTextBox, 4, 1);
+ this.mMissionPropertiesTable.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.mMissionPropertiesTable.GrowStyle = System.Windows.Forms.TableLayoutPanelGrowStyle.AddColumns;
+ this.mMissionPropertiesTable.Location = new System.Drawing.Point(5, 18);
+ this.mMissionPropertiesTable.MinimumSize = new System.Drawing.Size(0, 85);
+ this.mMissionPropertiesTable.Name = "mMissionPropertiesTable";
+ this.mMissionPropertiesTable.RowCount = 4;
+ this.mMissionPropertiesTable.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.mMissionPropertiesTable.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.mMissionPropertiesTable.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.mMissionPropertiesTable.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100f));
+ this.mMissionPropertiesTable.Size = new System.Drawing.Size(1030, 85);
+ this.mMissionPropertiesTable.TabIndex = 0;
+ this.mIssuesLabel.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
+ this.mIssuesLabel.AutoSize = true;
+ this.mIssuesLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25f, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0);
+ this.mIssuesLabel.ForeColor = System.Drawing.Color.Red;
+ this.mIssuesLabel.Location = new System.Drawing.Point(642, 0);
+ this.mIssuesLabel.Name = "mIssuesLabel";
+ this.mMissionPropertiesTable.SetRowSpan(this.mIssuesLabel, 4);
+ this.mIssuesLabel.Size = new System.Drawing.Size(385, 85);
+ this.mIssuesLabel.TabIndex = 0;
+ this.mMissionLengthTextLabel.Anchor = System.Windows.Forms.AnchorStyles.Left;
+ this.mMissionLengthTextLabel.AutoSize = true;
+ this.mMissionLengthTextLabel.Location = new System.Drawing.Point(311, 37);
+ this.mMissionLengthTextLabel.Name = "mMissionLengthTextLabel";
+ this.mMissionLengthTextLabel.Size = new System.Drawing.Size(106, 13);
+ this.mMissionLengthTextLabel.TabIndex = 7;
+ this.mMissionLengthTextLabel.Text = "Mission Length (min):";
+ this.mMap.Anchor = System.Windows.Forms.AnchorStyles.Left;
+ this.mMap.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.mMap.FormattingEnabled = true;
+ this.mMap.Location = new System.Drawing.Point(76, 4);
+ this.mMap.Name = "mMap";
+ this.mMap.Size = new System.Drawing.Size(198, 21);
+ this.mMap.TabIndex = 0;
+ this.mMissionLengthDisplayLabel.Anchor = System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
+ this.mMissionLengthDisplayLabel.AutoSize = true;
+ this.mMissionLengthDisplayLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 12f, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0);
+ this.mMissionLengthDisplayLabel.ForeColor = System.Drawing.Color.Green;
+ this.mMissionLengthDisplayLabel.Location = new System.Drawing.Point(529, 33);
+ this.mMissionLengthDisplayLabel.Name = "mMissionLengthDisplayLabel";
+ this.mMissionLengthDisplayLabel.Size = new System.Drawing.Size(1, 20);
+ this.mMissionLengthDisplayLabel.TabIndex = 9;
+ this.mMissionLengthDisplayLabel.Text = "00:00";
+ this.mMissionLengthDisplayLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ this.mMissionLengthDisplayLabel.Visible = false;
+ this.mWeather.Anchor = System.Windows.Forms.AnchorStyles.Left;
+ this.mWeather.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.mWeather.FormattingEnabled = true;
+ this.mWeather.Location = new System.Drawing.Point(76, 33);
+ this.mWeather.Name = "mWeather";
+ this.mWeather.Size = new System.Drawing.Size(198, 21);
+ this.mWeather.TabIndex = 1;
+ this.mTimeOfDay.Anchor = System.Windows.Forms.AnchorStyles.Left;
+ this.mTimeOfDay.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.mTimeOfDay.FormattingEnabled = true;
+ this.mTimeOfDay.Location = new System.Drawing.Point(76, 62);
+ this.mTimeOfDay.Name = "mTimeOfDay";
+ this.mTimeOfDay.Size = new System.Drawing.Size(198, 21);
+ this.mTimeOfDay.TabIndex = 2;
+ this.mMapLabel.Anchor = System.Windows.Forms.AnchorStyles.Left;
+ this.mMapLabel.AutoSize = true;
+ this.mMapLabel.Location = new System.Drawing.Point(3, 8);
+ this.mMapLabel.Name = "mMapLabel";
+ this.mMapLabel.Size = new System.Drawing.Size(31, 13);
+ this.mMapLabel.TabIndex = 0;
+ this.mMapLabel.Text = "Map:";
+ this.mWeatherLabel.Anchor = System.Windows.Forms.AnchorStyles.Left;
+ this.mWeatherLabel.AutoSize = true;
+ this.mWeatherLabel.Location = new System.Drawing.Point(3, 37);
+ this.mWeatherLabel.Name = "mWeatherLabel";
+ this.mWeatherLabel.Size = new System.Drawing.Size(51, 13);
+ this.mWeatherLabel.TabIndex = 2;
+ this.mWeatherLabel.Text = "Weather:";
+ this.mTimeOfDayLabel.Anchor = System.Windows.Forms.AnchorStyles.Left;
+ this.mTimeOfDayLabel.AutoSize = true;
+ this.mTimeOfDayLabel.Location = new System.Drawing.Point(3, 66);
+ this.mTimeOfDayLabel.Name = "mTimeOfDayLabel";
+ this.mTimeOfDayLabel.Size = new System.Drawing.Size(67, 13);
+ this.mTimeOfDayLabel.TabIndex = 4;
+ this.mTimeOfDayLabel.Text = "Time of Day:";
+ this.mAdvancedDamage.Anchor = System.Windows.Forms.AnchorStyles.Left;
+ this.mAdvancedDamage.AutoSize = true;
+ this.mMissionPropertiesTable.SetColumnSpan(this.mAdvancedDamage, 3);
+ this.mAdvancedDamage.Checked = true;
+ this.mAdvancedDamage.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.mAdvancedDamage.Location = new System.Drawing.Point(311, 6);
+ this.mAdvancedDamage.Name = "mAdvancedDamage";
+ this.mAdvancedDamage.Size = new System.Drawing.Size(117, 17);
+ this.mAdvancedDamage.TabIndex = 6;
+ this.mAdvancedDamage.Text = "Advanced Damage";
+ this.mAdvancedDamage.UseVisualStyleBackColor = true;
+ this.mGoButton.Anchor = System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
+ this.mMissionPropertiesTable.SetColumnSpan(this.mGoButton, 3);
+ this.mGoButton.ContextMenuStrip = this.mResetContextMenu;
+ this.mGoButton.Location = new System.Drawing.Point(311, 61);
+ this.mGoButton.Name = "mGoButton";
+ this.mGoButton.Size = new System.Drawing.Size(212, 23);
+ this.mGoButton.TabIndex = 10;
+ this.mGoButton.Text = "Load";
+ this.mGoButton.UseVisualStyleBackColor = true;
+ this.mGoButton.Click += new System.EventHandler(mGoButton_Click);
+ this.mResetContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[1] { this.resetToolStripMenuItem });
+ this.mResetContextMenu.Name = "mResetContextMenu";
+ this.mResetContextMenu.Size = new System.Drawing.Size(103, 26);
+ this.resetToolStripMenuItem.Name = "resetToolStripMenuItem";
+ this.resetToolStripMenuItem.Size = new System.Drawing.Size(102, 22);
+ this.resetToolStripMenuItem.Text = "&Reset";
+ this.resetToolStripMenuItem.Click += new System.EventHandler(resetToolStripMenuItem_Click);
+ this.mAutoTranslocateCheckbox.Anchor = System.Windows.Forms.AnchorStyles.Left;
+ this.mAutoTranslocateCheckbox.AutoSize = true;
+ this.mAutoTranslocateCheckbox.Location = new System.Drawing.Point(529, 6);
+ this.mAutoTranslocateCheckbox.Name = "mAutoTranslocateCheckbox";
+ this.mAutoTranslocateCheckbox.Size = new System.Drawing.Size(107, 17);
+ this.mAutoTranslocateCheckbox.TabIndex = 8;
+ this.mAutoTranslocateCheckbox.Text = "Auto Translocate";
+ this.mAutoTranslocateCheckbox.UseVisualStyleBackColor = true;
+ this.mRandomMap.Location = new System.Drawing.Point(280, 3);
+ this.mRandomMap.Name = "mRandomMap";
+ this.mRandomMap.Size = new System.Drawing.Size(25, 23);
+ this.mRandomMap.TabIndex = 3;
+ this.mRandomMap.Text = "R";
+ this.mRandomMap.UseVisualStyleBackColor = true;
+ this.mRandomMap.Click += new System.EventHandler(mRandomMap_Click);
+ this.mRandomWeather.Location = new System.Drawing.Point(280, 32);
+ this.mRandomWeather.Name = "mRandomWeather";
+ this.mRandomWeather.Size = new System.Drawing.Size(25, 23);
+ this.mRandomWeather.TabIndex = 4;
+ this.mRandomWeather.Text = "R";
+ this.mRandomWeather.UseVisualStyleBackColor = true;
+ this.mRandomWeather.Click += new System.EventHandler(mRandomWeather_Click);
+ this.mRandomTimeOfDay.Location = new System.Drawing.Point(280, 61);
+ this.mRandomTimeOfDay.Name = "mRandomTimeOfDay";
+ this.mRandomTimeOfDay.Size = new System.Drawing.Size(25, 23);
+ this.mRandomTimeOfDay.TabIndex = 5;
+ this.mRandomTimeOfDay.Text = "R";
+ this.mRandomTimeOfDay.UseVisualStyleBackColor = true;
+ this.mRandomTimeOfDay.Click += new System.EventHandler(mRandomTimeOfDay_Click);
+ this.mMissionLengthTextBox.Anchor = System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
+ this.mMissionLengthTextBox.Location = new System.Drawing.Point(423, 33);
+ this.mMissionLengthTextBox.Name = "mMissionLengthTextBox";
+ this.mMissionLengthTextBox.Size = new System.Drawing.Size(100, 20);
+ this.mMissionLengthTextBox.TabIndex = 12;
+ this.mMissionLengthTextBox.TextChanged += new System.EventHandler(mMissionLengthTextBox_TextChanged);
+ this.mPilotsGroupBox.Controls.Add(this.mPilotsDataGrid);
+ this.mPilotsGroupBox.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.mPilotsGroupBox.Location = new System.Drawing.Point(8, 113);
+ this.mPilotsGroupBox.Name = "mPilotsGroupBox";
+ this.mPilotsGroupBox.Padding = new System.Windows.Forms.Padding(5);
+ this.mPilotsGroupBox.Size = new System.Drawing.Size(1040, 425);
+ this.mPilotsGroupBox.TabIndex = 11;
+ this.mPilotsGroupBox.TabStop = false;
+ this.mPilotsGroupBox.Text = "Pilots";
+ this.mPilotsDataGrid.AllowDrop = true;
+ this.mPilotsDataGrid.AllowUserToAddRows = false;
+ this.mPilotsDataGrid.AllowUserToDeleteRows = false;
+ this.mPilotsDataGrid.AllowUserToResizeColumns = false;
+ this.mPilotsDataGrid.AllowUserToResizeRows = false;
+ this.mPilotsDataGrid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+ this.mPilotsDataGrid.Columns.AddRange(this.mEnabledColumn, this.mStatusIconColumn, this.mStatusTextColumn, this.mPilotColumn, this.mVehicleColumn, this.mColorColumn, this.mPatchColumn, this.mBadgeColumn, this.mExperienceColumn);
+ this.mPilotsDataGrid.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.mPilotsDataGrid.Location = new System.Drawing.Point(5, 18);
+ this.mPilotsDataGrid.MultiSelect = false;
+ this.mPilotsDataGrid.Name = "mPilotsDataGrid";
+ this.mPilotsDataGrid.RowHeadersWidthSizeMode = System.Windows.Forms.DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders;
+ this.mPilotsDataGrid.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.CellSelect;
+ this.mPilotsDataGrid.ShowEditingIcon = false;
+ this.mPilotsDataGrid.Size = new System.Drawing.Size(1030, 402);
+ this.mPilotsDataGrid.TabIndex = 0;
+ this.mPilotsDataGrid.MouseDown += new System.Windows.Forms.MouseEventHandler(mPilotsDataGrid_MouseDown);
+ this.mPilotsDataGrid.CellBeginEdit += new System.Windows.Forms.DataGridViewCellCancelEventHandler(mPilotsDataGrid_CellBeginEdit);
+ this.mPilotsDataGrid.DragOver += new System.Windows.Forms.DragEventHandler(mPilotsDataGrid_DragOver);
+ this.mPilotsDataGrid.CellEndEdit += new System.Windows.Forms.DataGridViewCellEventHandler(mPilotsDataGrid_CellEndEdit);
+ this.mPilotsDataGrid.EditingControlShowing += new System.Windows.Forms.DataGridViewEditingControlShowingEventHandler(mPilotsDataGrid_EditingControlShowing);
+ this.mPilotsDataGrid.KeyUp += new System.Windows.Forms.KeyEventHandler(mPilotsDataGrid_KeyUp);
+ this.mPilotsDataGrid.DragDrop += new System.Windows.Forms.DragEventHandler(mPilotsDataGrid_DragDrop);
+ this.mEnabledColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.DisplayedCells;
+ this.mEnabledColumn.HeaderText = "Enabled";
+ this.mEnabledColumn.Name = "mEnabledColumn";
+ this.mEnabledColumn.Width = 52;
+ this.mStatusIconColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.ColumnHeader;
+ this.mStatusIconColumn.HeaderText = "Status";
+ this.mStatusIconColumn.Name = "mStatusIconColumn";
+ this.mStatusIconColumn.ReadOnly = true;
+ this.mStatusIconColumn.Resizable = System.Windows.Forms.DataGridViewTriState.False;
+ this.mStatusIconColumn.Width = 43;
+ this.mStatusTextColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
+ this.mStatusTextColumn.HeaderText = "Status Text";
+ this.mStatusTextColumn.MinimumWidth = 100;
+ this.mStatusTextColumn.Name = "mStatusTextColumn";
+ this.mStatusTextColumn.ReadOnly = true;
+ this.mPilotColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
+ this.mPilotColumn.HeaderText = "Pilot";
+ this.mPilotColumn.MinimumWidth = 100;
+ this.mPilotColumn.Name = "mPilotColumn";
+ this.mPilotColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+ this.mVehicleColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
+ this.mVehicleColumn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.mVehicleColumn.HeaderText = "Mech";
+ this.mVehicleColumn.MinimumWidth = 100;
+ this.mVehicleColumn.Name = "mVehicleColumn";
+ this.mColorColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
+ this.mColorColumn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.mColorColumn.HeaderText = "Camo";
+ this.mColorColumn.MinimumWidth = 80;
+ this.mColorColumn.Name = "mColorColumn";
+ this.mPatchColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
+ this.mPatchColumn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.mPatchColumn.HeaderText = "Patch";
+ this.mPatchColumn.MinimumWidth = 80;
+ this.mPatchColumn.Name = "mPatchColumn";
+ this.mBadgeColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
+ this.mBadgeColumn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.mBadgeColumn.HeaderText = "Badge";
+ this.mBadgeColumn.MinimumWidth = 80;
+ this.mBadgeColumn.Name = "mBadgeColumn";
+ this.mExperienceColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
+ this.mExperienceColumn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.mExperienceColumn.HeaderText = "Experience";
+ this.mExperienceColumn.MinimumWidth = 80;
+ this.mExperienceColumn.Name = "mExperienceColumn";
+ this.mDragDropContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[2] { this.mSwapPilots, this.mShiftPilots });
+ this.mDragDropContextMenu.Name = "contextMenuStrip1";
+ this.mDragDropContextMenu.Size = new System.Drawing.Size(103, 48);
+ this.mSwapPilots.Name = "mSwapPilots";
+ this.mSwapPilots.Size = new System.Drawing.Size(102, 22);
+ this.mSwapPilots.Text = "Swap";
+ this.mSwapPilots.Click += new System.EventHandler(swapToolStripMenuItem_Click);
+ this.mShiftPilots.Name = "mShiftPilots";
+ this.mShiftPilots.Size = new System.Drawing.Size(102, 22);
+ this.mShiftPilots.Text = "Shift";
+ this.mShiftPilots.Click += new System.EventHandler(shiftToolStripMenuItem_Click);
+ this.mNetworkTimer.Enabled = true;
+ this.mNetworkTimer.Tick += new System.EventHandler(NetworkScan);
+ this.tmrAutoTranslocate.Interval = 1000;
+ this.tmrAutoTranslocate.Tick += new System.EventHandler(tmrAutoTranslocate_Tick);
+ base.AutoScaleDimensions = new System.Drawing.SizeF(6f, 13f);
+ base.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ base.ClientSize = new System.Drawing.Size(1056, 546);
+ base.Controls.Add(this.mPilotsGroupBox);
+ base.Controls.Add(this.mMissionPropertiesGroupBox);
+ this.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25f, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0);
+ base.KeyPreview = true;
+ base.Name = "BTGame";
+ base.Padding = new System.Windows.Forms.Padding(8);
+ base.TabText = "BattleTech Game";
+ this.Text = "BattleTech Game";
+ this.mMissionPropertiesGroupBox.ResumeLayout(false);
+ this.mMissionPropertiesGroupBox.PerformLayout();
+ this.mMissionPropertiesTable.ResumeLayout(false);
+ this.mMissionPropertiesTable.PerformLayout();
+ this.mResetContextMenu.ResumeLayout(false);
+ this.mPilotsGroupBox.ResumeLayout(false);
+ ((System.ComponentModel.ISupportInitialize)this.mPilotsDataGrid).EndInit();
+ this.mDragDropContextMenu.ResumeLayout(false);
+ base.ResumeLayout(false);
+ }
+}
diff --git a/Console/TeslaConsole.BattleTech/BTKilledEvent.cs b/Console/TeslaConsole.BattleTech/BTKilledEvent.cs
new file mode 100644
index 0000000..2bbce4b
--- /dev/null
+++ b/Console/TeslaConsole.BattleTech/BTKilledEvent.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+
+namespace TeslaConsole.BattleTech;
+
+/// A mech was destroyed (MechKilledMessage).
+[Serializable]
+internal class BTKilledEvent : BTMissionEvent
+{
+ public readonly BTPlayer Killer;
+
+ public override IEnumerable InvolvedPilots => new BTPlayer[2] { ReportingPilot, Killer };
+
+ public BTKilledEvent(BTPlayer reportingPilot, TimeSpan missionTime, BTPlayer killer)
+ : base(reportingPilot, missionTime)
+ {
+ Killer = killer;
+ }
+
+ private BTKilledEvent()
+ {
+ }
+}
diff --git a/Console/TeslaConsole.BattleTech/BTMissionEvent.cs b/Console/TeslaConsole.BattleTech/BTMissionEvent.cs
new file mode 100644
index 0000000..ab5a72c
--- /dev/null
+++ b/Console/TeslaConsole.BattleTech/BTMissionEvent.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+
+namespace TeslaConsole.BattleTech;
+
+///
+/// Base class for a recorded in-match BattleTech event. Mirrors the Red Planet
+/// MissionEvent, typed over .
+///
+[Serializable]
+internal abstract class BTMissionEvent
+{
+ public readonly TimeSpan GameTime;
+
+ public readonly BTPlayer ReportingPilot;
+
+ public abstract IEnumerable InvolvedPilots { get; }
+
+ public BTMissionEvent(BTPlayer reportingPilot, TimeSpan missionTime)
+ {
+ ReportingPilot = reportingPilot;
+ GameTime = missionTime;
+ }
+
+ protected BTMissionEvent()
+ {
+ }
+}
diff --git a/Console/TeslaConsole.BattleTech/BTMissionRecorder.cs b/Console/TeslaConsole.BattleTech/BTMissionRecorder.cs
new file mode 100644
index 0000000..11d36a9
--- /dev/null
+++ b/Console/TeslaConsole.BattleTech/BTMissionRecorder.cs
@@ -0,0 +1,99 @@
+using System;
+
+namespace TeslaConsole.BattleTech;
+
+///
+/// Records the in-match Munga event messages of one BattleTech mission into a
+/// . Mirrors RPMissionRecorder; the event
+/// set follows the BT messages in Munga Net.dll (Mech* / EndMission).
+///
+internal class BTMissionRecorder
+{
+ private BTMissionResults mMissionResults;
+
+ private bool mStartSet;
+
+ public BTMissionRecorder(BTMission mission)
+ {
+ mMissionResults = new BTMissionResults(mission);
+ }
+
+ public void SetMissionStart()
+ {
+ if (mStartSet)
+ {
+ throw new InvalidOperationException();
+ }
+ mMissionResults.mMissionStart = DateTime.Now;
+ mStartSet = true;
+ }
+
+ private void ValidatePlayer(BTPlayer player, string param)
+ {
+ if (player == null)
+ {
+ throw new ArgumentNullException(param);
+ }
+ foreach (BTPlayer player2 in mMissionResults.Mission.Players)
+ {
+ if (player2 == player)
+ {
+ return;
+ }
+ }
+ throw new ArgumentException(param);
+ }
+
+ private TimeSpan GetMissionTime()
+ {
+ if (!mStartSet)
+ {
+ return TimeSpan.Zero;
+ }
+ return DateTime.Now - mMissionResults.mMissionStart;
+ }
+
+ public void PlayerKilled(BTPlayer reportingPlayer, BTPlayer killer)
+ {
+ ValidatePlayer(reportingPlayer, "reportingPlayer");
+ ValidatePlayer(killer, "killer");
+ TimeSpan missionTime = GetMissionTime();
+ mMissionResults.mEvents.Add(new BTKilledEvent(reportingPlayer, missionTime, killer));
+ }
+
+ public void PlayerDeathWithoutHonor(BTPlayer reportingPlayer)
+ {
+ ValidatePlayer(reportingPlayer, "reportingPlayer");
+ TimeSpan missionTime = GetMissionTime();
+ mMissionResults.mEvents.Add(new BTDeathWithoutHonorEvent(reportingPlayer, missionTime));
+ }
+
+ public void PlayerScoreUpdate(BTPlayer reportingPlayer, int score)
+ {
+ ValidatePlayer(reportingPlayer, "reportingPlayer");
+ TimeSpan missionTime = GetMissionTime();
+ mMissionResults.mEvents.Add(new BTScoreUpdateEvent(reportingPlayer, missionTime, score));
+ }
+
+ public void PlayerDamaged(BTPlayer reportingPlayer, BTPlayer damager, int damageLoss, int pointsTransfered, int damageZoneIndex, bool damageZoneDestroyed, int weaponIndex)
+ {
+ ValidatePlayer(reportingPlayer, "reportingPlayer");
+ ValidatePlayer(damager, "damager");
+ TimeSpan missionTime = GetMissionTime();
+ mMissionResults.mEvents.Add(new BTDamagedEvent(reportingPlayer, missionTime, damager, damageLoss, pointsTransfered, damageZoneIndex, damageZoneDestroyed, weaponIndex));
+ }
+
+ public void PlayerFinalScore(BTPlayer reportingPlayer, int finalScore)
+ {
+ ValidatePlayer(reportingPlayer, "reportingPlayer");
+ mMissionResults.mFinalScores.Add(reportingPlayer, finalScore);
+ }
+
+ public BTMissionResults EndMission(TimeSpan missionLength)
+ {
+ mMissionResults.mActuallMissionTime = missionLength;
+ BTMissionResults result = mMissionResults;
+ mMissionResults = null;
+ return result;
+ }
+}
diff --git a/Console/TeslaConsole.BattleTech/BTMissionResults.cs b/Console/TeslaConsole.BattleTech/BTMissionResults.cs
new file mode 100644
index 0000000..dc6698f
--- /dev/null
+++ b/Console/TeslaConsole.BattleTech/BTMissionResults.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.IO.Compression;
+using System.Runtime.Serialization.Formatters.Binary;
+
+namespace TeslaConsole.BattleTech;
+
+///
+/// The recorded outcome of one BattleTech mission, saved as a gzip'd
+/// BinaryFormatter blob (.btm) exactly like the RP .rpm mechanism. Mirrors
+/// RPMissionResults minus the football branches; the score-sheet print
+/// document (RPPrintDocument's counterpart) is deferred until a real BT match
+/// has been recorded to design it against.
+///
+[Serializable]
+internal class BTMissionResults
+{
+ private BTMission mMission;
+
+ internal DateTime mMissionStart;
+
+ internal TimeSpan mActuallMissionTime;
+
+ internal readonly List mEvents = new List();
+
+ internal readonly Dictionary mFinalScores = new Dictionary();
+
+ public BTMission Mission => mMission;
+
+ public DateTime MissionStart => mMissionStart;
+
+ public TimeSpan ActuallMissionTime => mActuallMissionTime;
+
+ public IEnumerable Events => mEvents;
+
+ internal BTMissionResults(BTMission mission)
+ {
+ mMission = mission;
+ }
+
+ public static string GetBTMissionsDirectory()
+ {
+ string text = Path.Combine(Program.GetCommonAppDataDirectory(), "BT Missions");
+ if (!Directory.Exists(text))
+ {
+ Directory.CreateDirectory(text);
+ }
+ return text;
+ }
+
+ public static BTMissionResults Load(string file)
+ {
+ using GZipStream gZipStream = new GZipStream(File.OpenRead(file), CompressionMode.Decompress);
+ BinaryFormatter binaryFormatter = new BinaryFormatter();
+ BTMissionResults result = (BTMissionResults)binaryFormatter.Deserialize(gZipStream);
+ gZipStream.Close();
+ return result;
+ }
+
+ public void Save()
+ {
+ string path = Path.Combine(GetBTMissionsDirectory(), mMissionStart.ToString("yyyy-MM-dd HH-mm-ss.ffff") + ".btm");
+ using GZipStream gZipStream = new GZipStream(File.OpenWrite(path), CompressionMode.Compress);
+ BinaryFormatter binaryFormatter = new BinaryFormatter();
+ binaryFormatter.Serialize(gZipStream, this);
+ gZipStream.Close();
+ }
+
+ public int GetScore(BTPlayer player)
+ {
+ return GetScore(player, TimeSpan.MaxValue);
+ }
+
+ public int GetScore(BTPlayer player, TimeSpan gameTime)
+ {
+ if (gameTime == TimeSpan.MaxValue && mFinalScores.ContainsKey(player))
+ {
+ return mFinalScores[player];
+ }
+ int result = 1000;
+ TimeSpan timeSpan = TimeSpan.MinValue;
+ foreach (BTMissionEvent mEvent in mEvents)
+ {
+ if (mEvent is BTScoreUpdateEvent && mEvent.ReportingPilot == player && mEvent.GameTime > timeSpan && mEvent.GameTime <= gameTime)
+ {
+ result = ((BTScoreUpdateEvent)mEvent).Score;
+ timeSpan = mEvent.GameTime;
+ }
+ }
+ return result;
+ }
+
+ public int GetFinalPlace(BTPlayer player)
+ {
+ int num = 1;
+ int score = GetScore(player, TimeSpan.MaxValue);
+ foreach (BTPlayer player2 in mMission.Players)
+ {
+ if (player2 != player && GetScore(player2, TimeSpan.MaxValue) > score)
+ {
+ num++;
+ }
+ }
+ return num;
+ }
+}
diff --git a/Console/TeslaConsole.BattleTech/BTRole.cs b/Console/TeslaConsole.BattleTech/BTRole.cs
index 17ac67f..b90442c 100644
--- a/Console/TeslaConsole.BattleTech/BTRole.cs
+++ b/Console/TeslaConsole.BattleTech/BTRole.cs
@@ -1,3 +1,4 @@
+using System;
using System.Xml;
namespace TeslaConsole.BattleTech;
@@ -6,8 +7,11 @@ namespace TeslaConsole.BattleTech;
/// A BattleTech pilot role. Each participant references one role
/// (role=Role::<Key>); the egg then carries a matching
/// [Role::<Key>] model=<Model> block. Free For All uses the
-/// Default role, No Return uses the NoReturn role.
+/// Default role, No Return uses the NoReturn role. Serializable because it is
+/// reachable from a saved via the mission's
+/// players (mirrors the .rpm save mechanism).
///
+[Serializable]
public class BTRole
{
private readonly string mKey;
diff --git a/Console/TeslaConsole.BattleTech/BTScoreUpdateEvent.cs b/Console/TeslaConsole.BattleTech/BTScoreUpdateEvent.cs
new file mode 100644
index 0000000..1fc1f67
--- /dev/null
+++ b/Console/TeslaConsole.BattleTech/BTScoreUpdateEvent.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+
+namespace TeslaConsole.BattleTech;
+
+/// A pilot's running score changed (MechScoreUpdateMessage).
+[Serializable]
+internal class BTScoreUpdateEvent : BTMissionEvent
+{
+ public readonly int Score;
+
+ public override IEnumerable InvolvedPilots => new BTPlayer[1] { ReportingPilot };
+
+ public BTScoreUpdateEvent(BTPlayer reportingPilot, TimeSpan missionTime, int score)
+ : base(reportingPilot, missionTime)
+ {
+ Score = score;
+ }
+
+ private BTScoreUpdateEvent()
+ {
+ }
+}
diff --git a/Console/TeslaConsole/TeslaConsoleForm.cs b/Console/TeslaConsole/TeslaConsoleForm.cs
index 69d73b9..70e802a 100644
--- a/Console/TeslaConsole/TeslaConsoleForm.cs
+++ b/Console/TeslaConsole/TeslaConsoleForm.cs
@@ -5,6 +5,7 @@ using System.Drawing.Drawing2D;
using System.Drawing.Printing;
using System.Windows.Forms;
using Munga.Net;
+using TeslaConsole.BattleTech;
using TeslaConsole.RedPlanet;
using WeifenLuo.WinFormsUI.Docking;
@@ -38,6 +39,10 @@ public class TeslaConsoleForm : Form
private ToolStripMenuItem mRpMartianFootball;
+ private ToolStripMenuItem mBtFreeForAll;
+
+ private ToolStripMenuItem mBtNoReturn;
+
private ToolStripMenuItem mPlasmaFontTool;
private ToolStripMenuItem mRpMissionPrintPreview;
@@ -136,15 +141,16 @@ public class TeslaConsoleForm : Form
pod.MungaGame.SetStatus(ImageCache.PodQuestion16, "Waiting For State Update...");
break;
}
- if (pod.MungaGame.AppID.Value != 0)
+ string gameTag = GameTag(pod.MungaGame.AppID.Value);
+ if (gameTag == null)
{
- pod.MungaGame.SetStatus(ImageCache.PodBad16, "Pod Not Running RP");
+ pod.MungaGame.SetStatus(ImageCache.PodBad16, "Unknown Pod Application");
break;
}
switch (pod.MungaGame.AppState.Value)
{
case ApplicationState.InitializingState:
- pod.MungaGame.SetStatus(ImageCache.PodQuestion16, "RP Initalizing");
+ pod.MungaGame.SetStatus(ImageCache.PodQuestion16, gameTag + " Initalizing");
break;
case ApplicationState.WaitingForEgg:
pod.MungaGame.SetStatus(ImageCache.PodOnline16, "Waiting For A Game");
@@ -202,6 +208,26 @@ public class TeslaConsoleForm : Form
}
}
+ ///
+ /// Short display tag for a pod's reported application, or null when the
+ /// console has no game module for it. RPL4 is Red Planet, BTL4 is
+ /// BattleTech; NDL4 (the never-released air-combat game) has no console
+ /// support. The "Initalizing" spelling in the status strings is preserved
+ /// from the original console.
+ ///
+ private static string GameTag(ApplicationID appID)
+ {
+ switch (appID)
+ {
+ case ApplicationID.RPL4:
+ return "RP";
+ case ApplicationID.BTL4:
+ return "BT";
+ default:
+ return null;
+ }
+ }
+
private void redPlanetDeathRaceToolStripMenuItem_Click(object sender, EventArgs e)
{
CreateNewRPGame(footballMode: false);
@@ -219,6 +245,23 @@ public class TeslaConsoleForm : Form
rPGame.Show(mMainDockPanel, DockState.Document);
}
+ private void battleTechFreeForAllToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ CreateNewBTGame(noReturnMode: false);
+ }
+
+ private void battleTechNoReturnToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ CreateNewBTGame(noReturnMode: true);
+ }
+
+ private void CreateNewBTGame(bool noReturnMode)
+ {
+ BTGame bTGame = new BTGame(TeslaConsole.Site.Active, noReturnMode);
+ bTGame.MdiParent = this;
+ bTGame.Show(mMainDockPanel, DockState.Document);
+ }
+
private void plasmaEditorToolStripMenuItem_Click(object sender, EventArgs e)
{
new PlasmaEditor().Show();
@@ -409,6 +452,8 @@ public class TeslaConsoleForm : Form
this.mGamesMenu = new System.Windows.Forms.ToolStripMenuItem();
this.mRpDeathRace = new System.Windows.Forms.ToolStripMenuItem();
this.mRpMartianFootball = new System.Windows.Forms.ToolStripMenuItem();
+ this.mBtFreeForAll = new System.Windows.Forms.ToolStripMenuItem();
+ this.mBtNoReturn = new System.Windows.Forms.ToolStripMenuItem();
this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.aboutToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
this.mExceptionsMenu = new System.Windows.Forms.ToolStripMenuItem();
@@ -540,7 +585,7 @@ public class TeslaConsoleForm : Form
this.enableCustomBitmapsToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
this.enableCustomBitmapsToolStripMenuItem.Text = "Enable Custom Bitmaps";
this.enableCustomBitmapsToolStripMenuItem.Click += new System.EventHandler(enableCustomBitmapsToolStripMenuItem_Click);
- this.mGamesMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[2] { this.mRpDeathRace, this.mRpMartianFootball });
+ this.mGamesMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[4] { this.mRpDeathRace, this.mRpMartianFootball, this.mBtFreeForAll, this.mBtNoReturn });
this.mGamesMenu.Name = "mGamesMenu";
this.mGamesMenu.Size = new System.Drawing.Size(55, 20);
this.mGamesMenu.Text = "Games";
@@ -552,6 +597,14 @@ public class TeslaConsoleForm : Form
this.mRpMartianFootball.Size = new System.Drawing.Size(223, 22);
this.mRpMartianFootball.Text = "Red Planet: Martian Football";
this.mRpMartianFootball.Click += new System.EventHandler(redPlanetMartianFootballToolStripMenuItem_Click);
+ this.mBtFreeForAll.Name = "mBtFreeForAll";
+ this.mBtFreeForAll.Size = new System.Drawing.Size(223, 22);
+ this.mBtFreeForAll.Text = "BattleTech: Free For All";
+ this.mBtFreeForAll.Click += new System.EventHandler(battleTechFreeForAllToolStripMenuItem_Click);
+ this.mBtNoReturn.Name = "mBtNoReturn";
+ this.mBtNoReturn.Size = new System.Drawing.Size(223, 22);
+ this.mBtNoReturn.Text = "BattleTech: No Return";
+ this.mBtNoReturn.Click += new System.EventHandler(battleTechNoReturnToolStripMenuItem_Click);
this.aboutToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[1] { this.aboutToolStripMenuItem1 });
this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem";
this.aboutToolStripMenuItem.Size = new System.Drawing.Size(52, 20);