Files
TeslaSuite/Console/TeslaConsole.BattleTech/BTDefaults.cs
T
CydandClaude Fable 5 36166a95b0 BTGame pane + shell de-hardcode for multi-game pods (BT port phase 3)
BTGame mirrors RPGame - same GameStateData/state-machine/NetworkScan engine
driving each pod's MungaGame (take ownership, stream egg on WaitingForEgg,
Run/Abort/Stop, countdown) - with the BT differences: ApplicationID.BTL4, a
pilots grid carrying Mech/Camo/Patch/Badge/Experience, an Advanced Damage
checkbox in place of RP's Score Compression, and the Mech* in-match messages
recorded via BTMissionRecorder into BTMissionResults (.btm, gzip +
BinaryFormatter like .rpm; scores are 1000-based like RP). Free For All and
No Return share the pane; the mode selects the pilots' role. BTDefaults
persists per-mode operator defaults to BTDefaults.btd (no dialog yet).
RPGame's dead decompile members (sStopToIdleStates, IsAllPodsAppState) were
not carried over.

TeslaConsoleForm no longer assumes RP: the "AppID != 0 -> Pod Not Running RP"
check becomes a GameTag map (RPL4 -> RP, BTL4 -> BT, otherwise Unknown Pod
Application) feeding the per-game status strings, and the Games menu gains
BattleTech: Free For All / No Return.

Deferred to phase 4: mech/arena art, BT defaults dialog, BT score-sheet
print document, Apps.xml BT411 product, live-pod verification.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 22:29:20 -05:00

348 lines
6.9 KiB
C#

using System;
using System.IO;
using System.Windows.Forms;
using System.Xml;
namespace TeslaConsole.BattleTech;
/// <summary>
/// Operator defaults for the two BattleTech game modes, persisted to
/// BTDefaults.btd in the common app-data directory (mirrors
/// <c>RPDefaults</c>/.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.
/// </summary>
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);
}
}