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; } } }