diff --git a/Console/BattleTech/BTConfig.xml b/Console/BattleTech/BTConfig.xml
index 9b547f0..08f7b32 100644
--- a/Console/BattleTech/BTConfig.xml
+++ b/Console/BattleTech/BTConfig.xml
@@ -64,10 +64,12 @@
+ egg value. The Mac ini tag is "noreturn" and the game's BTL4.RES role
+ resources are named dfltrole/NoReturn; the 4.10 console emitted a broken
+ "noretun" (a dropped character) in every egg on the production box, which
+ cannot resolve against the RES, so the correct spelling is used here. -->
-
+
diff --git a/Console/BattleTech/BTStrings.xml b/Console/BattleTech/BTStrings.xml
new file mode 100644
index 0000000..95e0803
--- /dev/null
+++ b/Console/BattleTech/BTStrings.xml
@@ -0,0 +1,34 @@
+
+
+
+ {time} - Armor plating flakes off as {damager} lightly damages {player}'s mech.
+ {time} - {damager} lands a glancing hit on {player}.
+ {player}'s armor shrugs off a light volley from {damager}.
+ {player} laughs over the comm as {damager} can only scratch {player}'s paint.
+
+ {time} - Armor buckles as {damager} moderately damages {player}'s mech.
+ {player} is still in the fight as {damager} delivers a solid blow to {player}'s mech.
+ {damager} carves a respectable chunk out of {player}'s armor.
+ {time} - {damager} rocks {player}'s cockpit with a moderate impact.
+
+ {time} - Molten armor sprays as {damager} heavily damages {player}'s mech.
+ {player} fights the controls as {damager} nearly cores {player}'s mech.
+ {damager} unloads a devastating alpha strike into {player}'s mech.
+ {time} - Warning klaxons scream in {player}'s cockpit after a heavy impact from {damager}.
+
+ {time} - {damager} delivers a righteous kill to {player}.
+ {damager} stands victorious over the smoking wreckage of {player}'s {vehicle}.
+ {time} - {damager} cores {player}'s reactor. Glory to the victor.
+ The shattered remains of {player}'s {vehicle} litter the arena floor as {damager} salutes.
+
+ {time} - {player} dies without honor as the {vehicle} destroys itself.
+ Shame falls upon {player}, whose {vehicle} is lost to no enemy's hand.
+ {time} - {player}'s {vehicle} overheats catastrophically. A death without honor.
+ {player} learns a hard lesson in mech management as the {vehicle} goes down on its own.
+
+ ...and at the end of the mission it's: {winners} followed by {looser}.
+
diff --git a/Console/RedPlanet/Apps.xml b/Console/RedPlanet/Apps.xml
index de112e5..ec28749 100644
--- a/Console/RedPlanet/Apps.xml
+++ b/Console/RedPlanet/Apps.xml
@@ -53,6 +53,33 @@
hostType="MissionReview" />
+
+
+
+
+
+
+
+/// The BattleTech operator-defaults editor: one column per game mode (Free For
+/// All / No Return), mirroring RPDefaultsDialog's Death Race / Football
+/// layout. OK persists to (BTDefaults.btd). Both
+/// modes share the single BT catalog; the rows are the BT option set (mech,
+/// camo, patch, badge, experience, advanced damage) instead of RP's.
+///
+public class BTDefaultsDialog : Form
+{
+ private IContainer components;
+
+ private TableLayoutPanel mMainTable;
+
+ private Label mFfaHeaderLabel;
+
+ private Label mNoReturnHeaderLabel;
+
+ private Label mMapLabel;
+
+ private Label mWeatherLabel;
+
+ private Label mTimeOfDayLabel;
+
+ private Label mAdvancedDamageLabel;
+
+ private Label mMissionLengthLabel;
+
+ private Label mMechLabel;
+
+ private Label mCamoLabel;
+
+ private Label mPatchLabel;
+
+ private Label mBadgeLabel;
+
+ private Label mExperienceLabel;
+
+ private Label mLaunchDelayLabel;
+
+ private ComboBox mFfaMap;
+
+ private ComboBox mNoReturnMap;
+
+ private ComboBox mFfaWeather;
+
+ private ComboBox mNoReturnWeather;
+
+ private ComboBox mFfaTimeOfDay;
+
+ private ComboBox mNoReturnTimeOfDay;
+
+ private ComboBox mFfaAdvancedDamage;
+
+ private ComboBox mNoReturnAdvancedDamage;
+
+ private MaskedTextBox mFfaMissionLength;
+
+ private MaskedTextBox mNoReturnMissionLength;
+
+ private ComboBox mFfaVehicle;
+
+ private ComboBox mNoReturnVehicle;
+
+ private ComboBox mFfaCamo;
+
+ private ComboBox mNoReturnCamo;
+
+ private ComboBox mFfaPatch;
+
+ private ComboBox mNoReturnPatch;
+
+ private ComboBox mFfaBadge;
+
+ private ComboBox mNoReturnBadge;
+
+ private ComboBox mFfaExperience;
+
+ private ComboBox mNoReturnExperience;
+
+ private NumericUpDown mFfaLaunchDelay;
+
+ private NumericUpDown mNoReturnLaunchDelay;
+
+ private TableLayoutPanel mButtonsTable;
+
+ private Button mCancel;
+
+ private Button mOK;
+
+ private static BTDefaultsDialog mSingletonDialog;
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && components != null)
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ public static void ShowSingleton()
+ {
+ if (mSingletonDialog == null || mSingletonDialog.IsDisposed)
+ {
+ mSingletonDialog = new BTDefaultsDialog();
+ }
+ mSingletonDialog.Show();
+ mSingletonDialog.Focus();
+ mSingletonDialog.WindowState = FormWindowState.Normal;
+ }
+
+ private BTDefaultsDialog()
+ {
+ InitializeComponent();
+ base.Icon = Resources.swirl;
+ BTScenario scenario = BTConfig.FreeForAll;
+ BuildColumn(scenario, BTDefaults.FreeForAll, mFfaMap, mFfaWeather, mFfaTimeOfDay, mFfaAdvancedDamage, mFfaMissionLength, mFfaVehicle, mFfaCamo, mFfaPatch, mFfaBadge, mFfaExperience, mFfaLaunchDelay);
+ BuildColumn(scenario, BTDefaults.NoReturn, mNoReturnMap, mNoReturnWeather, mNoReturnTimeOfDay, mNoReturnAdvancedDamage, mNoReturnMissionLength, mNoReturnVehicle, mNoReturnCamo, mNoReturnPatch, mNoReturnBadge, mNoReturnExperience, mNoReturnLaunchDelay);
+ }
+
+ private static void BuildColumn(BTScenario scenario, BTDefaults.BattleDefaults defaults, ComboBox map, ComboBox weather, ComboBox timeOfDay, ComboBox advancedDamage, MaskedTextBox missionLength, ComboBox vehicle, ComboBox camo, ComboBox patch, ComboBox badge, ComboBox experience, NumericUpDown launchDelay)
+ {
+ BuildNamedOption(map, scenario.Maps.Keys, scenario.Maps.Values, defaults.MapKey);
+ BuildNamedOption(weather, scenario.Weather.Keys, scenario.Weather.Values, defaults.WeatherKey);
+ BuildGenericOption(timeOfDay, scenario.TimesOfDay, defaults.TimeOfDayKey);
+ BuildOnOffOptions(advancedDamage, defaults.AdvancedDamage);
+ BuildMissionLengthControl(missionLength, defaults.MissionLength);
+ BuildNamedOption(vehicle, scenario.Vehicles.Keys, scenario.Vehicles.Values, defaults.VehicleKey);
+ BuildGenericOption(camo, scenario.Colors, defaults.CamoKey);
+ BuildGenericOption(patch, scenario.Patches, defaults.PatchKey);
+ BuildGenericOption(badge, scenario.Badges, defaults.EmblemKey);
+ BuildGenericOption(experience, scenario.Experiences, defaults.ExperienceKey);
+ launchDelay.Value = defaults.LaunchDelay;
+ }
+
+ private static void BuildOnOffOptions(ComboBox comboBox, bool defaultValue)
+ {
+ comboBox.DisplayMember = "Value";
+ comboBox.ValueMember = "Key";
+ comboBox.Items.Add(new KeyValuePair(key: false, "Off"));
+ comboBox.Items.Add(new KeyValuePair(key: true, "On"));
+ comboBox.SelectedIndex = (defaultValue ? 1 : 0);
+ }
+
+ private static void BuildMissionLengthControl(MaskedTextBox maskedTextBox, TimeSpan defaultValue)
+ {
+ maskedTextBox.Mask = "00:00:00";
+ maskedTextBox.ValidatingType = typeof(TimeSpan);
+ maskedTextBox.Text = defaultValue.ToString();
+ }
+
+ ///
+ /// Fills a combo from a keyed catalog of objects whose Name property is the
+ /// display text and whose ToString returns it (BTMap/BTVehicle/BTWeather).
+ ///
+ private static void BuildNamedOption(ComboBox comboBox, IEnumerable keys, IEnumerable values, string defaultKey)
+ {
+ int selectedIndex = 0;
+ int num = 0;
+ comboBox.DisplayMember = "Name";
+ comboBox.ValueMember = "Key";
+ IEnumerator keyEnumerator = keys.GetEnumerator();
+ foreach (T value in values)
+ {
+ keyEnumerator.MoveNext();
+ comboBox.Items.Add(value);
+ if (keyEnumerator.Current == defaultKey)
+ {
+ selectedIndex = num;
+ }
+ num++;
+ }
+ comboBox.SelectedIndex = selectedIndex;
+ }
+
+ private static void BuildGenericOption(ComboBox comboBox, IEnumerable> options, string defaultKey)
+ {
+ int selectedIndex = 0;
+ int num = 0;
+ comboBox.DisplayMember = "Value";
+ comboBox.ValueMember = "Key";
+ foreach (KeyValuePair option in options)
+ {
+ comboBox.Items.Add(option);
+ if (option.Key == defaultKey)
+ {
+ selectedIndex = num;
+ }
+ num++;
+ }
+ comboBox.SelectedIndex = selectedIndex;
+ }
+
+ private void mCancel_Click(object sender, EventArgs e)
+ {
+ Close();
+ }
+
+ private void mOK_Click(object sender, EventArgs e)
+ {
+ SaveColumn(BTDefaults.FreeForAll, mFfaMap, mFfaWeather, mFfaTimeOfDay, mFfaAdvancedDamage, mFfaMissionLength, mFfaVehicle, mFfaCamo, mFfaPatch, mFfaBadge, mFfaExperience, mFfaLaunchDelay);
+ SaveColumn(BTDefaults.NoReturn, mNoReturnMap, mNoReturnWeather, mNoReturnTimeOfDay, mNoReturnAdvancedDamage, mNoReturnMissionLength, mNoReturnVehicle, mNoReturnCamo, mNoReturnPatch, mNoReturnBadge, mNoReturnExperience, mNoReturnLaunchDelay);
+ BTDefaults.Save();
+ Hide();
+ }
+
+ private static void SaveColumn(BTDefaults.BattleDefaults defaults, ComboBox map, ComboBox weather, ComboBox timeOfDay, ComboBox advancedDamage, MaskedTextBox missionLength, ComboBox vehicle, ComboBox camo, ComboBox patch, ComboBox badge, ComboBox experience, NumericUpDown launchDelay)
+ {
+ defaults.MapKey = ((BTMap)map.SelectedItem).Key;
+ defaults.WeatherKey = ((BTWeather)weather.SelectedItem).Key;
+ defaults.TimeOfDayKey = ExtractSelectedKey(timeOfDay);
+ defaults.AdvancedDamage = ExtractSelectedKey(advancedDamage);
+ defaults.MissionLength = (TimeSpan)missionLength.ValidateText();
+ defaults.VehicleKey = ((BTVehicle)vehicle.SelectedItem).Key;
+ defaults.CamoKey = ExtractSelectedKey(camo);
+ defaults.PatchKey = ExtractSelectedKey(patch);
+ defaults.EmblemKey = ExtractSelectedKey(badge);
+ defaults.ExperienceKey = ExtractSelectedKey(experience);
+ defaults.LaunchDelay = (int)launchDelay.Value;
+ }
+
+ private static T ExtractSelectedKey(ComboBox comboBox)
+ {
+ if (comboBox.SelectedItem is KeyValuePair)
+ {
+ return ((KeyValuePair)comboBox.SelectedItem).Key;
+ }
+ return (T)comboBox.SelectedItem;
+ }
+
+ private void InitializeComponent()
+ {
+ this.mMainTable = new System.Windows.Forms.TableLayoutPanel();
+ this.mFfaHeaderLabel = new System.Windows.Forms.Label();
+ this.mNoReturnHeaderLabel = new System.Windows.Forms.Label();
+ this.mMapLabel = new System.Windows.Forms.Label();
+ this.mWeatherLabel = new System.Windows.Forms.Label();
+ this.mTimeOfDayLabel = new System.Windows.Forms.Label();
+ this.mAdvancedDamageLabel = new System.Windows.Forms.Label();
+ this.mMissionLengthLabel = new System.Windows.Forms.Label();
+ this.mMechLabel = new System.Windows.Forms.Label();
+ this.mCamoLabel = new System.Windows.Forms.Label();
+ this.mPatchLabel = new System.Windows.Forms.Label();
+ this.mBadgeLabel = new System.Windows.Forms.Label();
+ this.mExperienceLabel = new System.Windows.Forms.Label();
+ this.mLaunchDelayLabel = new System.Windows.Forms.Label();
+ this.mFfaMap = new System.Windows.Forms.ComboBox();
+ this.mNoReturnMap = new System.Windows.Forms.ComboBox();
+ this.mFfaWeather = new System.Windows.Forms.ComboBox();
+ this.mNoReturnWeather = new System.Windows.Forms.ComboBox();
+ this.mFfaTimeOfDay = new System.Windows.Forms.ComboBox();
+ this.mNoReturnTimeOfDay = new System.Windows.Forms.ComboBox();
+ this.mFfaAdvancedDamage = new System.Windows.Forms.ComboBox();
+ this.mNoReturnAdvancedDamage = new System.Windows.Forms.ComboBox();
+ this.mFfaMissionLength = new System.Windows.Forms.MaskedTextBox();
+ this.mNoReturnMissionLength = new System.Windows.Forms.MaskedTextBox();
+ this.mFfaVehicle = new System.Windows.Forms.ComboBox();
+ this.mNoReturnVehicle = new System.Windows.Forms.ComboBox();
+ this.mFfaCamo = new System.Windows.Forms.ComboBox();
+ this.mNoReturnCamo = new System.Windows.Forms.ComboBox();
+ this.mFfaPatch = new System.Windows.Forms.ComboBox();
+ this.mNoReturnPatch = new System.Windows.Forms.ComboBox();
+ this.mFfaBadge = new System.Windows.Forms.ComboBox();
+ this.mNoReturnBadge = new System.Windows.Forms.ComboBox();
+ this.mFfaExperience = new System.Windows.Forms.ComboBox();
+ this.mNoReturnExperience = new System.Windows.Forms.ComboBox();
+ this.mFfaLaunchDelay = new System.Windows.Forms.NumericUpDown();
+ this.mNoReturnLaunchDelay = new System.Windows.Forms.NumericUpDown();
+ this.mButtonsTable = new System.Windows.Forms.TableLayoutPanel();
+ this.mCancel = new System.Windows.Forms.Button();
+ this.mOK = new System.Windows.Forms.Button();
+ this.mMainTable.SuspendLayout();
+ this.mButtonsTable.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)this.mFfaLaunchDelay).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)this.mNoReturnLaunchDelay).BeginInit();
+ base.SuspendLayout();
+ this.mMainTable.ColumnCount = 3;
+ this.mMainTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
+ this.mMainTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50f));
+ this.mMainTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50f));
+ this.mMainTable.Controls.Add(this.mFfaHeaderLabel, 1, 0);
+ this.mMainTable.Controls.Add(this.mNoReturnHeaderLabel, 2, 0);
+ this.mMainTable.Controls.Add(this.mMapLabel, 0, 1);
+ this.mMainTable.Controls.Add(this.mFfaMap, 1, 1);
+ this.mMainTable.Controls.Add(this.mNoReturnMap, 2, 1);
+ this.mMainTable.Controls.Add(this.mWeatherLabel, 0, 2);
+ this.mMainTable.Controls.Add(this.mFfaWeather, 1, 2);
+ this.mMainTable.Controls.Add(this.mNoReturnWeather, 2, 2);
+ this.mMainTable.Controls.Add(this.mTimeOfDayLabel, 0, 3);
+ this.mMainTable.Controls.Add(this.mFfaTimeOfDay, 1, 3);
+ this.mMainTable.Controls.Add(this.mNoReturnTimeOfDay, 2, 3);
+ this.mMainTable.Controls.Add(this.mAdvancedDamageLabel, 0, 4);
+ this.mMainTable.Controls.Add(this.mFfaAdvancedDamage, 1, 4);
+ this.mMainTable.Controls.Add(this.mNoReturnAdvancedDamage, 2, 4);
+ this.mMainTable.Controls.Add(this.mMissionLengthLabel, 0, 5);
+ this.mMainTable.Controls.Add(this.mFfaMissionLength, 1, 5);
+ this.mMainTable.Controls.Add(this.mNoReturnMissionLength, 2, 5);
+ this.mMainTable.Controls.Add(this.mMechLabel, 0, 6);
+ this.mMainTable.Controls.Add(this.mFfaVehicle, 1, 6);
+ this.mMainTable.Controls.Add(this.mNoReturnVehicle, 2, 6);
+ this.mMainTable.Controls.Add(this.mCamoLabel, 0, 7);
+ this.mMainTable.Controls.Add(this.mFfaCamo, 1, 7);
+ this.mMainTable.Controls.Add(this.mNoReturnCamo, 2, 7);
+ this.mMainTable.Controls.Add(this.mPatchLabel, 0, 8);
+ this.mMainTable.Controls.Add(this.mFfaPatch, 1, 8);
+ this.mMainTable.Controls.Add(this.mNoReturnPatch, 2, 8);
+ this.mMainTable.Controls.Add(this.mBadgeLabel, 0, 9);
+ this.mMainTable.Controls.Add(this.mFfaBadge, 1, 9);
+ this.mMainTable.Controls.Add(this.mNoReturnBadge, 2, 9);
+ this.mMainTable.Controls.Add(this.mExperienceLabel, 0, 10);
+ this.mMainTable.Controls.Add(this.mFfaExperience, 1, 10);
+ this.mMainTable.Controls.Add(this.mNoReturnExperience, 2, 10);
+ this.mMainTable.Controls.Add(this.mLaunchDelayLabel, 0, 11);
+ this.mMainTable.Controls.Add(this.mFfaLaunchDelay, 1, 11);
+ this.mMainTable.Controls.Add(this.mNoReturnLaunchDelay, 2, 11);
+ this.mMainTable.Controls.Add(this.mButtonsTable, 0, 12);
+ this.mMainTable.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.mMainTable.Location = new System.Drawing.Point(3, 3);
+ this.mMainTable.Name = "mMainTable";
+ this.mMainTable.RowCount = 13;
+ for (int i = 0; i < 12; i++)
+ {
+ this.mMainTable.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ }
+ this.mMainTable.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100f));
+ this.mMainTable.Size = new System.Drawing.Size(478, 384);
+ this.mMainTable.TabIndex = 0;
+ this.mFfaHeaderLabel.Anchor = System.Windows.Forms.AnchorStyles.None;
+ this.mFfaHeaderLabel.AutoSize = true;
+ this.mFfaHeaderLabel.Name = "mFfaHeaderLabel";
+ this.mFfaHeaderLabel.Text = "Free For All";
+ this.mNoReturnHeaderLabel.Anchor = System.Windows.Forms.AnchorStyles.None;
+ this.mNoReturnHeaderLabel.AutoSize = true;
+ this.mNoReturnHeaderLabel.Name = "mNoReturnHeaderLabel";
+ this.mNoReturnHeaderLabel.Text = "No Return";
+ ConfigureRowLabel(this.mMapLabel, "mMapLabel", "Map:");
+ ConfigureRowLabel(this.mWeatherLabel, "mWeatherLabel", "Weather:");
+ ConfigureRowLabel(this.mTimeOfDayLabel, "mTimeOfDayLabel", "Time Of Day:");
+ ConfigureRowLabel(this.mAdvancedDamageLabel, "mAdvancedDamageLabel", "Advanced Damage:");
+ ConfigureRowLabel(this.mMissionLengthLabel, "mMissionLengthLabel", "Mission Length:");
+ ConfigureRowLabel(this.mMechLabel, "mMechLabel", "Mech:");
+ ConfigureRowLabel(this.mCamoLabel, "mCamoLabel", "Camo:");
+ ConfigureRowLabel(this.mPatchLabel, "mPatchLabel", "Patch:");
+ ConfigureRowLabel(this.mBadgeLabel, "mBadgeLabel", "Badge:");
+ ConfigureRowLabel(this.mExperienceLabel, "mExperienceLabel", "Experience:");
+ ConfigureRowLabel(this.mLaunchDelayLabel, "mLaunchDelayLabel", "Autotranslocate Delay:");
+ ConfigureOptionCombo(this.mFfaMap, "mFfaMap");
+ ConfigureOptionCombo(this.mNoReturnMap, "mNoReturnMap");
+ ConfigureOptionCombo(this.mFfaWeather, "mFfaWeather");
+ ConfigureOptionCombo(this.mNoReturnWeather, "mNoReturnWeather");
+ ConfigureOptionCombo(this.mFfaTimeOfDay, "mFfaTimeOfDay");
+ ConfigureOptionCombo(this.mNoReturnTimeOfDay, "mNoReturnTimeOfDay");
+ ConfigureOptionCombo(this.mFfaAdvancedDamage, "mFfaAdvancedDamage");
+ ConfigureOptionCombo(this.mNoReturnAdvancedDamage, "mNoReturnAdvancedDamage");
+ ConfigureOptionCombo(this.mFfaVehicle, "mFfaVehicle");
+ ConfigureOptionCombo(this.mNoReturnVehicle, "mNoReturnVehicle");
+ ConfigureOptionCombo(this.mFfaCamo, "mFfaCamo");
+ ConfigureOptionCombo(this.mNoReturnCamo, "mNoReturnCamo");
+ ConfigureOptionCombo(this.mFfaPatch, "mFfaPatch");
+ ConfigureOptionCombo(this.mNoReturnPatch, "mNoReturnPatch");
+ ConfigureOptionCombo(this.mFfaBadge, "mFfaBadge");
+ ConfigureOptionCombo(this.mNoReturnBadge, "mNoReturnBadge");
+ ConfigureOptionCombo(this.mFfaExperience, "mFfaExperience");
+ ConfigureOptionCombo(this.mNoReturnExperience, "mNoReturnExperience");
+ this.mFfaMissionLength.Anchor = System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
+ this.mFfaMissionLength.Name = "mFfaMissionLength";
+ this.mNoReturnMissionLength.Anchor = System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
+ this.mNoReturnMissionLength.Name = "mNoReturnMissionLength";
+ this.mFfaLaunchDelay.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.mFfaLaunchDelay.Name = "mFfaLaunchDelay";
+ this.mNoReturnLaunchDelay.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.mNoReturnLaunchDelay.Name = "mNoReturnLaunchDelay";
+ this.mButtonsTable.ColumnCount = 2;
+ this.mMainTable.SetColumnSpan(this.mButtonsTable, 3);
+ this.mButtonsTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100f));
+ this.mButtonsTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
+ this.mButtonsTable.Controls.Add(this.mCancel, 1, 0);
+ this.mButtonsTable.Controls.Add(this.mOK, 0, 0);
+ this.mButtonsTable.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.mButtonsTable.Margin = new System.Windows.Forms.Padding(0);
+ this.mButtonsTable.Name = "mButtonsTable";
+ this.mButtonsTable.RowCount = 1;
+ this.mButtonsTable.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100f));
+ this.mButtonsTable.Size = new System.Drawing.Size(478, 44);
+ this.mButtonsTable.TabIndex = 27;
+ this.mCancel.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right;
+ this.mCancel.Name = "mCancel";
+ this.mCancel.Size = new System.Drawing.Size(75, 22);
+ this.mCancel.TabIndex = 1;
+ this.mCancel.Text = "&Cancel";
+ this.mCancel.UseVisualStyleBackColor = true;
+ this.mCancel.Click += new System.EventHandler(mCancel_Click);
+ this.mOK.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right;
+ this.mOK.Name = "mOK";
+ this.mOK.Size = new System.Drawing.Size(75, 22);
+ this.mOK.TabIndex = 0;
+ this.mOK.Text = "&OK";
+ this.mOK.UseVisualStyleBackColor = true;
+ this.mOK.Click += new System.EventHandler(mOK_Click);
+ base.AcceptButton = this.mOK;
+ base.AutoScaleDimensions = new System.Drawing.SizeF(6f, 13f);
+ base.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ base.ClientSize = new System.Drawing.Size(484, 390);
+ base.Controls.Add(this.mMainTable);
+ base.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ base.MaximizeBox = false;
+ base.Name = "BTDefaultsDialog";
+ base.Padding = new System.Windows.Forms.Padding(3);
+ this.Text = "BattleTech Defaults";
+ this.mMainTable.ResumeLayout(false);
+ this.mMainTable.PerformLayout();
+ this.mButtonsTable.ResumeLayout(false);
+ ((System.ComponentModel.ISupportInitialize)this.mFfaLaunchDelay).EndInit();
+ ((System.ComponentModel.ISupportInitialize)this.mNoReturnLaunchDelay).EndInit();
+ base.ResumeLayout(false);
+ }
+
+ private static void ConfigureRowLabel(Label label, string name, string text)
+ {
+ label.Anchor = AnchorStyles.Right;
+ label.AutoSize = true;
+ label.Name = name;
+ label.Text = text;
+ }
+
+ private static void ConfigureOptionCombo(ComboBox comboBox, string name)
+ {
+ comboBox.Anchor = AnchorStyles.Left | AnchorStyles.Right;
+ comboBox.DropDownStyle = ComboBoxStyle.DropDownList;
+ comboBox.FormattingEnabled = true;
+ comboBox.Name = name;
+ }
+}
diff --git a/Console/TeslaConsole.BattleTech/BTGame.cs b/Console/TeslaConsole.BattleTech/BTGame.cs
index 7ed9911..dd26e81 100644
--- a/Console/TeslaConsole.BattleTech/BTGame.cs
+++ b/Console/TeslaConsole.BattleTech/BTGame.cs
@@ -166,6 +166,10 @@ internal class BTGame : DockContent
private ToolStripMenuItem resetToolStripMenuItem;
+ private Button mPrintLastMission;
+
+ private CheckBox mAutoPrint;
+
private CheckBox mAutoTranslocateCheckbox;
private Button mRandomMap;
@@ -807,19 +811,40 @@ internal class BTGame : DockContent
}
Program.LogExceptionAndShowDialog(ex, "Mission results failed to save.", "Error Saving Mission Results");
}
+ if (mAutoPrint.Checked)
+ {
+ try
+ {
+ mLastMissionResults.GetPrintDocument().Print();
+ }
+ catch (Exception ex2)
+ {
+ if (Debugger.IsAttached)
+ {
+ throw;
+ }
+ Program.LogExceptionAndShowDialog(ex2, "Mission results failed to print.", "Error Printing Mission Results");
+ }
+ }
+ mPrintLastMission.Enabled = true;
}
- catch (Exception ex2)
+ catch (Exception ex3)
{
if (Debugger.IsAttached)
{
throw;
}
- Program.LogExceptionAndShowDialog(ex2, "Failed to create mission results.", "Error Creating Mission Results");
+ Program.LogExceptionAndShowDialog(ex3, "Failed to create mission results.", "Error Creating Mission Results");
}
mMissionRecorder = null;
mMissionPlayers = null;
}
+ private void mPrintLastMission_Click(object sender, EventArgs e)
+ {
+ mLastMissionResults.GetPrintDocument().Print();
+ }
+
private void SwitchControlsMode(bool editMode)
{
mMap.Enabled = editMode;
@@ -1267,6 +1292,8 @@ internal class BTGame : DockContent
this.mGoButton = new System.Windows.Forms.Button();
this.mResetContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
this.resetToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.mPrintLastMission = new System.Windows.Forms.Button();
+ this.mAutoPrint = new System.Windows.Forms.CheckBox();
this.mAutoTranslocateCheckbox = new System.Windows.Forms.CheckBox();
this.mRandomMap = new System.Windows.Forms.Button();
this.mRandomWeather = new System.Windows.Forms.Button();
@@ -1326,6 +1353,8 @@ internal class BTGame : DockContent
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.mPrintLastMission, 6, 2);
+ this.mMissionPropertiesTable.Controls.Add(this.mAutoPrint, 6, 1);
this.mMissionPropertiesTable.Controls.Add(this.mAutoTranslocateCheckbox, 6, 0);
this.mMissionPropertiesTable.Controls.Add(this.mRandomMap, 2, 0);
this.mMissionPropertiesTable.Controls.Add(this.mRandomWeather, 2, 1);
@@ -1440,6 +1469,24 @@ internal class BTGame : DockContent
this.resetToolStripMenuItem.Size = new System.Drawing.Size(102, 22);
this.resetToolStripMenuItem.Text = "&Reset";
this.resetToolStripMenuItem.Click += new System.EventHandler(resetToolStripMenuItem_Click);
+ this.mPrintLastMission.Anchor = System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
+ this.mPrintLastMission.AutoSize = true;
+ this.mPrintLastMission.Enabled = false;
+ this.mPrintLastMission.Location = new System.Drawing.Point(529, 61);
+ this.mPrintLastMission.Name = "mPrintLastMission";
+ this.mPrintLastMission.Size = new System.Drawing.Size(107, 23);
+ this.mPrintLastMission.TabIndex = 11;
+ this.mPrintLastMission.Text = "Print Last Mission";
+ this.mPrintLastMission.UseVisualStyleBackColor = true;
+ this.mPrintLastMission.Click += new System.EventHandler(mPrintLastMission_Click);
+ this.mAutoPrint.Anchor = System.Windows.Forms.AnchorStyles.Left;
+ this.mAutoPrint.AutoSize = true;
+ this.mAutoPrint.Location = new System.Drawing.Point(529, 35);
+ this.mAutoPrint.Name = "mAutoPrint";
+ this.mAutoPrint.Size = new System.Drawing.Size(72, 17);
+ this.mAutoPrint.TabIndex = 9;
+ this.mAutoPrint.Text = "Auto Print";
+ this.mAutoPrint.UseVisualStyleBackColor = true;
this.mAutoTranslocateCheckbox.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.mAutoTranslocateCheckbox.AutoSize = true;
this.mAutoTranslocateCheckbox.Location = new System.Drawing.Point(529, 6);
diff --git a/Console/TeslaConsole.BattleTech/BTMissionResults.cs b/Console/TeslaConsole.BattleTech/BTMissionResults.cs
index dc6698f..dd99366 100644
--- a/Console/TeslaConsole.BattleTech/BTMissionResults.cs
+++ b/Console/TeslaConsole.BattleTech/BTMissionResults.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Drawing.Printing;
using System.IO;
using System.IO.Compression;
using System.Runtime.Serialization.Formatters.Binary;
@@ -9,9 +10,8 @@ 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.
+/// RPMissionResults minus the football branches (BT battle modes have
+/// no teams, so every ranking entry is a single pilot).
///
[Serializable]
internal class BTMissionResults
@@ -104,4 +104,41 @@ internal class BTMissionResults
}
return num;
}
+
+ public BTPlayer[][] GetChartOrder()
+ {
+ return GetChartOrder(TimeSpan.MaxValue);
+ }
+
+ public BTPlayer[][] GetChartOrder(TimeSpan gameTime)
+ {
+ List> list = new List>();
+ foreach (BTPlayer player in Mission.Players)
+ {
+ list.Add(new Tuple(new BTPlayer[1] { player }, GetScore(player, gameTime)));
+ }
+ for (int i = 0; i < list.Count - 1; i++)
+ {
+ for (int j = i + 1; j < list.Count; j++)
+ {
+ if (list[i].B < list[j].B || (list[i].B == list[j].B && string.CompareOrdinal(list[i].A[0].Name, list[j].A[0].Name) > 0))
+ {
+ Tuple value = list[i];
+ list[i] = list[j];
+ list[j] = value;
+ }
+ }
+ }
+ List list2 = new List();
+ foreach (Tuple item in list)
+ {
+ list2.Add(item.A);
+ }
+ return list2.ToArray();
+ }
+
+ public PrintDocument GetPrintDocument()
+ {
+ return new BTPrintDocument(this);
+ }
}
diff --git a/Console/TeslaConsole.BattleTech/BTPrintDocument.cs b/Console/TeslaConsole.BattleTech/BTPrintDocument.cs
new file mode 100644
index 0000000..00dad51
--- /dev/null
+++ b/Console/TeslaConsole.BattleTech/BTPrintDocument.cs
@@ -0,0 +1,748 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Printing;
+using System.Text;
+
+namespace TeslaConsole.BattleTech;
+
+///
+/// The BattleTech score-sheet print document: one landscape page per pilot with
+/// the mech portrait, placing, kill/death/damage stats, a randomized
+/// mission-highlights narrative (), the pilot-vs-pilot
+/// damage matrix, and the place-over-time chart. A close mirror of
+/// RPPrintDocument minus the football branches and the RP-only
+/// lap/boost/score-zone concepts; the chart marks kills and deaths only.
+///
+public class BTPrintDocument : PrintDocument
+{
+ private const int sThinBorderSize = 3;
+
+ private const int sThickBorderSize = 14;
+
+ private const int sChampherSize = 14;
+
+ private const double sSmallRectWidthDropFraction = 0.5721493440968718;
+
+ private const double sSmallRectHeightDropFraction = 245.0 / 372.0;
+
+ private const string sSansSerifFontName = "Helvetica LT Std";
+
+ private const string sSerifFontName = "Courier New";
+
+ private readonly BTMissionResults mMissionResults;
+
+ private readonly BTPlayer[][] mFinalRanking;
+
+ private readonly BTPlayer[] mPrintOrder;
+
+ private int mCurrentPlayer;
+
+ private Dictionary> mPlayerLines;
+
+ private int[] mChartRows;
+
+ private Dictionary mChartCols;
+
+ internal BTPrintDocument(BTMissionResults missionResults)
+ {
+ mMissionResults = missionResults;
+ bool noReturn = false;
+ foreach (BTPlayer player in mMissionResults.Mission.Players)
+ {
+ if (player.Role.Key == "NoReturn")
+ {
+ noReturn = true;
+ break;
+ }
+ }
+ base.DocumentName = string.Format("BattleTech {0} mission at {1} on {2}", noReturn ? "No Return" : "Free For All", mMissionResults.MissionStart.ToLongTimeString(), mMissionResults.MissionStart.ToLongDateString());
+ mFinalRanking = mMissionResults.GetChartOrder();
+ List list = new List();
+ for (int i = 0; i < mFinalRanking.Length; i++)
+ {
+ list.Add(mFinalRanking[i][0]);
+ }
+ for (int j = 0; j < mFinalRanking.Length; j++)
+ {
+ for (int k = 1; k < mFinalRanking[j].Length; k++)
+ {
+ list.Add(mFinalRanking[j][k]);
+ }
+ }
+ mPrintOrder = list.ToArray();
+ }
+
+ protected override void OnQueryPageSettings(QueryPageSettingsEventArgs e)
+ {
+ e.PageSettings.Margins = new Margins(50, 50, 50, 50);
+ e.PageSettings.Landscape = true;
+ base.OnQueryPageSettings(e);
+ }
+
+ protected override void OnBeginPrint(PrintEventArgs e)
+ {
+ mCurrentPlayer = 0;
+ base.OnBeginPrint(e);
+ }
+
+ protected override void OnPrintPage(PrintPageEventArgs e)
+ {
+ BTPlayer bTPlayer = mPrintOrder[mCurrentPlayer];
+ List list = new List();
+ foreach (BTMissionEvent @event in mMissionResults.Events)
+ {
+ if (Contains(@event.InvolvedPilots, bTPlayer))
+ {
+ list.Add(@event);
+ }
+ }
+ for (int i = 0; i < list.Count - 1; i++)
+ {
+ for (int j = i + 1; j < list.Count; j++)
+ {
+ if (list[i].GameTime > list[j].GameTime)
+ {
+ BTMissionEvent value = list[i];
+ list[i] = list[j];
+ list[j] = value;
+ }
+ }
+ }
+ int score = mMissionResults.GetScore(bTPlayer);
+ int finalPlace = mMissionResults.GetFinalPlace(bTPlayer);
+ Size size = new Size(e.PageBounds.Width - 100, e.PageBounds.Height - 100);
+ if (size.Width > e.MarginBounds.Width)
+ {
+ size.Width = e.MarginBounds.Width;
+ }
+ if (size.Height > e.MarginBounds.Height)
+ {
+ size.Height = e.MarginBounds.Height;
+ }
+ Rectangle rectangle = new Rectangle((e.MarginBounds.Width - size.Width) / 2 + e.MarginBounds.Left, (e.MarginBounds.Height - size.Height) / 2 + e.MarginBounds.Top, size.Width, size.Height);
+ Rectangle inputRect = rectangle;
+ inputRect.Inflate(-14, -14);
+ Rectangle rectangle2 = rectangle;
+ rectangle2.Inflate(-3, -3);
+ Rectangle inputRect2 = rectangle2;
+ inputRect2.Inflate(-14, -14);
+ Rectangle rectangle3 = rectangle2;
+ rectangle3.Inflate(-7, -7);
+ Rectangle inputRect3 = rectangle3;
+ inputRect3.Inflate(-14, -14);
+ Rectangle rectangle4 = rectangle2;
+ rectangle4.Inflate(-14, -14);
+ Rectangle inputRect4 = rectangle4;
+ inputRect4.Inflate(-14, -14);
+ Rectangle rectangle5 = rectangle4;
+ rectangle5.Inflate(-3, -3);
+ Rectangle inputRect5 = rectangle5;
+ inputRect5.Inflate(-14, -14);
+ int widthDrop = (int)(0.5721493440968718 * (double)rectangle3.Width + 0.5);
+ int heightDrop = (int)(245.0 / 372.0 * (double)rectangle3.Height + 0.5);
+ Rectangle rectangle6 = RectDrop(rectangle, widthDrop, heightDrop);
+ Rectangle rectangle7 = RectDrop(inputRect, widthDrop, heightDrop);
+ Rectangle rectangle8 = RectDrop(rectangle2, widthDrop, heightDrop);
+ Rectangle rectangle9 = RectDrop(inputRect2, widthDrop, heightDrop);
+ Rectangle rectangle10 = RectDrop(rectangle3, widthDrop, heightDrop);
+ Rectangle rectangle11 = RectDrop(inputRect3, widthDrop, heightDrop);
+ Rectangle rectangle12 = RectDrop(rectangle4, widthDrop, heightDrop);
+ Rectangle rectangle13 = RectDrop(inputRect4, widthDrop, heightDrop);
+ Rectangle rectangle14 = RectDrop(rectangle5, widthDrop, heightDrop);
+ Rectangle rectangle15 = RectDrop(inputRect5, widthDrop, heightDrop);
+ using (GraphicsPath graphicsPath = new GraphicsPath())
+ {
+ graphicsPath.AddLine(rectangle.Left, inputRect.Bottom, rectangle.Left, inputRect.Top);
+ graphicsPath.AddLine(inputRect.Left, rectangle.Top, inputRect.Right, rectangle.Top);
+ graphicsPath.AddLine(rectangle3.Right, rectangle3.Top, inputRect3.Left, rectangle3.Top);
+ graphicsPath.AddLine(rectangle3.Left, inputRect3.Top, rectangle3.Left, rectangle3.Bottom);
+ graphicsPath.StartFigure();
+ graphicsPath.AddLine(rectangle3.Left, inputRect5.Bottom, rectangle5.Left, inputRect5.Bottom);
+ graphicsPath.AddLine(inputRect5.Left, rectangle5.Bottom, inputRect5.Right, rectangle5.Bottom);
+ graphicsPath.AddLine(rectangle5.Right, inputRect5.Bottom, rectangle5.Right, rectangle3.Top);
+ graphicsPath.AddLine(rectangle3.Right, rectangle3.Top, rectangle3.Right, inputRect3.Bottom);
+ graphicsPath.AddLine(inputRect3.Right, rectangle3.Bottom, rectangle3.Left, rectangle3.Bottom);
+ graphicsPath.StartFigure();
+ graphicsPath.AddLine(rectangle10.Left, rectangle15.Bottom, rectangle14.Left, rectangle15.Bottom);
+ graphicsPath.AddLine(rectangle15.Left, rectangle14.Bottom, rectangle15.Right, rectangle14.Bottom);
+ graphicsPath.AddLine(rectangle14.Right, rectangle15.Bottom, rectangle14.Right, rectangle10.Top);
+ graphicsPath.AddLine(rectangle10.Right, rectangle10.Top, rectangle10.Right, rectangle11.Bottom);
+ graphicsPath.AddLine(rectangle11.Right, rectangle10.Bottom, rectangle10.Left, rectangle10.Bottom);
+ e.Graphics.FillPath(Brushes.LightGray, graphicsPath);
+ }
+ using (GraphicsPath graphicsPath2 = new GraphicsPath())
+ {
+ graphicsPath2.AddLine(rectangle2.Left, inputRect2.Bottom, rectangle.Left, inputRect.Bottom);
+ graphicsPath2.AddLine(inputRect.Left, rectangle.Bottom, inputRect.Right, rectangle.Bottom);
+ graphicsPath2.AddLine(rectangle.Right, inputRect.Bottom, rectangle.Right, inputRect.Top);
+ graphicsPath2.AddLine(inputRect.Right, rectangle.Top, inputRect2.Right, rectangle2.Top);
+ graphicsPath2.AddLine(inputRect2.Right, rectangle3.Top, rectangle3.Right, inputRect3.Top);
+ graphicsPath2.AddLine(rectangle3.Right, inputRect3.Bottom, inputRect3.Right, rectangle3.Bottom);
+ graphicsPath2.AddLine(inputRect2.Left, rectangle3.Bottom, rectangle3.Left, inputRect2.Bottom);
+ graphicsPath2.StartFigure();
+ graphicsPath2.AddLine(rectangle12.Left, rectangle13.Bottom, rectangle14.Left, rectangle15.Bottom);
+ graphicsPath2.AddLine(rectangle14.Left, rectangle15.Top, rectangle15.Left, rectangle14.Top);
+ graphicsPath2.AddLine(rectangle15.Right, rectangle14.Top, rectangle14.Right, rectangle15.Top);
+ graphicsPath2.AddLine(rectangle12.Right, rectangle13.Top, rectangle10.Right, rectangle13.Top);
+ graphicsPath2.AddLine(rectangle10.Right, rectangle10.Top, rectangle11.Left, rectangle10.Top);
+ graphicsPath2.AddLine(rectangle10.Left, rectangle11.Top, rectangle10.Left, rectangle13.Bottom);
+ graphicsPath2.StartFigure();
+ graphicsPath2.AddLine(rectangle4.Left, inputRect4.Bottom, rectangle5.Left, inputRect5.Bottom);
+ graphicsPath2.AddLine(rectangle5.Left, rectangle6.Bottom + 14, inputRect5.Left, rectangle6.Bottom);
+ graphicsPath2.AddLine(rectangle7.Right, rectangle6.Bottom, rectangle6.Right, rectangle7.Bottom);
+ graphicsPath2.AddLine(rectangle6.Right, inputRect5.Top, rectangle6.Right + 14, rectangle5.Top);
+ graphicsPath2.AddLine(inputRect5.Right, rectangle5.Top, rectangle5.Right, inputRect5.Top);
+ graphicsPath2.AddLine(rectangle4.Right, inputRect4.Top, rectangle3.Right, inputRect4.Top);
+ graphicsPath2.AddLine(rectangle3.Right, inputRect3.Top, inputRect3.Right, rectangle3.Top);
+ graphicsPath2.AddLine(rectangle10.Right, rectangle3.Top, rectangle10.Right, rectangle11.Bottom);
+ graphicsPath2.AddLine(rectangle11.Right, rectangle10.Bottom, inputRect3.Left, rectangle10.Bottom);
+ graphicsPath2.AddLine(rectangle3.Left, rectangle10.Bottom, rectangle3.Left, inputRect4.Bottom);
+ e.Graphics.FillPath(Brushes.DarkGray, graphicsPath2);
+ }
+ using (GraphicsPath graphicsPath3 = new GraphicsPath())
+ {
+ graphicsPath3.AddLine(rectangle2.Left, inputRect2.Bottom, rectangle2.Left, inputRect2.Top);
+ graphicsPath3.AddLine(inputRect2.Left, rectangle2.Top, inputRect2.Right, rectangle2.Top);
+ graphicsPath3.AddLine(rectangle2.Right, inputRect2.Top, rectangle2.Right, inputRect2.Bottom);
+ graphicsPath3.AddLine(inputRect2.Right, rectangle2.Bottom, inputRect2.Left, rectangle2.Bottom);
+ graphicsPath3.StartFigure();
+ graphicsPath3.AddLine(rectangle12.Left, rectangle13.Bottom, rectangle12.Left, rectangle13.Top);
+ graphicsPath3.AddLine(rectangle13.Left, rectangle12.Top, rectangle13.Right, rectangle12.Top);
+ graphicsPath3.AddLine(rectangle12.Right, rectangle13.Top, rectangle12.Right, rectangle13.Bottom);
+ graphicsPath3.AddLine(rectangle13.Right, rectangle12.Bottom, rectangle13.Left, rectangle12.Bottom);
+ graphicsPath3.StartFigure();
+ graphicsPath3.AddLine(rectangle4.Left, inputRect4.Bottom, rectangle4.Left, rectangle8.Bottom + 14);
+ graphicsPath3.AddLine(rectangle13.Left, rectangle8.Bottom, rectangle9.Right, rectangle8.Bottom);
+ graphicsPath3.AddLine(rectangle8.Right, rectangle9.Bottom, rectangle8.Right, inputRect4.Top);
+ graphicsPath3.AddLine(rectangle8.Right + 14, rectangle4.Top, inputRect4.Right, rectangle4.Top);
+ graphicsPath3.AddLine(rectangle4.Right, inputRect4.Top, rectangle4.Right, inputRect4.Bottom);
+ graphicsPath3.AddLine(inputRect4.Right, rectangle4.Bottom, inputRect4.Left, rectangle4.Bottom);
+ e.Graphics.FillPath(Brushes.Gray, graphicsPath3);
+ }
+ using Font font3 = new Font("Helvetica LT Std", 12f);
+ using Font font = new Font("Helvetica LT Std", 8f);
+ Rectangle rectangle16 = rectangle14;
+ rectangle16.X += 175;
+ rectangle16.Width -= 178;
+ rectangle16.Y += 58;
+ rectangle16.Height -= 86;
+ BTVehicle bTVehicle = (BTConfig.Vehicles.ContainsKey(bTPlayer.VehicleKey) ? BTConfig.Vehicles[bTPlayer.VehicleKey] : null);
+ Image image = bTVehicle?.Image;
+ if (image != null)
+ {
+ e.Graphics.DrawImage(image, GetCenteredScaledRect(rectangle16, image.Size));
+ }
+ else
+ {
+ StringFormat stringFormat = new StringFormat();
+ stringFormat.LineAlignment = StringAlignment.Center;
+ stringFormat.Alignment = StringAlignment.Center;
+ using (StringFormat format = stringFormat)
+ {
+ Rectangle rectangle17 = rectangle16;
+ rectangle17.Inflate(-20, -20);
+ e.Graphics.DrawString("The tech crew's holo-imager is down for repairs. Recon imagery could not be obtained for this mech.", font, Brushes.Black, rectangle17, format);
+ }
+ e.Graphics.DrawRectangle(Pens.Black, rectangle16);
+ }
+ using (Font font2 = new Font("Helvetica LT Std", 18f, FontStyle.Bold))
+ {
+ using StringFormat stringFormat2 = new StringFormat();
+ stringFormat2.Alignment = StringAlignment.Center;
+ stringFormat2.LineAlignment = StringAlignment.Far;
+ e.Graphics.DrawString(bTPlayer.Name, font2, Brushes.Black, rectangle14.Left + rectangle14.Width / 2, rectangle16.Top - 10, stringFormat2);
+ }
+ using (StringFormat stringFormat3 = new StringFormat())
+ {
+ stringFormat3.Alignment = StringAlignment.Center;
+ e.Graphics.DrawString((bTVehicle != null) ? bTVehicle.Name : bTPlayer.VehicleKey, font3, Brushes.Black, rectangle16.Left + rectangle16.Width / 2, rectangle16.Bottom + 5, stringFormat3);
+ }
+ int num = rectangle15.Left - 7;
+ Rectangle rectangle18 = new Rectangle(num, rectangle16.Top, rectangle16.Left - num, rectangle15.Bottom - rectangle16.Top);
+ using (Font font4 = new Font("Helvetica LT Std", 16f, FontStyle.Bold))
+ {
+ using StringFormat stringFormat4 = new StringFormat();
+ stringFormat4.Alignment = StringAlignment.Center;
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.AppendLine(string.Format("{0}{1} Place", finalPlace, finalPlace switch
+ {
+ 3 => "rd",
+ 2 => "nd",
+ 1 => "st",
+ _ => "th",
+ }));
+ e.Graphics.DrawString(stringBuilder.ToString(), font4, Brushes.Black, rectangle18, stringFormat4);
+ }
+ using (StringFormat stringFormat5 = new StringFormat())
+ {
+ stringFormat5.LineAlignment = StringAlignment.Far;
+ stringFormat5.SetTabStops(0f, new float[1] { 80f });
+ int deaths = 0;
+ int kills = 0;
+ GetPlayerStats(out deaths, out kills, bTPlayer, list);
+ StringBuilder stringBuilder2 = new StringBuilder();
+ stringBuilder2.AppendLine($"Score:\t{score}");
+ stringBuilder2.AppendLine();
+ stringBuilder2.AppendLine($"Deaths:\t{deaths}");
+ stringBuilder2.AppendLine();
+ stringBuilder2.AppendLine($"Kills:\t{kills}");
+ e.Graphics.DrawString(stringBuilder2.ToString(), font, Brushes.Black, rectangle18, stringFormat5);
+ }
+ int num2 = rectangle5.Top + 40;
+ Rectangle rectangle19 = new Rectangle(rectangle6.Right + 5, num2, rectangle5.Right - rectangle6.Right - 10, rectangle6.Bottom - 5 - num2);
+ using (StringFormat stringFormat6 = new StringFormat())
+ {
+ stringFormat6.Alignment = StringAlignment.Center;
+ e.Graphics.DrawString("Mission Highlights", font3, Brushes.Black, (rectangle19.Right + rectangle19.Left) / 2, rectangle5.Top + 15, stringFormat6);
+ }
+ using (Font font5 = new Font("Courier New", 10f))
+ {
+ string text = mMissionResults.MissionStart.ToString() + " ";
+ string s = text;
+ List list2 = new List();
+ BTPlayer[][] array = mFinalRanking;
+ foreach (BTPlayer[] array2 in array)
+ {
+ list2.Add(array2[0].Name);
+ }
+ string text2 = BTStrings.Recap(list2.ToArray());
+ Random random = new Random();
+ List list3 = new List(list);
+ SortedList sortedList = new SortedList();
+ string text3 = text + text2;
+ while (e.Graphics.MeasureString(text3, font5, rectangle19.Width).Height < (float)rectangle19.Height)
+ {
+ s = text3;
+ if (list3.Count < 1)
+ {
+ break;
+ }
+ int index = random.Next(list3.Count);
+ BTMissionEvent bTMissionEvent = list3[index];
+ list3.RemoveAt(index);
+ string text4 = null;
+ if (bTMissionEvent is BTDamagedEvent)
+ {
+ BTDamagedEvent bTDamagedEvent = (BTDamagedEvent)bTMissionEvent;
+ if (bTDamagedEvent.DamageLoss > 0)
+ {
+ text4 = ((bTDamagedEvent.DamageLoss < 10) ? BTStrings.LightDamage(bTDamagedEvent.GameTime, bTDamagedEvent.ReportingPilot.Name, BTConfig.VehicleNameOrKey(bTDamagedEvent.ReportingPilot.VehicleKey), bTDamagedEvent.Damager.Name) : ((bTDamagedEvent.DamageLoss >= 100) ? BTStrings.HeavyDamage(bTDamagedEvent.GameTime, bTDamagedEvent.ReportingPilot.Name, BTConfig.VehicleNameOrKey(bTDamagedEvent.ReportingPilot.VehicleKey), bTDamagedEvent.Damager.Name) : BTStrings.ModerateDamage(bTDamagedEvent.GameTime, bTDamagedEvent.ReportingPilot.Name, BTConfig.VehicleNameOrKey(bTDamagedEvent.ReportingPilot.VehicleKey), bTDamagedEvent.Damager.Name)));
+ }
+ }
+ else if (bTMissionEvent is BTKilledEvent)
+ {
+ BTKilledEvent bTKilledEvent = (BTKilledEvent)bTMissionEvent;
+ text4 = ((bTKilledEvent.ReportingPilot != bTKilledEvent.Killer) ? BTStrings.Kill(bTKilledEvent.GameTime, bTKilledEvent.ReportingPilot.Name, BTConfig.VehicleNameOrKey(bTKilledEvent.ReportingPilot.VehicleKey), bTKilledEvent.Killer.Name) : BTStrings.DeathWithoutHonor(bTKilledEvent.GameTime, bTKilledEvent.ReportingPilot.Name, BTConfig.VehicleNameOrKey(bTKilledEvent.ReportingPilot.VehicleKey)));
+ }
+ else if (bTMissionEvent is BTDeathWithoutHonorEvent)
+ {
+ text4 = BTStrings.DeathWithoutHonor(bTMissionEvent.GameTime, bTMissionEvent.ReportingPilot.Name, BTConfig.VehicleNameOrKey(bTMissionEvent.ReportingPilot.VehicleKey));
+ }
+ if (text4 != null)
+ {
+ TimeSpan gameTime;
+ for (gameTime = bTMissionEvent.GameTime; sortedList.ContainsKey(gameTime); gameTime += TimeSpan.FromTicks(1L))
+ {
+ }
+ sortedList.Add(gameTime, text4);
+ }
+ StringBuilder stringBuilder3 = new StringBuilder(text);
+ foreach (KeyValuePair item in sortedList)
+ {
+ if (stringBuilder3.Length > 0)
+ {
+ stringBuilder3.Append(" ");
+ }
+ stringBuilder3.Append(item.Value);
+ }
+ if (stringBuilder3.Length > 0)
+ {
+ stringBuilder3.Append(" ");
+ }
+ stringBuilder3.Append(text2);
+ text3 = stringBuilder3.ToString();
+ }
+ e.Graphics.DrawString(s, font5, Brushes.Black, rectangle19);
+ }
+ int num3 = rectangle6.Bottom + 5;
+ Rectangle rectangle20 = new Rectangle(inputRect5.Left, num3, inputRect5.Width, rectangle5.Bottom - num3);
+ Rectangle rectangle21 = new Rectangle(rectangle20.Right - 250, rectangle20.Top, 250, rectangle20.Height - 20);
+ Image image2 = (BTConfig.Maps.ContainsKey(mMissionResults.Mission.MapKey) ? BTConfig.Maps[mMissionResults.Mission.MapKey] : null)?.Image;
+ if (image2 != null)
+ {
+ e.Graphics.DrawImage(image2, GetCenteredScaledRect(rectangle21, image2.Size));
+ }
+ else
+ {
+ StringFormat stringFormat7 = new StringFormat();
+ stringFormat7.LineAlignment = StringAlignment.Center;
+ stringFormat7.Alignment = StringAlignment.Center;
+ using (StringFormat format2 = stringFormat7)
+ {
+ Rectangle rectangle22 = rectangle21;
+ rectangle22.Inflate(-20, -20);
+ e.Graphics.DrawString("The recon satellite is currently on a transitional orbit. Satellite imagery could not be obtained for this arena.", font, Brushes.Black, rectangle22, format2);
+ }
+ e.Graphics.DrawRectangle(Pens.Black, rectangle21);
+ }
+ Rectangle rect = new Rectangle(rectangle20.Left, rectangle20.Top, rectangle21.Left - 5 - rectangle20.Left, 92);
+ Dictionary dictionary = new Dictionary();
+ foreach (BTPlayer player in mMissionResults.Mission.Players)
+ {
+ if (player != bTPlayer)
+ {
+ dictionary.Add(player, new int[4]);
+ }
+ }
+ foreach (BTMissionEvent event2 in mMissionResults.Events)
+ {
+ if (event2 is BTKilledEvent)
+ {
+ BTKilledEvent bTKilledEvent2 = (BTKilledEvent)event2;
+ if (bTKilledEvent2.ReportingPilot != bTKilledEvent2.Killer)
+ {
+ if (bTKilledEvent2.Killer == bTPlayer)
+ {
+ dictionary[bTKilledEvent2.ReportingPilot][3]++;
+ }
+ else if (bTKilledEvent2.ReportingPilot == bTPlayer)
+ {
+ dictionary[bTKilledEvent2.Killer][2]++;
+ }
+ }
+ }
+ else
+ {
+ if (!(event2 is BTDamagedEvent))
+ {
+ continue;
+ }
+ BTDamagedEvent bTDamagedEvent2 = (BTDamagedEvent)event2;
+ if (bTDamagedEvent2.ReportingPilot != bTDamagedEvent2.Damager)
+ {
+ if (bTDamagedEvent2.Damager == bTPlayer)
+ {
+ dictionary[bTDamagedEvent2.ReportingPilot][1] += bTDamagedEvent2.DamageLoss;
+ }
+ else if (bTDamagedEvent2.ReportingPilot == bTPlayer)
+ {
+ dictionary[bTDamagedEvent2.Damager][0] += bTDamagedEvent2.DamageLoss;
+ }
+ }
+ }
+ }
+ using (Pen pen = new Pen(Color.Gray, 2f))
+ {
+ using Font font6 = new Font("Helvetica LT Std", 6f, FontStyle.Regular);
+ using StringFormat stringFormat8 = new StringFormat();
+ e.Graphics.DrawRectangle(Pens.Gray, rect);
+ int num4 = 120;
+ int num5 = 14;
+ int num6 = rect.Left + 1;
+ int num7 = rect.Left + num4;
+ int num8 = (rect.Width - num4) / Math.Max(1, dictionary.Count);
+ if (dictionary.Count == 0)
+ {
+ e.Graphics.DrawLine(pen, num7, rect.Top, num7, rect.Bottom);
+ }
+ int num9 = rect.Bottom;
+ for (int l = 0; l < 5; l++)
+ {
+ num9 -= num5;
+ e.Graphics.DrawLine(Pens.Gray, rect.Left, num9, rect.Right, num9);
+ }
+ int num10 = rect.Top + 1;
+ stringFormat8.LineAlignment = StringAlignment.Near;
+ e.Graphics.DrawString("Pilot", font6, Brushes.Black, num6, num10, stringFormat8);
+ int num11 = rect.Bottom - num5 / 2;
+ int num12 = num11 - num5;
+ int num13 = num12 - num5;
+ int num14 = num13 - num5;
+ int num15 = num14 - num5;
+ stringFormat8.LineAlignment = StringAlignment.Center;
+ e.Graphics.DrawString("Score", font6, Brushes.Black, num6, num15, stringFormat8);
+ e.Graphics.DrawString("Damage You Received From", font6, Brushes.Black, num6, num14, stringFormat8);
+ e.Graphics.DrawString("Damage You Inflicted On", font6, Brushes.Black, num6, num13, stringFormat8);
+ e.Graphics.DrawString("Times You Were Killed By", font6, Brushes.Black, num6, num12, stringFormat8);
+ e.Graphics.DrawString("Times You Killed", font6, Brushes.Black, num6, num11, stringFormat8);
+ int num16 = num7;
+ foreach (KeyValuePair item2 in dictionary)
+ {
+ int num17 = num16 + 1;
+ e.Graphics.DrawLine(pen, num16, rect.Top, num16, rect.Bottom);
+ stringFormat8.LineAlignment = StringAlignment.Near;
+ e.Graphics.DrawString(item2.Key.Name, font6, Brushes.Black, num17, num10, stringFormat8);
+ stringFormat8.LineAlignment = StringAlignment.Center;
+ e.Graphics.DrawString(mMissionResults.GetScore(item2.Key).ToString(), font6, Brushes.Black, num17, num15, stringFormat8);
+ e.Graphics.DrawString(item2.Value[0].ToString(), font6, Brushes.Black, num17, num14, stringFormat8);
+ e.Graphics.DrawString(item2.Value[1].ToString(), font6, Brushes.Black, num17, num13, stringFormat8);
+ e.Graphics.DrawString(item2.Value[2].ToString(), font6, Brushes.Black, num17, num12, stringFormat8);
+ e.Graphics.DrawString(item2.Value[3].ToString(), font6, Brushes.Black, num17, num11, stringFormat8);
+ num16 += num8;
+ }
+ }
+ int num18 = rectangle20.Left + 60;
+ int num19 = rect.Bottom + 120;
+ Rectangle rectangle23 = new Rectangle(num18, num19, rect.Right - 75 - num18, rectangle20.Bottom - 85 - num19);
+ if (mPlayerLines == null)
+ {
+ mPlayerLines = new Dictionary>();
+ BTPlayer[][] array = mFinalRanking;
+ foreach (BTPlayer[] array3 in array)
+ {
+ BTPlayer[] array4 = array3;
+ foreach (BTPlayer key in array4)
+ {
+ mPlayerLines.Add(key, new List());
+ }
+ }
+ mChartRows = new int[mPlayerLines.Count];
+ float num20 = (float)rectangle23.Height / (float)mPlayerLines.Count;
+ for (int n = 0; n < mChartRows.Length; n++)
+ {
+ mChartRows[n] = (int)(num20 * (float)n + 0.5f) + rectangle23.Top;
+ }
+ mChartCols = new Dictionary();
+ TimeSpan timeSpan = mMissionResults.ActuallMissionTime.Subtract(TimeSpan.FromSeconds(10.0));
+ TimeSpan timeSpan2 = TimeSpan.FromSeconds(15.0);
+ for (TimeSpan timeSpan3 = timeSpan2; timeSpan3 < timeSpan; timeSpan3 += timeSpan2)
+ {
+ mChartCols.Add(timeSpan3, (int)((float)timeSpan3.Ticks / (float)mMissionResults.ActuallMissionTime.Ticks * (float)rectangle23.Width + 0.5f) + rectangle23.Left);
+ }
+ int num21 = 0;
+ array = mFinalRanking;
+ foreach (BTPlayer[] array5 in array)
+ {
+ BTPlayer[] array4 = array5;
+ foreach (BTPlayer key2 in array4)
+ {
+ mPlayerLines[key2].Add(new Point(rectangle23.Left, mChartRows[num21++]));
+ }
+ }
+ foreach (KeyValuePair mChartCol in mChartCols)
+ {
+ num21 = 0;
+ array = mMissionResults.GetChartOrder(mChartCol.Key);
+ foreach (BTPlayer[] array6 in array)
+ {
+ BTPlayer[] array4 = array6;
+ foreach (BTPlayer key3 in array4)
+ {
+ mPlayerLines[key3].Add(new Point(mChartCol.Value, mChartRows[num21++]));
+ }
+ }
+ }
+ num21 = 0;
+ array = mFinalRanking;
+ foreach (BTPlayer[] array7 in array)
+ {
+ BTPlayer[] array4 = array7;
+ foreach (BTPlayer key4 in array4)
+ {
+ mPlayerLines[key4].Add(new Point(rectangle23.Right, mChartRows[num21++]));
+ }
+ }
+ }
+ using (Font font7 = new Font("Helvetica LT Std", 8f))
+ {
+ using (StringFormat stringFormat9 = new StringFormat())
+ {
+ stringFormat9.LineAlignment = StringAlignment.Center;
+ foreach (KeyValuePair> mPlayerLine in mPlayerLines)
+ {
+ if (mPlayerLine.Key != bTPlayer)
+ {
+ DrawPlayerLine(e.Graphics, mPlayerLine.Key, mPlayerLine.Value.ToArray(), rectangle23.Right + 5, Pens.LightGray, Brushes.LightGray, font7, stringFormat9);
+ }
+ }
+ DrawPlayerLine(e.Graphics, bTPlayer, mPlayerLines[bTPlayer].ToArray(), rectangle23.Right + 5, Pens.Black, Brushes.Black, font7, stringFormat9);
+ }
+ using Pen pen2 = new Pen(Color.Black, 1.5f);
+ using (Font font8 = new Font("Courier New", 8f))
+ {
+ int num22 = 5;
+ int num23 = 3;
+ e.Graphics.DrawLines(pen2, new Point[3]
+ {
+ new Point(rectangle23.Left, rectangle23.Top),
+ new Point(rectangle23.Left, rectangle23.Bottom),
+ new Point(rectangle23.Right, rectangle23.Bottom)
+ });
+ using StringFormat stringFormat10 = new StringFormat();
+ stringFormat10.Alignment = StringAlignment.Far;
+ stringFormat10.LineAlignment = StringAlignment.Center;
+ int num24 = 0;
+ BTPlayer[][] array = mFinalRanking;
+ foreach (BTPlayer[] array8 in array)
+ {
+ int num25 = mChartRows[num24];
+ e.Graphics.DrawLine(pen2, rectangle23.Left - num22, num25, rectangle23.Left + num22, num25);
+ Graphics graphics = e.Graphics;
+ int num26 = ++num24;
+ graphics.DrawString(num26.ToString(), font8, Brushes.Black, rectangle23.Left - 10, num25, stringFormat10);
+ _ = array8;
+ }
+ int num27 = rectangle23.Bottom + 23;
+ stringFormat10.Alignment = StringAlignment.Center;
+ stringFormat10.LineAlignment = StringAlignment.Near;
+ e.Graphics.DrawString("0", font8, Brushes.Black, rectangle23.Left, num27, stringFormat10);
+ foreach (KeyValuePair mChartCol2 in mChartCols)
+ {
+ if (mChartCol2.Key.Seconds == 0)
+ {
+ e.Graphics.DrawLine(pen2, mChartCol2.Value, rectangle23.Bottom - num22, mChartCol2.Value, rectangle23.Bottom + num22);
+ e.Graphics.DrawString(mChartCol2.Key.Minutes.ToString(), font8, Brushes.Black, mChartCol2.Value, num27, stringFormat10);
+ }
+ else
+ {
+ e.Graphics.DrawLine(pen2, mChartCol2.Value, rectangle23.Bottom - num23, mChartCol2.Value, rectangle23.Bottom);
+ }
+ }
+ e.Graphics.DrawLine(pen2, rectangle23.Right, rectangle23.Bottom - num22, rectangle23.Right, rectangle23.Bottom + num22);
+ e.Graphics.DrawString(((int)(mMissionResults.ActuallMissionTime.TotalMinutes + 0.5)).ToString(), font8, Brushes.Black, rectangle23.Right, num27, stringFormat10);
+ e.Graphics.DrawString("Time", font, Brushes.Black, (rectangle23.Left + rectangle23.Right) / 2, rectangle23.Bottom + 68, stringFormat10);
+ stringFormat10.LineAlignment = StringAlignment.Center;
+ e.Graphics.DrawString("P\r\nl\r\na\r\nc\r\ne", font, Brushes.Black, rectangle23.Left - 54, (rectangle23.Bottom + rectangle23.Top) / 2, stringFormat10);
+ int num28 = rectangle23.Top - 70;
+ int num29 = rectangle23.Left + 10;
+ int num30 = (rectangle23.Right + rectangle23.Left) / 2 - 30;
+ stringFormat10.Alignment = StringAlignment.Near;
+ DrawKillMarker(e.Graphics, pen2, num29, num28, 15f);
+ e.Graphics.DrawString("Kill", font7, Brushes.Black, num29 + 15, num28, stringFormat10);
+ DrawDeathMarker(e.Graphics, pen2, num30, num28, 15f);
+ e.Graphics.DrawString("Death", font7, Brushes.Black, num30 + 15, num28, stringFormat10);
+ }
+ foreach (BTMissionEvent event3 in mMissionResults.Events)
+ {
+ if (event3 is BTKilledEvent)
+ {
+ BTKilledEvent bTKilledEvent3 = (BTKilledEvent)event3;
+ if (bTKilledEvent3.Killer != bTKilledEvent3.ReportingPilot)
+ {
+ DrawKillMarker(e.Graphics, (bTKilledEvent3.ReportingPilot == bTPlayer || bTKilledEvent3.Killer == bTPlayer) ? Pens.Black : Pens.LightGray, GetMarkerPosition(bTKilledEvent3.GameTime, mPlayerLines[bTKilledEvent3.Killer], rectangle23), 10f);
+ }
+ DrawDeathMarker(e.Graphics, (bTKilledEvent3.ReportingPilot == bTPlayer || bTKilledEvent3.Killer == bTPlayer) ? Pens.Black : Pens.LightGray, GetMarkerPosition(bTKilledEvent3.GameTime, mPlayerLines[bTKilledEvent3.ReportingPilot], rectangle23), 10f);
+ }
+ else if (event3 is BTDeathWithoutHonorEvent)
+ {
+ DrawDeathMarker(e.Graphics, (event3.ReportingPilot == bTPlayer) ? Pens.Black : Pens.LightGray, GetMarkerPosition(event3.GameTime, mPlayerLines[event3.ReportingPilot], rectangle23), 10f);
+ }
+ }
+ }
+ e.HasMorePages = ++mCurrentPlayer < mPrintOrder.Length;
+ base.OnPrintPage(e);
+ }
+
+ private PointF GetMarkerPosition(TimeSpan time, List chartLine, RectangleF chartArea)
+ {
+ TimeSpan timeSpan = TimeSpan.Zero;
+ TimeSpan timeSpan2 = mMissionResults.ActuallMissionTime;
+ int num = 0;
+ foreach (KeyValuePair mChartCol in mChartCols)
+ {
+ timeSpan2 = mChartCol.Key;
+ if (mChartCol.Key < time)
+ {
+ num++;
+ timeSpan = timeSpan2;
+ continue;
+ }
+ break;
+ }
+ if (timeSpan == timeSpan2)
+ {
+ timeSpan2 = mMissionResults.ActuallMissionTime;
+ }
+ float num2 = ((float)time.Ticks - (float)timeSpan.Ticks) / ((float)timeSpan2.Ticks - (float)timeSpan.Ticks);
+ PointF pointF = chartLine[num];
+ PointF pointF2 = chartLine[num + 1];
+ return new PointF((pointF2.X - pointF.X) * num2 + pointF.X, (pointF2.Y - pointF.Y) * num2 + pointF.Y);
+ }
+
+ private static void DrawKillMarker(Graphics graphics, Pen pen, PointF point, float size)
+ {
+ DrawKillMarker(graphics, pen, point.X, point.Y, size);
+ }
+
+ private static void DrawKillMarker(Graphics graphics, Pen pen, float x, float y, float size)
+ {
+ float y2 = y + size / 2f;
+ graphics.DrawPolygon(pen, new PointF[3]
+ {
+ new PointF(x - size / 2f, y2),
+ new PointF(x + size / 2f, y2),
+ new PointF(x, y - size / 2f)
+ });
+ }
+
+ private static void DrawDeathMarker(Graphics graphics, Pen pen, PointF point, float size)
+ {
+ DrawDeathMarker(graphics, pen, point.X, point.Y, size);
+ }
+
+ private static void DrawDeathMarker(Graphics graphics, Pen pen, float x, float y, float size)
+ {
+ graphics.DrawRectangle(pen, x - size / 2f, y - size / 2f, size, size);
+ }
+
+ private static void DrawPlayerLine(Graphics graphics, BTPlayer player, Point[] points, int playerNameX, Pen pen, Brush brush, Font font, StringFormat format)
+ {
+ graphics.DrawLines(pen, points);
+ graphics.DrawString(player.Name, font, brush, playerNameX, points[points.Length - 1].Y, format);
+ }
+
+ private static void GetPlayerStats(out int deaths, out int kills, BTPlayer player, IEnumerable relaventEventsSorted)
+ {
+ deaths = 0;
+ kills = 0;
+ foreach (BTMissionEvent item in relaventEventsSorted)
+ {
+ if (item.ReportingPilot == player)
+ {
+ if (item is BTKilledEvent || item is BTDeathWithoutHonorEvent)
+ {
+ deaths++;
+ }
+ }
+ else if (item is BTKilledEvent && ((BTKilledEvent)item).Killer == player)
+ {
+ kills++;
+ }
+ }
+ }
+
+ private static Rectangle RectDrop(Rectangle inputRect, int widthDrop, int heightDrop)
+ {
+ return new Rectangle(inputRect.X, inputRect.Y, inputRect.Width - widthDrop, inputRect.Height - heightDrop);
+ }
+
+ private static Rectangle GetCenteredScaledRect(Rectangle bounds, Size originalSize)
+ {
+ float num = (float)bounds.Width / (float)bounds.Height;
+ float num2 = (float)originalSize.Width / (float)originalSize.Height;
+ Size size = bounds.Size;
+ if (num > num2)
+ {
+ size.Width = (int)((float)size.Height * num2 + 0.5f);
+ }
+ else
+ {
+ size.Height = (int)((float)size.Width / num2 + 0.5f);
+ }
+ return new Rectangle(bounds.X + (bounds.Width - size.Width) / 2, bounds.Y + (bounds.Height - size.Height) / 2, size.Width, size.Height);
+ }
+
+ private static bool Contains(IEnumerable players, BTPlayer player)
+ {
+ foreach (BTPlayer player2 in players)
+ {
+ if (player2 == player)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/Console/TeslaConsole.BattleTech/BTStrings.cs b/Console/TeslaConsole.BattleTech/BTStrings.cs
new file mode 100644
index 0000000..a246995
--- /dev/null
+++ b/Console/TeslaConsole.BattleTech/BTStrings.cs
@@ -0,0 +1,144 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Windows.Forms;
+using System.Xml;
+
+namespace TeslaConsole.BattleTech;
+
+///
+/// The BattleTech mission-highlight narrative strings, loaded from
+/// BattleTech\BTStrings.xml. Mirrors TeslaConsole.RPStrings: each
+/// category is a pool of templates and one is picked at random with the
+/// {time}/{player}/{vehicle}/{damager} placeholders substituted. The RP-only
+/// categories (score/boost/lap) have no BT counterpart; DeathWithoutHonor
+/// replaces SelfKill.
+///
+internal class BTStrings
+{
+ private static bool sInitalized = false;
+
+ private static List sLightDamage = new List();
+
+ private static List sModerateDamage = new List();
+
+ private static List sHeavyDamage = new List();
+
+ private static List sKill = new List();
+
+ private static List sDeathWithoutHonor = new List();
+
+ private static List sRecap = new List();
+
+ private static Random sRandom = new Random();
+
+ private static void Initalize()
+ {
+ XmlDocument xmlDocument = new XmlDocument();
+ xmlDocument.Load(Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "BattleTech\\BTStrings.xml"));
+ if (xmlDocument.DocumentElement.Name != "BTStrings")
+ {
+ throw new XmlException("Document element was not a BTStrings node.");
+ }
+ foreach (XmlNode childNode in xmlDocument.DocumentElement.ChildNodes)
+ {
+ switch (childNode.Name)
+ {
+ case "LightDamage":
+ if (!sLightDamage.Contains(childNode.InnerText))
+ {
+ sLightDamage.Add(childNode.InnerText);
+ }
+ break;
+ case "ModerateDamage":
+ if (!sModerateDamage.Contains(childNode.InnerText))
+ {
+ sModerateDamage.Add(childNode.InnerText);
+ }
+ break;
+ case "HeavyDamage":
+ if (!sHeavyDamage.Contains(childNode.InnerText))
+ {
+ sHeavyDamage.Add(childNode.InnerText);
+ }
+ break;
+ case "Kill":
+ if (!sKill.Contains(childNode.InnerText))
+ {
+ sKill.Add(childNode.InnerText);
+ }
+ break;
+ case "DeathWithoutHonor":
+ if (!sDeathWithoutHonor.Contains(childNode.InnerText))
+ {
+ sDeathWithoutHonor.Add(childNode.InnerText);
+ }
+ break;
+ case "Recap":
+ if (!sRecap.Contains(childNode.InnerText))
+ {
+ sRecap.Add(childNode.InnerText);
+ }
+ break;
+ }
+ }
+ sInitalized = true;
+ }
+
+ private static string GetRandomStringAndReplace(List list, TimeSpan time, string player, string vehicle, string damager)
+ {
+ if (!sInitalized)
+ {
+ Initalize();
+ }
+ if (list.Count == 0)
+ {
+ return null;
+ }
+ return list[sRandom.Next(list.Count)].Replace("{time}", GetTimeString(time)).Replace("{player}", player).Replace("{vehicle}", vehicle)
+ .Replace("{damager}", damager);
+ }
+
+ public static string GetTimeString(TimeSpan time)
+ {
+ int num = (int)(time.TotalSeconds + 0.5);
+ int num2 = num / 60;
+ return $"{num2:D2}:{num % 60:D2}";
+ }
+
+ public static string LightDamage(TimeSpan time, string player, string vehicle, string damager)
+ {
+ return GetRandomStringAndReplace(sLightDamage, time, player, vehicle, damager);
+ }
+
+ public static string ModerateDamage(TimeSpan time, string player, string vehicle, string damager)
+ {
+ return GetRandomStringAndReplace(sModerateDamage, time, player, vehicle, damager);
+ }
+
+ public static string HeavyDamage(TimeSpan time, string player, string vehicle, string damager)
+ {
+ return GetRandomStringAndReplace(sHeavyDamage, time, player, vehicle, damager);
+ }
+
+ public static string Kill(TimeSpan time, string player, string vehicle, string damager)
+ {
+ return GetRandomStringAndReplace(sKill, time, player, vehicle, damager);
+ }
+
+ public static string DeathWithoutHonor(TimeSpan time, string player, string vehicle)
+ {
+ return GetRandomStringAndReplace(sDeathWithoutHonor, time, player, vehicle, "");
+ }
+
+ public static string Recap(string[] playerRanking)
+ {
+ StringBuilder stringBuilder = new StringBuilder(playerRanking[0]);
+ for (int i = 1; i < playerRanking.Length - 1; i++)
+ {
+ stringBuilder.AppendFormat(", {0}", playerRanking[i]);
+ }
+ return GetRandomStringAndReplace(sRecap, TimeSpan.Zero, "", "", "").Replace("{winners}", stringBuilder.ToString()).Replace("{looser}", (playerRanking.Length > 1) ? playerRanking[playerRanking.Length - 1] : "nobody");
+ }
+}
diff --git a/Console/TeslaConsole.csproj b/Console/TeslaConsole.csproj
index e397835..5e7cdfe 100644
--- a/Console/TeslaConsole.csproj
+++ b/Console/TeslaConsole.csproj
@@ -31,6 +31,7 @@
+
diff --git a/Console/TeslaConsole/TeslaConsoleForm.cs b/Console/TeslaConsole/TeslaConsoleForm.cs
index 70e802a..95c7d7c 100644
--- a/Console/TeslaConsole/TeslaConsoleForm.cs
+++ b/Console/TeslaConsole/TeslaConsoleForm.cs
@@ -51,6 +51,12 @@ public class TeslaConsoleForm : Form
private ToolStripMenuItem mPrintRpMission;
+ private ToolStripMenuItem mBtMissionPrintPreview;
+
+ private ToolStripMenuItem mPrintBtMission;
+
+ private OpenFileDialog mBTMissionOpenDialog;
+
private ToolStripSeparator mSeperator1;
private PrintDialog mRPPrintDialog;
@@ -73,10 +79,20 @@ public class TeslaConsoleForm : Form
private ToolStripMenuItem exportRedPlanetDefaultsToolStripMenuItem;
+ private ToolStripMenuItem battleTechDefaultsToolStripMenuItem;
+
+ private ToolStripMenuItem importBattleTechDefaultsToolStripMenuItem;
+
+ private ToolStripMenuItem exportBattleTechDefaultsToolStripMenuItem;
+
private OpenFileDialog mRPDefaultsOpenDialog;
private SaveFileDialog mRPDefaultsSaveDialog;
+ private OpenFileDialog mBTDefaultsOpenDialog;
+
+ private SaveFileDialog mBTDefaultsSaveDialog;
+
private ToolStripSeparator toolStripSeparator1;
private ToolStripMenuItem enableCustomBitmapsToolStripMenuItem;
@@ -91,10 +107,12 @@ public class TeslaConsoleForm : Form
{
InitializeComponent();
mRpMissionPrintPreview.Visible = false;
+ mBtMissionPrintPreview.Visible = false;
mSeperator1.Visible = false;
mExceptionsMenu.Visible = false;
enableCustomBitmapsToolStripMenuItem.Checked = PlasmaBitmaps.EnableCustomBitmaps;
mRPMissionOpenDialog.InitialDirectory = RPMissionResults.GetRPMissionsDirectory();
+ mBTMissionOpenDialog.InitialDirectory = BTMissionResults.GetBTMissionsDirectory();
TeslaConsole.Site.LoadFromStore();
PodManager.StartConfigurationServer();
}
@@ -323,6 +341,52 @@ public class TeslaConsoleForm : Form
}
}
+ private PrintDocument GetBTMissionPrintDocument()
+ {
+ if (mBTMissionOpenDialog.ShowDialog() == DialogResult.OK)
+ {
+ try
+ {
+ BTMissionResults bTMissionResults = BTMissionResults.Load(mBTMissionOpenDialog.FileName);
+ return bTMissionResults.GetPrintDocument();
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show("The selected document could not be loaded because it appears to be corrupt.", "Error Loading Mission Data", MessageBoxButtons.OK);
+ Program.LogException(ex, $"Error Loading BT Mission Results (\"{mBTMissionOpenDialog.FileName}\").");
+ }
+ }
+ return null;
+ }
+
+ private void btPrintPreviewToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ PrintDocument bTMissionPrintDocument = GetBTMissionPrintDocument();
+ if (bTMissionPrintDocument != null)
+ {
+ if (mRPPrintPreviewDialog.IsDisposed)
+ {
+ mRPPrintPreviewDialog = new PrintPreviewDialog();
+ }
+ mRPPrintPreviewDialog.Document = bTMissionPrintDocument;
+ mRPPrintPreviewDialog.Show();
+ mRPPrintPreviewDialog.DesktopBounds = Screen.PrimaryScreen.WorkingArea;
+ }
+ }
+
+ private void printBtMissionToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ PrintDocument bTMissionPrintDocument = GetBTMissionPrintDocument();
+ if (bTMissionPrintDocument != null)
+ {
+ mRPPrintDialog.Document = bTMissionPrintDocument;
+ if (mRPPrintDialog.ShowDialog() == DialogResult.OK)
+ {
+ mRPPrintDialog.Document.Print();
+ }
+ }
+ }
+
private void TeslaConsoleForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (mSitePanel != null && !mSitePanel.IsDisposed)
@@ -374,6 +438,43 @@ public class TeslaConsoleForm : Form
}
}
+ private void changeBattleTechDefaultsToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ BTDefaultsDialog.ShowSingleton();
+ }
+
+ private void importBattleTechDefaultsToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (mBTDefaultsOpenDialog.ShowDialog() == DialogResult.OK)
+ {
+ try
+ {
+ BTDefaults.Import(mBTDefaultsOpenDialog.FileName);
+ }
+ catch (Exception)
+ {
+ MessageBox.Show("This BattleTech defaults file appears to be corrupt.", "Error Loading BattleTech Defaults!", MessageBoxButtons.OK);
+ return;
+ }
+ BTDefaults.Save();
+ }
+ }
+
+ private void exportBattleTechDefaultsToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (mBTDefaultsSaveDialog.ShowDialog() == DialogResult.OK)
+ {
+ try
+ {
+ BTDefaults.Export(mBTDefaultsSaveDialog.FileName);
+ }
+ catch (Exception)
+ {
+ MessageBox.Show("The BattleTech defaults file could not be exported.", "Error Exporting BattleTech Defaults!", MessageBoxButtons.OK);
+ }
+ }
+ }
+
private void enableCustomBitmapsToolStripMenuItem_Click(object sender, EventArgs e)
{
enableCustomBitmapsToolStripMenuItem.Checked = (PlasmaBitmaps.EnableCustomBitmaps = !PlasmaBitmaps.EnableCustomBitmaps);
@@ -437,6 +538,8 @@ public class TeslaConsoleForm : Form
this.mSitePanelSeparator = new System.Windows.Forms.ToolStripSeparator();
this.mRpMissionPrintPreview = new System.Windows.Forms.ToolStripMenuItem();
this.mPrintRpMission = new System.Windows.Forms.ToolStripMenuItem();
+ this.mBtMissionPrintPreview = new System.Windows.Forms.ToolStripMenuItem();
+ this.mPrintBtMission = new System.Windows.Forms.ToolStripMenuItem();
this.mSeperator1 = new System.Windows.Forms.ToolStripSeparator();
this.mPlasmaEditor = new System.Windows.Forms.ToolStripMenuItem();
this.mPlasmaFontTool = new System.Windows.Forms.ToolStripMenuItem();
@@ -447,6 +550,9 @@ public class TeslaConsoleForm : Form
this.redPlanetDefaultsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.importRedPlanetDefaultsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.exportRedPlanetDefaultsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.battleTechDefaultsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.importBattleTechDefaultsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.exportBattleTechDefaultsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
this.enableCustomBitmapsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.mGamesMenu = new System.Windows.Forms.ToolStripMenuItem();
@@ -462,8 +568,11 @@ public class TeslaConsoleForm : Form
this.mRPPrintPreviewDialog = new System.Windows.Forms.PrintPreviewDialog();
this.mRPPrintDialog = new System.Windows.Forms.PrintDialog();
this.mRPMissionOpenDialog = new System.Windows.Forms.OpenFileDialog();
+ this.mBTMissionOpenDialog = new System.Windows.Forms.OpenFileDialog();
this.mRPDefaultsOpenDialog = new System.Windows.Forms.OpenFileDialog();
this.mRPDefaultsSaveDialog = new System.Windows.Forms.SaveFileDialog();
+ this.mBTDefaultsOpenDialog = new System.Windows.Forms.OpenFileDialog();
+ this.mBTDefaultsSaveDialog = new System.Windows.Forms.SaveFileDialog();
this.mMenu.SuspendLayout();
base.SuspendLayout();
this.mMainDockPanel.ActiveAutoHideContent = null;
@@ -525,7 +634,7 @@ public class TeslaConsoleForm : Form
this.mMenu.Size = new System.Drawing.Size(1168, 24);
this.mMenu.TabIndex = 3;
this.mMenu.Text = "menuStrip1";
- this.mFileMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[10] { this.mShowSitePanelMenuItem, this.mSitePanelSeparator, this.mRpMissionPrintPreview, this.mPrintRpMission, this.mSeperator1, this.mPlasmaEditor, this.mPlasmaFontTool, this.mPlasmaBitmapDecoder, this.mSeperator2, this.mExit });
+ this.mFileMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[12] { this.mShowSitePanelMenuItem, this.mSitePanelSeparator, this.mRpMissionPrintPreview, this.mPrintRpMission, this.mBtMissionPrintPreview, this.mPrintBtMission, this.mSeperator1, this.mPlasmaEditor, this.mPlasmaFontTool, this.mPlasmaBitmapDecoder, this.mSeperator2, this.mExit });
this.mFileMenu.Name = "mFileMenu";
this.mFileMenu.Size = new System.Drawing.Size(37, 20);
this.mFileMenu.Text = "File";
@@ -543,6 +652,14 @@ public class TeslaConsoleForm : Form
this.mPrintRpMission.Size = new System.Drawing.Size(204, 22);
this.mPrintRpMission.Text = "Print RP Mission";
this.mPrintRpMission.Click += new System.EventHandler(printToolStripMenuItem_Click);
+ this.mBtMissionPrintPreview.Name = "mBtMissionPrintPreview";
+ this.mBtMissionPrintPreview.Size = new System.Drawing.Size(204, 22);
+ this.mBtMissionPrintPreview.Text = "BT Mission Print Preview";
+ this.mBtMissionPrintPreview.Click += new System.EventHandler(btPrintPreviewToolStripMenuItem_Click);
+ this.mPrintBtMission.Name = "mPrintBtMission";
+ this.mPrintBtMission.Size = new System.Drawing.Size(204, 22);
+ this.mPrintBtMission.Text = "Print BT Mission";
+ this.mPrintBtMission.Click += new System.EventHandler(printBtMissionToolStripMenuItem_Click);
this.mSeperator1.Name = "mSeperator1";
this.mSeperator1.Size = new System.Drawing.Size(201, 6);
this.mPlasmaEditor.Name = "mPlasmaEditor";
@@ -563,7 +680,7 @@ public class TeslaConsoleForm : Form
this.mExit.Size = new System.Drawing.Size(204, 22);
this.mExit.Text = "Exit";
this.mExit.Click += new System.EventHandler(mExit_Click);
- this.settingsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[5] { this.redPlanetDefaultsToolStripMenuItem, this.importRedPlanetDefaultsToolStripMenuItem, this.exportRedPlanetDefaultsToolStripMenuItem, this.toolStripSeparator1, this.enableCustomBitmapsToolStripMenuItem });
+ this.settingsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[8] { this.redPlanetDefaultsToolStripMenuItem, this.importRedPlanetDefaultsToolStripMenuItem, this.exportRedPlanetDefaultsToolStripMenuItem, this.battleTechDefaultsToolStripMenuItem, this.importBattleTechDefaultsToolStripMenuItem, this.exportBattleTechDefaultsToolStripMenuItem, this.toolStripSeparator1, this.enableCustomBitmapsToolStripMenuItem });
this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem";
this.settingsToolStripMenuItem.Size = new System.Drawing.Size(61, 20);
this.settingsToolStripMenuItem.Text = "Settings";
@@ -579,6 +696,18 @@ public class TeslaConsoleForm : Form
this.exportRedPlanetDefaultsToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
this.exportRedPlanetDefaultsToolStripMenuItem.Text = "&Export Red Planet Defaults";
this.exportRedPlanetDefaultsToolStripMenuItem.Click += new System.EventHandler(exportRedPlanetDefaultsToolStripMenuItem_Click);
+ this.battleTechDefaultsToolStripMenuItem.Name = "battleTechDefaultsToolStripMenuItem";
+ this.battleTechDefaultsToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
+ this.battleTechDefaultsToolStripMenuItem.Text = "Change &BattleTech Defaults";
+ this.battleTechDefaultsToolStripMenuItem.Click += new System.EventHandler(changeBattleTechDefaultsToolStripMenuItem_Click);
+ this.importBattleTechDefaultsToolStripMenuItem.Name = "importBattleTechDefaultsToolStripMenuItem";
+ this.importBattleTechDefaultsToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
+ this.importBattleTechDefaultsToolStripMenuItem.Text = "Import BattleTech Defaults";
+ this.importBattleTechDefaultsToolStripMenuItem.Click += new System.EventHandler(importBattleTechDefaultsToolStripMenuItem_Click);
+ this.exportBattleTechDefaultsToolStripMenuItem.Name = "exportBattleTechDefaultsToolStripMenuItem";
+ this.exportBattleTechDefaultsToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
+ this.exportBattleTechDefaultsToolStripMenuItem.Text = "Export BattleTech Defaults";
+ this.exportBattleTechDefaultsToolStripMenuItem.Click += new System.EventHandler(exportBattleTechDefaultsToolStripMenuItem_Click);
this.toolStripSeparator1.Name = "toolStripSeparator1";
this.toolStripSeparator1.Size = new System.Drawing.Size(217, 6);
this.enableCustomBitmapsToolStripMenuItem.Name = "enableCustomBitmapsToolStripMenuItem";
@@ -634,8 +763,11 @@ public class TeslaConsoleForm : Form
this.mRPPrintPreviewDialog.Visible = false;
this.mRPPrintDialog.UseEXDialog = true;
this.mRPMissionOpenDialog.Filter = "RP Mission (*.rpm)|*.rpm";
+ this.mBTMissionOpenDialog.Filter = "BT Mission (*.btm)|*.btm";
this.mRPDefaultsOpenDialog.Filter = "RP Defaults (*.rpd)|*.rpd";
this.mRPDefaultsSaveDialog.Filter = "RP Defaults (*.rpd)|*.rpd";
+ this.mBTDefaultsOpenDialog.Filter = "BT Defaults (*.btd)|*.btd";
+ this.mBTDefaultsSaveDialog.Filter = "BT Defaults (*.btd)|*.btd";
base.AutoScaleDimensions = new System.Drawing.SizeF(6f, 13f);
base.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
base.ClientSize = new System.Drawing.Size(1168, 591);
diff --git a/Console/tests/TeslaConsole.DiffTests/BTGoldenEggTests.cs b/Console/tests/TeslaConsole.DiffTests/BTGoldenEggTests.cs
index 886d6f9..4a9111c 100644
--- a/Console/tests/TeslaConsole.DiffTests/BTGoldenEggTests.cs
+++ b/Console/tests/TeslaConsole.DiffTests/BTGoldenEggTests.cs
@@ -197,15 +197,18 @@ namespace TeslaConsole.DiffTests
{
// No Return is not a separate scenario on the wire: both golden eggs say
// scenario=freeforall, and the modes differ only by the pilots' role.
+ // The model is "noreturn" (the Mac ini tag, resolvable against the
+ // game's BTL4.RES "NoReturn" resource) — NOT the golden eggs' "noretun",
+ // which was a 4.10 console bug that dropped a character.
var args = (string[])CavernArgs.Clone();
args[13] = "NoReturn";
- args[14] = "noretun";
+ args[14] = "noreturn";
var egg = ParseEgg(Generate(args));
Assert.Contains("scenario=freeforall", egg["mission"]);
Assert.Contains("role=Role::NoReturn", egg["200.0.0.113"]);
Assert.True(egg.ContainsKey("Role::NoReturn"), "Missing [Role::NoReturn] block");
- Assert.Contains("model=noretun", egg["Role::NoReturn"]);
+ Assert.Contains("model=noreturn", egg["Role::NoReturn"]);
Assert.False(egg.ContainsKey("Role::Default"), "Unreferenced [Role::Default] emitted");
}
@@ -241,7 +244,7 @@ namespace TeslaConsole.DiffTests
Assert.Equal(7, ffa.SelectNodes("badge").Count);
Assert.Equal(2, ffa.SelectNodes("role").Count);
Assert.Equal("dfltrole", ffa.SelectSingleNode("role[@key='Default']").Attributes["model"].InnerText);
- Assert.Equal("noretun", ffa.SelectSingleNode("role[@key='NoReturn']").Attributes["model"].InnerText);
+ Assert.Equal("noreturn", ffa.SelectSingleNode("role[@key='NoReturn']").Attributes["model"].InnerText);
}
}
}
diff --git a/Console/tests/TeslaConsole.DiffTests/CatalogTests.cs b/Console/tests/TeslaConsole.DiffTests/CatalogTests.cs
index 28e3844..814005e 100644
--- a/Console/tests/TeslaConsole.DiffTests/CatalogTests.cs
+++ b/Console/tests/TeslaConsole.DiffTests/CatalogTests.cs
@@ -25,8 +25,8 @@ namespace TeslaConsole.DiffTests
=> _fx.Recovered.Run("CatalogEntry", new[] { _catalog, launchKey, w, h });
[Fact]
- public void Catalog_Has_Three_Products_And_Five_Entries()
- => Assert.Equal("products=3;entries=5",
+ public void Catalog_Has_Four_Products_And_Eight_Entries()
+ => Assert.Equal("products=4;entries=8",
_fx.Recovered.Run("CatalogSummary", new[] { _catalog }));
[Fact]
@@ -73,5 +73,32 @@ namespace TeslaConsole.DiffTests
=> Assert.Equal(
@"BattleTech Firestorm|cc8500ed-a653-45a7-bef8-c332d30371a6|C:\Games\MW4\launcher.exe||C:\Games\MW4|True",
Entry("CC8500ED-A653-45a7-BEF8-C332D30371A6"));
+
+ // BattleTech 4.11 is a new product (no original counterpart); these pin the
+ // catalog entries the console registers on BT pods.
+
+ [Fact]
+ public void BattleTech_GameClient_Matches_Expected()
+ => Assert.Equal(
+ @"BattleTech 4.11|f4c957fd-72f7-4c5f-8971-28095007e8df|C:\Games\BT411\btl4.exe|-net 1501|C:\Games\BT411|True",
+ Entry("F4C957FD-72F7-4C5F-8971-28095007E8DF"));
+
+ [Fact]
+ public void BattleTech_GameClient_With_Resolution_Matches_Expected()
+ => Assert.Equal(
+ @"BattleTech 4.11|f4c957fd-72f7-4c5f-8971-28095007e8df|C:\Games\BT411\btl4.exe|-net 1501 -res 1024 768|C:\Games\BT411|True",
+ Entry("F4C957FD-72F7-4C5F-8971-28095007E8DF", "1024", "768"));
+
+ [Fact]
+ public void BattleTech_LiveCamera_Matches_Expected()
+ => Assert.Equal(
+ @"BattleTech 4.11 LC|d393711a-eda0-48b2-82a0-89df12b768af|C:\Games\BT411\btl4.exe|-net 1501 -lc|C:\Games\BT411|True",
+ Entry("D393711A-EDA0-48B2-82A0-89DF12B768AF"));
+
+ [Fact]
+ public void BattleTech_MissionReview_Matches_Expected()
+ => Assert.Equal(
+ @"BattleTech 4.11 MR|2e9b8628-9c20-42fb-b070-e9c38d521082|C:\Games\BT411\btl4.exe|-net 1501 -mr|C:\Games\BT411|True",
+ Entry("2E9B8628-9C20-42FB-B070-E9C38D521082"));
}
}