BattleTech results printing, defaults dialog, and BT411 catalog (BT port phase 4)
Completes the BattleTech console feature to parity with Red Planet: - BTPrintDocument: the per-pilot landscape score sheet (mech portrait, placing, kill/death/damage stats, randomized mission-highlights narrative, pilot-vs-pilot damage matrix, place-over-time chart), mirroring RPPrintDocument minus the football/lap/boost/score-zone concepts. Wired into BTGame (Auto Print checkbox + Print Last Mission button) and the shell's File menu (BT Mission Print Preview / Print BT Mission, loading .btm files). - BTStrings(.xml): the BT mission-highlight narrative pools (damage tiers, kill, death-without-honor, recap), loaded from BattleTech\BTStrings.xml like RPStrings. - BTDefaultsDialog: two-column (Free For All / No Return) editor for the BT operator defaults, reachable from Settings (Change/Import/Export BattleTech Defaults). Verified via UI Automation: opens with all 18 option combos populated. - Apps.xml: the BattleTech 4.11 product (btl4.exe on the shared RP411 engine, same -net/-res/-lc/-mr command line; deploys to C:\Games\BT411) with Game Client / Live Camera / Mission Review launch entries. CatalogTests updated to 4 products / 8 entries plus the three new BT entry assertions. Role model spelling corrected to "noreturn": the Mac Console.ini tag and the game's BTL4.RES role resource are dfltrole/NoReturn; the 4.10 console's eggs emitted a broken "noretun" that cannot resolve against the RES. BTGoldenEggTests and BTConfig.xml updated accordingly. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// The BattleTech mission-highlight narrative strings, loaded from
|
||||
/// BattleTech\BTStrings.xml. Mirrors <c>TeslaConsole.RPStrings</c>: 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.
|
||||
/// </summary>
|
||||
internal class BTStrings
|
||||
{
|
||||
private static bool sInitalized = false;
|
||||
|
||||
private static List<string> sLightDamage = new List<string>();
|
||||
|
||||
private static List<string> sModerateDamage = new List<string>();
|
||||
|
||||
private static List<string> sHeavyDamage = new List<string>();
|
||||
|
||||
private static List<string> sKill = new List<string>();
|
||||
|
||||
private static List<string> sDeathWithoutHonor = new List<string>();
|
||||
|
||||
private static List<string> sRecap = new List<string>();
|
||||
|
||||
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<string> 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");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user