Own main menu (game's Continue/New Game/Credits/Changelog/Quit hidden, QUIT in the launcher); new server profile layout; admin items: ratchet set, battery, shop items; session shows server player limit
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,10 @@ Server und Mod müssen beide 2.7 sein (Server: `git pull && docker compose up -d
|
|||||||
- Letzte Position wird zuverlässig gespeichert (nicht mehr immer an der Toilette spawnen)
|
- Letzte Position wird zuverlässig gespeichert (nicht mehr immer an der Toilette spawnen)
|
||||||
- Server-Browser: Klick auf den Server öffnet das Profil (JOIN-Knopf in der Liste entfernt)
|
- Server-Browser: Klick auf den Server öffnet das Profil (JOIN-Knopf in der Liste entfernt)
|
||||||
- Alle Mod-Meldungen nur noch in der MSCO-Konsole (F7)
|
- Alle Mod-Meldungen nur noch in der MSCO-Konsole (F7)
|
||||||
|
- Eigenes Hauptmenü: Continue, New Game, Credits, Changelog und Quit des Spiels sind ausgeblendet, der MSCO-Launcher
|
||||||
|
ist das Hauptmenü (mit eigenem QUIT)
|
||||||
|
- Server-Profil neu: JOIN oben, Spielerliste rechts, Namensfeld ohne Steam in eigenem Kasten
|
||||||
|
- Admin-ITEMS: Werkzeuge und Laden-Artikel (Ratschenkasten, Batterie, Motoröl, Kühlmittel, Bremsflüssigkeit ...)
|
||||||
|
|
||||||
**Behoben**
|
**Behoben**
|
||||||
- Auto fiel beim Fahren eines anderen Spielers auseinander (angebaute Teile rissen an ihren Gelenken ab)
|
- Auto fiel beim Fahren eines anderen Spielers auseinander (angebaute Teile rissen an ihren Gelenken ab)
|
||||||
|
|||||||
+44
-6
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using HutongGames.PlayMaker;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace MSCO
|
namespace MSCO
|
||||||
@@ -7,31 +8,59 @@ namespace MSCO
|
|||||||
/// Admin: Items spawnen. Kopiert ein vorhandenes Item des Spiels (z.B. "beer case(itemx)" aus dem Laden) und
|
/// Admin: Items spawnen. Kopiert ein vorhandenes Item des Spiels (z.B. "beer case(itemx)" aus dem Laden) und
|
||||||
/// setzt die Kopie an die gewünschte Stelle. Die Kopie behält den Namen des Originals, damit sich die Spiel-Logik
|
/// setzt die Kopie an die gewünschte Stelle. Die Kopie behält den Namen des Originals, damit sich die Spiel-Logik
|
||||||
/// (Trinken, Essen, Tanken ...) wie beim echten Item verhält und der Objekt-Sync sie bei allen gleich benennt.
|
/// (Trinken, Essen, Tanken ...) wie beim echten Item verhält und der Objekt-Sync sie bei allen gleich benennt.
|
||||||
|
/// Werkzeuge wie der Ratschenkasten sind im Spiel keine Gegenstände, sondern ein Schalter ("hat der Spieler") -
|
||||||
|
/// die werden dem Admin direkt gegeben.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class ItemSpawner
|
public static class ItemSpawner
|
||||||
{
|
{
|
||||||
/// <summary>Auswahl im Admin-Menü (Name ohne "(itemx)").</summary>
|
/// <summary>Werkzeug statt Gegenstand: globale Spielvariable, die "gekauft" bedeutet.</summary>
|
||||||
|
public const string RatchetSet = "ratchet set";
|
||||||
|
|
||||||
|
/// <summary>Auswahl im Admin-Menü (Anzeigename).</summary>
|
||||||
public static readonly string[] Items =
|
public static readonly string[] Items =
|
||||||
{
|
{
|
||||||
"beer case", "sausages", "pizza", "macaron box", "milk", "juice", "ground coffee", "sugar", "yeast", "booze",
|
// Werkzeug / Auto
|
||||||
"gasoline", "diesel", "spray can", "fire extinguisher", "flashlight", "lantern", "car jack", "floor jack",
|
RatchetSet, "spanner set", "battery", "car jack", "floor jack", "motor hoist", "flashlight", "lantern",
|
||||||
"spanner set", "sledgehammer", "radio", "camera", "grill charcoal", "fireworks bag", "water bucket"
|
"fire extinguisher", "spray can", "sledgehammer", "ax", "digging bar",
|
||||||
|
// Flüssigkeiten / Kraftstoff
|
||||||
|
"motor oil", "coolant", "brake fluid", "two stroke fuel", "gasoline", "diesel", "n2o bottle",
|
||||||
|
// Essen / Trinken / Laden
|
||||||
|
"beer case", "beer", "booze", "vodka shot", "milk", "juice", "coffee", "ground coffee", "sugar", "yeast",
|
||||||
|
"sausages", "pizza", "macaron box", "potato chips", "cigarettes", "mosquito spray", "grill charcoal",
|
||||||
|
// Sonstiges
|
||||||
|
"grill", "radio", "camera", "helmet", "bucket", "water bucket", "fireworks bag", "parts magazine"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Items, die im Spiel nicht "(itemx)" heißen
|
||||||
|
static readonly Dictionary<string, string> objectNames = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "battery", "battery(Clone)" }
|
||||||
};
|
};
|
||||||
|
|
||||||
static readonly Dictionary<string, GameObject> templates = new Dictionary<string, GameObject>();
|
static readonly Dictionary<string, GameObject> templates = new Dictionary<string, GameObject>();
|
||||||
|
|
||||||
|
public static bool IsKnown(string item) { return System.Array.IndexOf(Items, item) >= 0; }
|
||||||
|
|
||||||
|
static string ObjectName(string item)
|
||||||
|
{
|
||||||
|
string name;
|
||||||
|
return objectNames.TryGetValue(item, out name) ? name : item + "(itemx)";
|
||||||
|
}
|
||||||
|
|
||||||
static GameObject FindTemplate(string item)
|
static GameObject FindTemplate(string item)
|
||||||
{
|
{
|
||||||
GameObject cached;
|
GameObject cached;
|
||||||
if (templates.TryGetValue(item, out cached) && cached != null) return cached;
|
if (templates.TryGetValue(item, out cached) && cached != null) return cached;
|
||||||
|
|
||||||
string name = item + "(itemx)";
|
string name = ObjectName(item);
|
||||||
GameObject best = null;
|
GameObject best = null;
|
||||||
foreach (Object o in Resources.FindObjectsOfTypeAll(typeof(GameObject)))
|
foreach (Object o in Resources.FindObjectsOfTypeAll(typeof(GameObject)))
|
||||||
{
|
{
|
||||||
var go = (GameObject)o;
|
var go = (GameObject)o;
|
||||||
if (go.name != name || go.GetComponent<Rigidbody>() == null) continue;
|
if (go.name != name || go.GetComponent<Rigidbody>() == null) continue;
|
||||||
if (best == null || (go.activeInHierarchy && !best.activeInHierarchy)) best = go; // am liebsten ein echtes in der Welt
|
// Keine eingebauten Teile kopieren (z.B. die Batterie im Auto): nicht unter einem anderen Rigidbody
|
||||||
|
if (go.transform.parent != null && go.transform.parent.GetComponentInParent<Rigidbody>() != null) continue;
|
||||||
|
if (best == null || (go.activeInHierarchy && !best.activeInHierarchy)) best = go; // am liebsten eins aus der Welt
|
||||||
}
|
}
|
||||||
templates[item] = best;
|
templates[item] = best;
|
||||||
return best;
|
return best;
|
||||||
@@ -60,6 +89,15 @@ namespace MSCO
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Ratschenkasten "kaufen": der Spieler hat ihn dann wie nach dem Kauf im Laden.</summary>
|
||||||
|
public static bool GiveRatchetSet()
|
||||||
|
{
|
||||||
|
FsmBool has = FsmVariables.GlobalVariables.FindFsmBool("PlayerHasRatchet");
|
||||||
|
if (has == null) return false;
|
||||||
|
has.Value = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public static void ClearCache() { templates.Clear(); }
|
public static void ClearCache() { templates.Clear(); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+79
-37
@@ -31,6 +31,8 @@ namespace MSCO
|
|||||||
static readonly Color Pending = Hex(0xf2, 0xc2, 0x1d);
|
static readonly Color Pending = Hex(0xf2, 0xc2, 0x1d);
|
||||||
|
|
||||||
Page page = Page.P2P;
|
Page page = Page.P2P;
|
||||||
|
Vector2 profileScroll;
|
||||||
|
bool quitConfirm;
|
||||||
bool minimized;
|
bool minimized;
|
||||||
Vector2 playerScroll;
|
Vector2 playerScroll;
|
||||||
Vector2 serverScroll;
|
Vector2 serverScroll;
|
||||||
@@ -46,6 +48,7 @@ namespace MSCO
|
|||||||
Texture2D texBackground, texSidebar, texAccent, texOnline, texPending, texMuted, texRow;
|
Texture2D texBackground, texSidebar, texAccent, texOnline, texPending, texMuted, texRow;
|
||||||
List<ServerListEntry> shownAll, shownServers; // Stand des letzten Layout-Durchgangs
|
List<ServerListEntry> shownAll, shownServers; // Stand des letzten Layout-Durchgangs
|
||||||
string layoutError;
|
string layoutError;
|
||||||
|
GUIStyle dangerStyle;
|
||||||
GUIStyle windowBox, sidebarBox, rowBox, accentBox, pillStyle, pillMutedStyle, chipOnStyle, chipOffStyle;
|
GUIStyle windowBox, sidebarBox, rowBox, accentBox, pillStyle, pillMutedStyle, chipOnStyle, chipOffStyle;
|
||||||
GUIStyle logoStyle, taglineStyle, navStyle, navActiveStyle, titleStyle, textStyle, captionStyle,
|
GUIStyle logoStyle, taglineStyle, navStyle, navActiveStyle, titleStyle, textStyle, captionStyle,
|
||||||
fieldStyle, primaryStyle, secondaryStyle, statusStyle, tabStyle, headerCellStyle,
|
fieldStyle, primaryStyle, secondaryStyle, statusStyle, tabStyle, headerCellStyle,
|
||||||
@@ -112,6 +115,14 @@ namespace MSCO
|
|||||||
y += 44;
|
y += 44;
|
||||||
if (NavButton(new Rect(r.x, y, r.width, 42), "Server Browser", page == Page.ServerBrowser)) page = Page.ServerBrowser;
|
if (NavButton(new Rect(r.x, y, r.width, 42), "Server Browser", page == Page.ServerBrowser)) page = Page.ServerBrowser;
|
||||||
|
|
||||||
|
// Eigenes Hauptmenü: Spiel beenden (die Knöpfe des Spiel-Menüs sind ausgeblendet)
|
||||||
|
if (quitConfirm)
|
||||||
|
{
|
||||||
|
if (GUI.Button(new Rect(r.x + 16, r.yMax - 118, r.width - 32, 36), "QUIT GAME?", dangerStyle)) Application.Quit();
|
||||||
|
if (GUI.Button(new Rect(r.x + 16, r.yMax - 76, r.width - 32, 30), "CANCEL", tabStyle)) quitConfirm = false;
|
||||||
|
}
|
||||||
|
else if (GUI.Button(new Rect(r.x + 16, r.yMax - 76, r.width - 32, 36), "QUIT", tabStyle)) quitConfirm = true;
|
||||||
|
|
||||||
GUI.Label(new Rect(r.x + 24, r.yMax - 30, r.width - 48, 20), "v" + MSCO.ModVersion, taglineStyle);
|
GUI.Label(new Rect(r.x + 24, r.yMax - 30, r.width - 48, 20), "v" + MSCO.ModVersion, taglineStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,7 +306,7 @@ namespace MSCO
|
|||||||
selectedServer = null;
|
selectedServer = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GUILayout.Space(6);
|
GUILayout.Space(8);
|
||||||
|
|
||||||
if (s == null)
|
if (s == null)
|
||||||
{
|
{
|
||||||
@@ -304,64 +315,94 @@ namespace MSCO
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kopf: Name + Abzeichen links, JOIN (und ohne Steam das Namensfeld) rechts - immer sichtbar,
|
// Kopf: Name + Abzeichen links, JOIN rechts - immer sichtbar
|
||||||
// egal wie lang Beschreibung und Spielerliste darunter sind
|
|
||||||
GUILayout.BeginHorizontal();
|
GUILayout.BeginHorizontal();
|
||||||
GUILayout.BeginVertical();
|
GUILayout.BeginVertical();
|
||||||
GUILayout.Label(s.Name, titleStyle);
|
GUILayout.Label(s.Name, titleStyle);
|
||||||
GUILayout.BeginHorizontal();
|
GUILayout.BeginHorizontal();
|
||||||
GUILayout.Label(s.RequireSteam ? "STEAM" : "NON-STEAM", badgeStyle, GUILayout.ExpandWidth(false));
|
Rect badgeRow = GUILayoutUtility.GetRect(10, 20, GUILayout.ExpandWidth(true));
|
||||||
if (s.IsLocal) { GUILayout.Space(10); GUILayout.Label("LOCAL", badgeStyle, GUILayout.ExpandWidth(false)); }
|
float bx = badgeRow.x;
|
||||||
GUILayout.FlexibleSpace();
|
bx += Pill(bx, badgeRow, s.RequireSteam ? "STEAM" : "NON-STEAM", s.RequireSteam ? pillStyle : pillMutedStyle);
|
||||||
|
if (s.IsLocal) bx += Pill(bx, badgeRow, "LOCAL", pillStyle);
|
||||||
|
if (s.Version != MSCO.ModVersion) Pill(bx, badgeRow, "v" + s.Version, pillStyle);
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
GUILayout.EndVertical();
|
GUILayout.EndVertical();
|
||||||
GUILayout.FlexibleSpace();
|
GUILayout.Space(12);
|
||||||
GUILayout.BeginVertical(GUILayout.Width(190));
|
|
||||||
GUI.enabled = CanJoin(mp, s);
|
GUI.enabled = CanJoin(mp, s);
|
||||||
if (GUILayout.Button(s.Players >= s.MaxPlayers ? "SERVER FULL" : "JOIN SERVER", primaryStyle, GUILayout.Height(42), GUILayout.Width(190)))
|
if (GUILayout.Button(s.Players >= s.MaxPlayers ? "SERVER FULL" : "JOIN SERVER", primaryStyle, GUILayout.Height(44), GUILayout.Width(180)))
|
||||||
mp.JoinServer(s.Address, s.Port, s.Name, s.MaxPlayers);
|
mp.JoinServer(s.Address, s.Port, s.Name, s.MaxPlayers);
|
||||||
GUI.enabled = true;
|
GUI.enabled = true;
|
||||||
if (s.RequireSteam && !mp.SteamAvailable)
|
|
||||||
GUILayout.Label("This server requires Steam.", textStyle);
|
|
||||||
else if (!mp.SteamAvailable)
|
|
||||||
{
|
|
||||||
GUILayout.Space(4);
|
|
||||||
GUILayout.BeginHorizontal();
|
|
||||||
GUILayout.Label("NAME", captionStyle, GUILayout.Width(42));
|
|
||||||
DrawNameField(mp, 140);
|
|
||||||
GUILayout.EndHorizontal();
|
|
||||||
}
|
|
||||||
GUILayout.EndVertical();
|
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
if (!string.IsNullOrEmpty(s.Description)) GUILayout.Label(s.Description, textStyle);
|
if (!string.IsNullOrEmpty(s.Description)) GUILayout.Label(s.Description, textStyle);
|
||||||
GUILayout.Space(10);
|
GUILayout.Space(10);
|
||||||
|
|
||||||
|
// Ohne Steam: Name wählen (sauber in einem eigenen Kasten)
|
||||||
|
if (s.RequireSteam && !mp.SteamAvailable)
|
||||||
|
{
|
||||||
|
GUILayout.BeginHorizontal(rowBox, GUILayout.Height(40));
|
||||||
|
GUILayout.Label("This server requires Steam - start the game through Steam to join.", textStyle);
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
GUILayout.Space(10);
|
||||||
|
}
|
||||||
|
else if (!mp.SteamAvailable)
|
||||||
|
{
|
||||||
|
GUILayout.BeginHorizontal(rowBox, GUILayout.Height(44));
|
||||||
|
GUILayout.Space(6);
|
||||||
|
GUILayout.BeginVertical(GUILayout.Width(110));
|
||||||
|
GUILayout.Space(4);
|
||||||
|
GUILayout.Label("PLAYING AS", captionStyle);
|
||||||
|
GUILayout.Label("no Steam", textStyle);
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
GUILayout.BeginVertical();
|
||||||
|
GUILayout.Space(5);
|
||||||
|
DrawNameField(mp, 220);
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
GUILayout.Space(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Infos links, Spielerliste rechts
|
||||||
bool versionOk = s.Version == MSCO.ModVersion;
|
bool versionOk = s.Version == MSCO.ModVersion;
|
||||||
GUILayout.BeginHorizontal();
|
GUILayout.BeginHorizontal();
|
||||||
GUILayout.BeginVertical(GUILayout.Width(250));
|
GUILayout.BeginVertical(GUILayout.Width(250));
|
||||||
InfoRow("HOSTED BY", string.IsNullOrEmpty(s.Owner) ? "unknown" : s.Owner, rowNameStyle);
|
InfoLine("HOSTED BY", string.IsNullOrEmpty(s.Owner) ? "unknown" : s.Owner, rowNameStyle);
|
||||||
InfoRow("VERSION", "v" + s.Version + (versionOk ? "" : " (you: v" + MSCO.ModVersion + ")"), versionOk ? rowNameStyle : badgeStyle);
|
InfoLine("VERSION", "v" + s.Version + (versionOk ? "" : " (you: v" + MSCO.ModVersion + ")"), versionOk ? rowNameStyle : badgeStyle);
|
||||||
InfoRow("STEAM", s.RequireSteam ? "Required" : "Not required", rowNameStyle);
|
InfoLine("STEAM", s.RequireSteam ? "Required" : "Not required", rowNameStyle);
|
||||||
InfoRow("ONLINE FOR", s.UptimeSeconds >= 0 ? FormatUptime(s.UptimeSeconds) : "-", rowNameStyle);
|
InfoLine("ONLINE FOR", s.UptimeSeconds >= 0 ? FormatUptime(s.UptimeSeconds) : "-", rowNameStyle);
|
||||||
|
InfoLine("PING", s.Ping < 0 ? "-" : s.Ping + " ms", rowNameStyle);
|
||||||
|
InfoLine("ADDRESS", s.Address + ":" + s.Port, rowNameStyle);
|
||||||
GUILayout.EndVertical();
|
GUILayout.EndVertical();
|
||||||
GUILayout.BeginVertical();
|
GUILayout.Space(16);
|
||||||
InfoRow("PLAYERS", s.Players + " / " + s.MaxPlayers, rowNameStyle);
|
|
||||||
InfoRow("PING", s.Ping < 0 ? "-" : s.Ping + " ms", rowNameStyle);
|
GUILayout.BeginVertical(rowBox, GUILayout.ExpandWidth(true), GUILayout.MinHeight(150));
|
||||||
InfoRow("ADDRESS", s.Address + ":" + s.Port, rowNameStyle);
|
GUILayout.Space(6);
|
||||||
|
GUILayout.Label("PLAYERS " + s.Players + " / " + s.MaxPlayers, captionStyle);
|
||||||
|
profileScroll = GUILayout.BeginScrollView(profileScroll, GUILayout.Height(130));
|
||||||
|
if (s.PlayerNames == null || s.PlayerNames.Count == 0)
|
||||||
|
GUILayout.Label("Nobody online right now.", textStyle);
|
||||||
|
else
|
||||||
|
foreach (string name in s.PlayerNames)
|
||||||
|
{
|
||||||
|
Rect line = GUILayoutUtility.GetRect(10, 24, GUILayout.ExpandWidth(true));
|
||||||
|
GUI.DrawTexture(new Rect(line.x + 2, line.y + 8, 8, 8), texOnline);
|
||||||
|
GUI.Label(new Rect(line.x + 18, line.y, line.width - 18, line.height), name, rowNameStyle);
|
||||||
|
}
|
||||||
|
GUILayout.EndScrollView();
|
||||||
GUILayout.EndVertical();
|
GUILayout.EndVertical();
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
// Spielerliste
|
|
||||||
if (s.PlayerNames != null && s.PlayerNames.Count > 0)
|
|
||||||
{
|
|
||||||
GUILayout.Space(4);
|
|
||||||
GUILayout.Label("ONLINE", captionStyle);
|
|
||||||
GUILayout.Label(string.Join(", ", s.PlayerNames.ToArray()), textStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
GUILayout.FlexibleSpace();
|
GUILayout.FlexibleSpace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Eine Info-Zeile: Bezeichnung links (grau), Wert rechts.</summary>
|
||||||
|
void InfoLine(string caption, string value, GUIStyle valueStyle)
|
||||||
|
{
|
||||||
|
GUILayout.BeginHorizontal(GUILayout.Height(26));
|
||||||
|
GUILayout.Label(caption, captionStyle, GUILayout.Width(100));
|
||||||
|
GUILayout.Label(value, valueStyle);
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Kleines abgerundetes Abzeichen, so breit wie sein Text. Gibt die belegte Breite zurück.</summary>
|
/// <summary>Kleines abgerundetes Abzeichen, so breit wie sein Text. Gibt die belegte Breite zurück.</summary>
|
||||||
static float Pill(float x, Rect row, string text, GUIStyle style)
|
static float Pill(float x, Rect row, string text, GUIStyle style)
|
||||||
{
|
{
|
||||||
@@ -576,6 +617,7 @@ namespace MSCO
|
|||||||
navActiveStyle.padding = new RectOffset(26, 10, 0, 0);
|
navActiveStyle.padding = new RectOffset(26, 10, 0, 0);
|
||||||
|
|
||||||
primaryStyle = Button(Accent, AccentHover, Color.white, 14, FontStyle.Bold);
|
primaryStyle = Button(Accent, AccentHover, Color.white, 14, FontStyle.Bold);
|
||||||
|
dangerStyle = Button(UiTheme.Danger, UiTheme.DangerHover, Color.white, 13, FontStyle.Bold);
|
||||||
secondaryStyle = Button(Secondary, SecondaryHover, Color.white, 14, FontStyle.Bold);
|
secondaryStyle = Button(Secondary, SecondaryHover, Color.white, 14, FontStyle.Bold);
|
||||||
tabStyle = Button(Sidebar, Secondary, Muted, 11, FontStyle.Bold);
|
tabStyle = Button(Sidebar, Secondary, Muted, 11, FontStyle.Bold);
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,27 @@ namespace MSCO
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Startet das Spiel wie ein Klick auf CONTINUE.</summary>
|
/// <summary>Startet das Spiel wie ein Klick auf CONTINUE.</summary>
|
||||||
|
// Knöpfe des Spiel-Hauptmenüs, die MSCO ersetzt (der MSCO-Launcher ist das Hauptmenü)
|
||||||
|
static readonly string[] HiddenMenuButtons = { "ButtonContinue", "ButtonNewgame", "ButtonCredits", "ButtonQuit", "ButtonChangelog" };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Continue, New Game, Credits, Changelog und Quit des Spiels unsichtbar und unklickbar machen. Nicht abschalten:
|
||||||
|
/// die Logik hinter CONTINUE lädt beim Beitreten den übertragenen Spielstand (StartGame). Gibt die Anzahl zurück.
|
||||||
|
/// </summary>
|
||||||
|
public static int HideGameMenuButtons()
|
||||||
|
{
|
||||||
|
int hidden = 0;
|
||||||
|
foreach (string name in HiddenMenuButtons)
|
||||||
|
{
|
||||||
|
GameObject button = GameObject.Find(name);
|
||||||
|
if (button == null) continue;
|
||||||
|
foreach (Renderer r in button.GetComponentsInChildren<Renderer>(true)) r.enabled = false;
|
||||||
|
foreach (Collider c in button.GetComponentsInChildren<Collider>(true)) c.enabled = false;
|
||||||
|
hidden++;
|
||||||
|
}
|
||||||
|
return hidden;
|
||||||
|
}
|
||||||
|
|
||||||
public static void StartGame()
|
public static void StartGame()
|
||||||
{
|
{
|
||||||
PlayMakerFSM fsm;
|
PlayMakerFSM fsm;
|
||||||
|
|||||||
+18
-1
@@ -344,6 +344,13 @@ namespace MSCO
|
|||||||
public void SpawnItem(string item)
|
public void SpawnItem(string item)
|
||||||
{
|
{
|
||||||
if (!CanCheat || localPlayer == null) return;
|
if (!CanCheat || localPlayer == null) return;
|
||||||
|
if (item == ItemSpawner.RatchetSet)
|
||||||
|
{
|
||||||
|
// Werkzeug, kein Gegenstand: nur für einen selbst freischalten
|
||||||
|
overlays.Log(ItemSpawner.GiveRatchetSet() ? "You now have the ratchet set" : "Ratchet set not found (only works in the game)");
|
||||||
|
AnnounceCheat("gave themselves the ratchet set");
|
||||||
|
return;
|
||||||
|
}
|
||||||
Transform head = playerCamera != null ? playerCamera.transform : localPlayer;
|
Transform head = playerCamera != null ? playerCamera.transform : localPlayer;
|
||||||
Vector3 forward = new Vector3(head.forward.x, 0f, head.forward.z).normalized;
|
Vector3 forward = new Vector3(head.forward.x, 0f, head.forward.z).normalized;
|
||||||
if (forward.sqrMagnitude < 0.01f) forward = localPlayer.forward;
|
if (forward.sqrMagnitude < 0.01f) forward = localPlayer.forward;
|
||||||
@@ -366,7 +373,7 @@ namespace MSCO
|
|||||||
string item = r.ReadString();
|
string item = r.ReadString();
|
||||||
var pos = new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
|
var pos = new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
|
||||||
var rot = new Quaternion(r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
|
var rot = new Quaternion(r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
|
||||||
if (System.Array.IndexOf(ItemSpawner.Items, item) < 0) return false; // nur bekannte Items
|
if (!ItemSpawner.IsKnown(item) || item == ItemSpawner.RatchetSet) return false; // nur bekannte Gegenstände
|
||||||
return ItemSpawner.Spawn(item, pos, rot);
|
return ItemSpawner.Spawn(item, pos, rot);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -740,6 +747,12 @@ namespace MSCO
|
|||||||
// Solange das Multiplayer-Fenster offen ist, reagiert das Spielmenü (CONTINUE, QUIT ...) gar nicht;
|
// Solange das Multiplayer-Fenster offen ist, reagiert das Spielmenü (CONTINUE, QUIT ...) gar nicht;
|
||||||
// erst nach MINIMIZE wieder. Über der eingeklappten Leiste ebenfalls nicht (sonst öffnet sich z.B. der Changelog).
|
// erst nach MINIMIZE wieder. Über der eingeklappten Leiste ebenfalls nicht (sonst öffnet sich z.B. der Changelog).
|
||||||
MenuInputBlocker.SetBlocked(MenuHelper.InMenu && (lobby.IsOpen || lobby.ContainsMouse() || overlays.AnyOpen));
|
MenuInputBlocker.SetBlocked(MenuHelper.InMenu && (lobby.IsOpen || lobby.ContainsMouse() || overlays.AnyOpen));
|
||||||
|
// Eigenes Hauptmenü: Singleplayer-Knöpfe des Spiels ausblenden (einmal pro Menü-Besuch, sobald sie da sind)
|
||||||
|
if (MenuHelper.InMenu && !menuButtonsHidden && Time.realtimeSinceStartup >= nextMenuButtonCheck)
|
||||||
|
{
|
||||||
|
nextMenuButtonCheck = Time.realtimeSinceStartup + 0.5f;
|
||||||
|
menuButtonsHidden = MenuHelper.HideGameMenuButtons() > 0;
|
||||||
|
}
|
||||||
UpdateOverlayKeys();
|
UpdateOverlayKeys();
|
||||||
MscoLog.Drain(overlays.Log); // alle Mod-Meldungen in die MSCO-Konsole (F7)
|
MscoLog.Drain(overlays.Log); // alle Mod-Meldungen in die MSCO-Konsole (F7)
|
||||||
UpdatePresence();
|
UpdatePresence();
|
||||||
@@ -1232,8 +1245,12 @@ namespace MSCO
|
|||||||
MscoLog.Info("[MSCO] Sent save (" + files.Count + " files) to " + targets.Count + " player(s)");
|
MscoLog.Info("[MSCO] Sent save (" + files.Count + " files) to " + targets.Count + " player(s)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool menuButtonsHidden;
|
||||||
|
float nextMenuButtonCheck;
|
||||||
|
|
||||||
void OnLevelWasLoaded(int level)
|
void OnLevelWasLoaded(int level)
|
||||||
{
|
{
|
||||||
|
menuButtonsHidden = false; // neues Hauptmenü: Knöpfe wieder ausblenden
|
||||||
nextPresenceUpdate = 0f; // Discord gleich nach dem Szenenwechsel aktualisieren
|
nextPresenceUpdate = 0f; // Discord gleich nach dem Szenenwechsel aktualisieren
|
||||||
if (MenuHelper.InGame)
|
if (MenuHelper.InGame)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user