using System;
using System.Collections.Generic;
using HutongGames.PlayMaker;
using UnityEngine;
namespace MSCO
{
///
/// Admin-Menü, Reiter VEHICLE: Füllstände und Teile des Satsuma aus der "Database" des Spiels anzeigen und zum Testen
/// reparieren/zerstören. Jedes Teil hat dort ein Objekt mit der FSM "Data" (Installed, Bolted, Damaged, teils Wear);
/// die Füllstände stehen in Tank, Ölwanne, Brems- und Kupplungszylinder. Die Werte überträgt VehicleStateSync an alle.
///
public static class VehicleAdmin
{
public sealed class Fluid
{
public string Label;
public FsmFloat Value;
public float Max;
}
public sealed class Part
{
public string Name, Category;
public FsmBool Damaged, Installed;
public FsmFloat Wear;
}
static readonly List fluids = new List();
static readonly List parts = new List();
static float scannedAt = -100f;
public static List Fluids { get { Refresh(false); return fluids; } }
public static List Parts { get { Refresh(false); return parts; } }
// Füllstand: Teil in der Database, Variable, Anzeige, Maximum (Tank: aus MaxCapacity)
static readonly string[][] FluidDefs =
{
new[] { "FuelTank", "FuelLevel", "Fuel", "36" },
new[] { "Oilpan", "Oil", "Engine oil", "3" },
new[] { "BrakeMasterCylinder", "BrakeFluidF", "Brake fluid (front)", "1" },
new[] { "BrakeMasterCylinder", "BrakeFluidR", "Brake fluid (rear)", "1" },
new[] { "ClutchMasterCylinder", "ClutchFluid", "Clutch fluid", "0.5" },
new[] { "Radiator", "Water", "Coolant", "6" },
};
/// Database neu einlesen (höchstens alle 5 s, außer erzwungen).
public static void Refresh(bool force)
{
if (!force && Time.realtimeSinceStartup - scannedAt < 5f) return;
scannedAt = Time.realtimeSinceStartup;
fluids.Clear();
parts.Clear();
if (!MenuHelper.InGame) return;
var byName = new Dictionary();
foreach (PlayMakerFSM fsm in Resources.FindObjectsOfTypeAll())
{
if (fsm == null || fsm.FsmName != "Data" || fsm.gameObject.hideFlags != HideFlags.None) continue;
Transform t = fsm.transform;
if (t.root.name != "Database" || t.parent == null || t.parent.parent != t.root) continue;
string category = t.parent.name;
if (category == "DatabaseOrders" || category == "PlayerDatabase") continue; // Bestellungen/Spieler: keine Fahrzeugteile
byName[t.name] = fsm;
FsmBool installed = fsm.FsmVariables.FindFsmBool("Installed");
FsmBool damaged = fsm.FsmVariables.FindFsmBool("Damaged");
FsmFloat wear = fsm.FsmVariables.FindFsmFloat("Wear");
if (damaged == null && wear == null) continue;
parts.Add(new Part
{
Name = Pretty(t.name),
Category = category.Replace("Database", ""),
Damaged = damaged, Installed = installed, Wear = wear,
});
}
parts.Sort((a, b) => string.Compare(a.Category + a.Name, b.Category + b.Name, StringComparison.Ordinal));
foreach (string[] def in FluidDefs)
{
PlayMakerFSM fsm;
if (!byName.TryGetValue(def[0], out fsm)) continue;
FsmFloat value = fsm.FsmVariables.FindFsmFloat(def[1]);
if (value == null) continue;
float max = float.Parse(def[3], System.Globalization.CultureInfo.InvariantCulture);
FsmFloat capacity = fsm.FsmVariables.FindFsmFloat("MaxCapacity");
if (def[0] == "FuelTank" && capacity != null && capacity.Value > 0f) max = capacity.Value;
fluids.Add(new Fluid { Label = def[2], Value = value, Max = max });
}
}
/// "RadiatorHose1" -> "Radiator Hose 1", "Drumbrake_RR" -> "Drumbrake RR".
static string Pretty(string name)
{
var sb = new System.Text.StringBuilder();
for (int i = 0; i < name.Length; i++)
{
char c = name[i];
if (c == '_') { sb.Append(' '); continue; }
if (i > 0 && ((char.IsUpper(c) && char.IsLower(name[i - 1])) || (char.IsDigit(c) && !char.IsDigit(name[i - 1])))) sb.Append(' ');
sb.Append(c);
}
return sb.ToString();
}
public static void SetFluid(Fluid f, bool full)
{
if (f.Value != null) f.Value.Value = full ? f.Max : 0f;
}
public static void Repair(Part p)
{
if (p.Damaged != null) p.Damaged.Value = false;
if (p.Wear != null) p.Wear.Value = 100f;
}
public static void Break(Part p)
{
if (p.Damaged != null) p.Damaged.Value = true;
if (p.Wear != null) p.Wear.Value = 0f;
}
public static int RepairAll()
{
Refresh(true);
int n = 0;
foreach (Part p in parts)
{
if (p.Installed != null && !p.Installed.Value) continue;
bool needs = (p.Damaged != null && p.Damaged.Value) || (p.Wear != null && p.Wear.Value < 100f);
if (!needs) continue;
Repair(p);
n++;
}
return n;
}
}
}