MSCO 2.10.2: passenger only while moving, drain plug sync, admin VEHICLE tab, profile layout
- Passenger: auto ride-along only when the vehicle moves (speed from its motion, also for kinematic remote cars) - no more getting stuck while working in the engine bay or re-captured - Bolts with a function (drain plug: stage 0-5 = oil leak on) are synced as stage and applied through the bolt's own stage logic; world authority sends its state once after joining. Fixes endless oil leaking when players had the drain plug in different states - Admin menu VEHICLE tab: fluids with FILL/EMPTY, all Database parts with wear/damage, REPAIR/BREAK per part, REPAIR ALL, filter - Server profile: info and players as two equal cards, no wrapping - fsmdump also lists FSM variables Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+110
-6
@@ -293,24 +293,128 @@ namespace MSCO
|
||||
|
||||
// Reiter
|
||||
GUILayout.BeginHorizontal();
|
||||
string[] tabs = { "PLAYERS", "TELEPORT", "ITEMS", "BANS" + (bannedIds != null && bannedIds.Count > 0 ? " (" + bannedIds.Count + ")" : ""), "WORLD" };
|
||||
string[] tabs = { "PLAYERS", "TELEPORT", "VEHICLE", "ITEMS", "BANS" + (bannedIds != null && bannedIds.Count > 0 ? " (" + bannedIds.Count + ")" : ""), "WORLD" };
|
||||
for (int i = 0; i < tabs.Length; i++)
|
||||
{
|
||||
if (GUILayout.Button(tabs[i], adminTab == i ? primary : secondary, GUILayout.Height(30), GUILayout.Width(120))) adminTab = i;
|
||||
if (GUILayout.Button(tabs[i], adminTab == i ? primary : secondary, GUILayout.Height(30), GUILayout.Width(104))) adminTab = i;
|
||||
GUILayout.Space(6);
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
GUILayout.Space(10);
|
||||
|
||||
if (adminTab == 1) DrawAdminTeleport(mp);
|
||||
else if (adminTab == 2) DrawAdminItems(mp);
|
||||
else if (adminTab == 3) DrawAdminBans(mp);
|
||||
else if (adminTab == 4) DrawAdminWorld(mp);
|
||||
else if (adminTab == 2) DrawAdminVehicle(mp);
|
||||
else if (adminTab == 3) DrawAdminItems(mp);
|
||||
else if (adminTab == 4) DrawAdminBans(mp);
|
||||
else if (adminTab == 5) DrawAdminWorld(mp);
|
||||
else DrawAdminPlayers(mp);
|
||||
GUILayout.EndArea();
|
||||
}
|
||||
|
||||
Vector2 teleportScroll;
|
||||
Vector2 teleportScroll, vehicleScroll;
|
||||
Texture2D texBarBack, texBarFill, texBarLow;
|
||||
string partFilter = "";
|
||||
|
||||
/// <summary>Reiter VEHICLE: Füllstände und Teile des Satsuma reparieren/zerstören (zum Testen).</summary>
|
||||
void DrawAdminVehicle(MultiplayerManager mp)
|
||||
{
|
||||
if (!mp.CanCheat)
|
||||
{
|
||||
GUILayout.Label("Only works in the game.", small);
|
||||
return;
|
||||
}
|
||||
if (texBarBack == null)
|
||||
{
|
||||
texBarBack = UiTheme.Solid(new Color(1f, 1f, 1f, 0.1f));
|
||||
texBarFill = UiTheme.Solid(UiTheme.Online);
|
||||
texBarLow = UiTheme.Solid(UiTheme.Danger);
|
||||
}
|
||||
|
||||
GUILayout.BeginHorizontal();
|
||||
if (GUILayout.Button("REPAIR ALL", primary, GUILayout.Height(30), GUILayout.Width(130)))
|
||||
{
|
||||
int n = VehicleAdmin.RepairAll();
|
||||
Log(n + " part(s) repaired");
|
||||
if (n > 0) mp.VehicleCheat("repaired the Satsuma (" + n + " parts)");
|
||||
}
|
||||
GUILayout.Space(6);
|
||||
if (GUILayout.Button("REFRESH", secondary, GUILayout.Height(30), GUILayout.Width(100))) VehicleAdmin.Refresh(true);
|
||||
GUILayout.Space(12);
|
||||
GUILayout.Label("Filter", caption, GUILayout.Width(44));
|
||||
partFilter = GUILayout.TextField(partFilter ?? "", 30, field, GUILayout.Height(30));
|
||||
GUILayout.EndHorizontal();
|
||||
GUILayout.Space(8);
|
||||
|
||||
vehicleScroll = GUILayout.BeginScrollView(vehicleScroll);
|
||||
GUILayout.Label("FLUIDS", caption);
|
||||
List<VehicleAdmin.Fluid> fluids = VehicleAdmin.Fluids;
|
||||
if (fluids.Count == 0) GUILayout.Label("No fluids found (only works in the game).", small);
|
||||
foreach (VehicleAdmin.Fluid f in fluids)
|
||||
{
|
||||
GUILayout.BeginHorizontal(rowStyle, GUILayout.Height(36));
|
||||
GUILayout.Label(f.Label, chatName, GUILayout.Width(170));
|
||||
Rect bar = GUILayoutUtility.GetRect(120, 36, GUILayout.ExpandWidth(true));
|
||||
float frac = f.Max > 0f ? Mathf.Clamp01(f.Value.Value / f.Max) : 0f;
|
||||
var back = new Rect(bar.x, bar.y + 15, bar.width, 6);
|
||||
GUI.DrawTexture(back, texBarBack);
|
||||
GUI.DrawTexture(new Rect(back.x, back.y, Mathf.Max(2f, back.width * frac), back.height), frac < 0.25f ? texBarLow : texBarFill);
|
||||
GUILayout.Label(f.Value.Value.ToString("0.00") + " / " + f.Max.ToString("0.#"), small, GUILayout.Width(90));
|
||||
if (GUILayout.Button("FILL", secondary, GUILayout.Height(26), GUILayout.Width(64)))
|
||||
{
|
||||
VehicleAdmin.SetFluid(f, true);
|
||||
mp.VehicleCheat("filled up " + f.Label.ToLower());
|
||||
}
|
||||
GUILayout.Space(4);
|
||||
if (GUILayout.Button("EMPTY", danger, GUILayout.Height(26), GUILayout.Width(70)))
|
||||
{
|
||||
VehicleAdmin.SetFluid(f, false);
|
||||
mp.VehicleCheat("emptied " + f.Label.ToLower());
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
GUILayout.Space(3);
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
GUILayout.Label("PARTS (wear: 100 = new)", caption);
|
||||
string filter = (partFilter ?? "").Trim().ToLowerInvariant();
|
||||
int shown = 0;
|
||||
foreach (VehicleAdmin.Part p in VehicleAdmin.Parts)
|
||||
{
|
||||
if (filter.Length > 0 && !(p.Name + " " + p.Category).ToLowerInvariant().Contains(filter)) continue;
|
||||
shown++;
|
||||
bool installed = p.Installed == null || p.Installed.Value;
|
||||
bool damaged = p.Damaged != null && p.Damaged.Value;
|
||||
GUILayout.BeginHorizontal(rowStyle, GUILayout.Height(36));
|
||||
GUILayout.BeginVertical(GUILayout.Width(220));
|
||||
GUILayout.Label(p.Name, chatName);
|
||||
GUILayout.Label(p.Category + (installed ? "" : " · not installed"), small);
|
||||
GUILayout.EndVertical();
|
||||
Rect bar = GUILayoutUtility.GetRect(100, 36, GUILayout.ExpandWidth(true));
|
||||
if (p.Wear != null)
|
||||
{
|
||||
float frac = Mathf.Clamp01(p.Wear.Value / 100f);
|
||||
var back = new Rect(bar.x, bar.y + 15, bar.width, 6);
|
||||
GUI.DrawTexture(back, texBarBack);
|
||||
GUI.DrawTexture(new Rect(back.x, back.y, Mathf.Max(2f, back.width * frac), back.height), frac < 0.3f ? texBarLow : texBarFill);
|
||||
}
|
||||
GUILayout.Label(damaged ? "DAMAGED" : p.Wear != null ? p.Wear.Value.ToString("0") + " %" : "OK", damaged ? danger : small, GUILayout.Width(84));
|
||||
if (GUILayout.Button("REPAIR", secondary, GUILayout.Height(26), GUILayout.Width(76)))
|
||||
{
|
||||
VehicleAdmin.Repair(p);
|
||||
mp.VehicleCheat("repaired " + p.Name);
|
||||
}
|
||||
GUILayout.Space(4);
|
||||
if (GUILayout.Button("BREAK", danger, GUILayout.Height(26), GUILayout.Width(70)))
|
||||
{
|
||||
VehicleAdmin.Break(p);
|
||||
mp.VehicleCheat("broke " + p.Name + " (testing)");
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
GUILayout.Space(3);
|
||||
}
|
||||
if (shown == 0) GUILayout.Label(VehicleAdmin.Parts.Count == 0 ? "No parts found (only works in the game)." : "No part matches the filter.", small);
|
||||
GUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
void DrawAdminTeleport(MultiplayerManager mp)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user