146 lines
6.0 KiB
C#
146 lines
6.0 KiB
C#
using System.Reflection;
|
|
using HutongGames.PlayMaker;
|
|
using HutongGames.PlayMaker.Actions;
|
|
using MSCLoader;
|
|
using UnityEngine;
|
|
|
|
namespace MSCO
|
|
{
|
|
/// <summary>Hilfsfunktionen rund um Hauptmenü und das Laden der Spielszene.</summary>
|
|
public static class MenuHelper
|
|
{
|
|
public const string MenuScene = "MainMenu";
|
|
public const string GameScene = "GAME";
|
|
|
|
public static bool InMenu { get { return Application.loadedLevelName == MenuScene; } }
|
|
public static bool InGame { get { return Application.loadedLevelName == GameScene; } }
|
|
|
|
static readonly MethodInfo switchState =
|
|
typeof(Fsm).GetMethod("SwitchState", BindingFlags.NonPublic | BindingFlags.Instance);
|
|
|
|
/// <summary>
|
|
/// Sucht im Hauptmenü die PlayMaker-FSM des CONTINUE-Buttons und den Zustand,
|
|
/// der per LoadLevel die Szene "GAME" lädt.
|
|
/// </summary>
|
|
public static bool FindContinueLoadState(out PlayMakerFSM fsm, out FsmState state)
|
|
{
|
|
fsm = null;
|
|
state = null;
|
|
foreach (Object o in Object.FindObjectsOfType(typeof(PlayMakerFSM)))
|
|
{
|
|
var candidate = (PlayMakerFSM)o;
|
|
if (!HierarchyContains(candidate.transform, "continue")) continue;
|
|
|
|
foreach (FsmState s in candidate.FsmStates)
|
|
{
|
|
if (!s.ActionsLoaded) s.LoadActions();
|
|
if (s.Actions == null) continue;
|
|
foreach (FsmStateAction action in s.Actions)
|
|
{
|
|
var load = action as LoadLevel;
|
|
if (load != null && load.levelName != null && load.levelName.Value == GameScene)
|
|
{
|
|
fsm = candidate;
|
|
state = s;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <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()
|
|
{
|
|
PlayMakerFSM fsm;
|
|
FsmState state;
|
|
if (switchState != null && FindContinueLoadState(out fsm, out state))
|
|
{
|
|
MscoLog.Info("[MSCO] Loading via CONTINUE (" + fsm.name + " / " + state.Name + ")");
|
|
switchState.Invoke(fsm.Fsm, new object[] { state });
|
|
}
|
|
else
|
|
{
|
|
MscoLog.Warning("[MSCO] CONTINUE button not found, loading GAME directly");
|
|
Application.LoadLevel(GameScene);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Neues Spiel starten (der Spielstand wurde vorher geleert): über die Logik des NEW-GAME-Knopfs des Spiels,
|
|
/// sonst wie CONTINUE - ohne Spielstand legt das Spiel dann eine frische Welt an.
|
|
/// </summary>
|
|
public static void StartNewGame()
|
|
{
|
|
PlayMakerFSM fsm;
|
|
FsmState state;
|
|
if (switchState != null && FindLoadState("newgame", out fsm, out state))
|
|
{
|
|
MscoLog.Info("[MSCO] Starting a new game via NEW GAME (" + fsm.name + " / " + state.Name + ")");
|
|
switchState.Invoke(fsm.Fsm, new object[] { state });
|
|
return;
|
|
}
|
|
MscoLog.Info("[MSCO] NEW GAME button not found - starting with an empty save");
|
|
StartGame();
|
|
}
|
|
|
|
/// <summary>FSM unter einem Objekt, dessen Name "hint" enthält, mit einem Zustand, der eine Szene lädt.</summary>
|
|
static bool FindLoadState(string hint, out PlayMakerFSM fsm, out FsmState state)
|
|
{
|
|
fsm = null;
|
|
state = null;
|
|
// Nur aktive Objekte der Menü-Szene (die Spiel-Knöpfe sind nur unsichtbar, nicht abgeschaltet)
|
|
foreach (Object o in Object.FindObjectsOfType(typeof(PlayMakerFSM)))
|
|
{
|
|
var candidate = (PlayMakerFSM)o;
|
|
if (!HierarchyContains(candidate.transform, hint)) continue;
|
|
foreach (FsmState s in candidate.FsmStates)
|
|
{
|
|
if (!s.ActionsLoaded) s.LoadActions();
|
|
if (s.Actions == null) continue;
|
|
foreach (FsmStateAction action in s.Actions)
|
|
{
|
|
var load = action as LoadLevel;
|
|
if (load != null && load.levelName != null && !string.IsNullOrEmpty(load.levelName.Value))
|
|
{
|
|
fsm = candidate;
|
|
state = s;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static bool HierarchyContains(Transform t, string text)
|
|
{
|
|
for (; t != null; t = t.parent)
|
|
if (t.name.ToLower().Contains(text)) return true;
|
|
return false;
|
|
}
|
|
}
|
|
}
|