forked from nikita/muzika-gromche
Override DeathScreen / GameOver text, add support for per-track strings
Custom message is shown only if the player dies to a Jester.
This commit is contained in:
parent
0fadf50bf4
commit
e67c72951e
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
## MuzikaGromche 1337.420.9004
|
## MuzikaGromche 1337.420.9004
|
||||||
|
|
||||||
|
- Override Death Screen / Game Over text in certain cases.
|
||||||
|
|
||||||
## MuzikaGromche 1337.420.9003 - Lights Out Edition
|
## MuzikaGromche 1337.420.9003 - Lights Out Edition
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
using System.Collections;
|
||||||
|
using HarmonyLib;
|
||||||
|
using TMPro;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace MuzikaGromche
|
||||||
|
{
|
||||||
|
static class DeathScreenGameOverTextManager
|
||||||
|
{
|
||||||
|
private const string GameOverTextVanilla = "[LIFE SUPPORT: OFFLINE]";
|
||||||
|
|
||||||
|
public const string GameOverTextModdedDefault = "[ MUZIKA: GROMCHE ]";
|
||||||
|
|
||||||
|
public static void Clear()
|
||||||
|
{
|
||||||
|
SetTextImpl(GameOverTextVanilla);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetText(string? text)
|
||||||
|
{
|
||||||
|
SetTextImpl(text ?? GameOverTextModdedDefault);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerator SetTextAndClear(string? text)
|
||||||
|
{
|
||||||
|
SetText(text);
|
||||||
|
// Game Over animation duration is about 4.25 seconds
|
||||||
|
yield return new WaitForSeconds(5f);
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetTextImpl(string text)
|
||||||
|
{
|
||||||
|
GameObject textGameObject = GameObject.Find("Systems/UI/Canvas/DeathScreen/GameOverText");
|
||||||
|
if (textGameObject == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TextMeshProUGUI tmp = textGameObject.GetComponent<TextMeshProUGUI>();
|
||||||
|
if (tmp == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var transform = textGameObject.GetComponent<RectTransform>();
|
||||||
|
if (transform == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Default transform width is 645.8 which only fit the default message and no extra characters
|
||||||
|
Vector2 size = transform.sizeDelta;
|
||||||
|
if (Mathf.Approximately(size.x, 645.8f))
|
||||||
|
{
|
||||||
|
size.x += 100f;
|
||||||
|
transform.sizeDelta = size;
|
||||||
|
}
|
||||||
|
tmp.text = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(RoundManager))]
|
||||||
|
static class DeathScreenGameOverTextResetPatch
|
||||||
|
{
|
||||||
|
[HarmonyPatch(nameof(RoundManager.DespawnPropsAtEndOfRound))]
|
||||||
|
[HarmonyPatch(nameof(RoundManager.OnDestroy))]
|
||||||
|
[HarmonyPrefix]
|
||||||
|
static void OnDestroy(RoundManager __instance)
|
||||||
|
{
|
||||||
|
var _ = __instance;
|
||||||
|
DeathScreenGameOverTextManager.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -52,6 +52,12 @@
|
||||||
<Reference Include="Unity.Netcode.Runtime" Publicize="true" Private="false">
|
<Reference Include="Unity.Netcode.Runtime" Publicize="true" Private="false">
|
||||||
<HintPath>$(LethalCompanyDir)Lethal Company_Data\Managed\Unity.Netcode.Runtime.dll</HintPath>
|
<HintPath>$(LethalCompanyDir)Lethal Company_Data\Managed\Unity.Netcode.Runtime.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="Unity.TextMeshPro" Publicize="true" Private="False">
|
||||||
|
<HintPath>$(LethalCompanyDir)Lethal Company_Data\Managed\Unity.TextMeshPro.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="UnityEngine.UI" Publicize="true" Private="False">
|
||||||
|
<HintPath>$(LethalCompanyDir)Lethal Company_Data\Managed\UnityEngine.UI.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
|
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
|
||||||
|
|
|
@ -260,6 +260,7 @@ namespace MuzikaGromche
|
||||||
FadeOutDuration = 4,
|
FadeOutDuration = 4,
|
||||||
FlickerLightsTimeSeries = [-5, 31],
|
FlickerLightsTimeSeries = [-5, 31],
|
||||||
Lyrics = [],
|
Lyrics = [],
|
||||||
|
GameOverText = "[MUZIKA GROMCHE: K-POP]",
|
||||||
},
|
},
|
||||||
new SelectableAudioTrack
|
new SelectableAudioTrack
|
||||||
{
|
{
|
||||||
|
@ -278,6 +279,7 @@ namespace MuzikaGromche
|
||||||
FadeOutDuration = 4,
|
FadeOutDuration = 4,
|
||||||
FlickerLightsTimeSeries = [-5],
|
FlickerLightsTimeSeries = [-5],
|
||||||
Lyrics = [],
|
Lyrics = [],
|
||||||
|
GameOverText = "[COULD'VE BEEN: IMMORTAL]",
|
||||||
},
|
},
|
||||||
new SelectableAudioTrack
|
new SelectableAudioTrack
|
||||||
{
|
{
|
||||||
|
@ -296,6 +298,7 @@ namespace MuzikaGromche
|
||||||
FadeOutDuration = 4,
|
FadeOutDuration = 4,
|
||||||
FlickerLightsTimeSeries = [-5.5f, 31, 63.9f],
|
FlickerLightsTimeSeries = [-5.5f, 31, 63.9f],
|
||||||
Lyrics = [],
|
Lyrics = [],
|
||||||
|
GameOverText = "[ HEY, YOUNG BLOOD ]",
|
||||||
},
|
},
|
||||||
new SelectableAudioTrack
|
new SelectableAudioTrack
|
||||||
{
|
{
|
||||||
|
@ -443,6 +446,7 @@ namespace MuzikaGromche
|
||||||
(96, $"\t\t\tresolving ur private IP\n/{PwnLyricsVariants[^1]}"),
|
(96, $"\t\t\tresolving ur private IP\n/{PwnLyricsVariants[^1]}"),
|
||||||
(98, $"\t\t\tresolving ur private IP\nP_WNED"),
|
(98, $"\t\t\tresolving ur private IP\nP_WNED"),
|
||||||
],
|
],
|
||||||
|
GameOverText = "[HACK3D BY: RUSSI4NS]",
|
||||||
},
|
},
|
||||||
new SelectableAudioTrack
|
new SelectableAudioTrack
|
||||||
{
|
{
|
||||||
|
@ -467,6 +471,7 @@ namespace MuzikaGromche
|
||||||
FadeOutDuration = 6,
|
FadeOutDuration = 6,
|
||||||
FlickerLightsTimeSeries = [-120.5f, -105, -89, -8, 44, 45],
|
FlickerLightsTimeSeries = [-120.5f, -105, -89, -8, 44, 45],
|
||||||
Lyrics = [],
|
Lyrics = [],
|
||||||
|
GameOverText = "[DIDN'T PUMP IT: LOUDER]",
|
||||||
},
|
},
|
||||||
new SelectableAudioTrack
|
new SelectableAudioTrack
|
||||||
{
|
{
|
||||||
|
@ -680,6 +685,7 @@ namespace MuzikaGromche
|
||||||
harmony.PatchAll(typeof(DiscoBallTilePatch));
|
harmony.PatchAll(typeof(DiscoBallTilePatch));
|
||||||
harmony.PatchAll(typeof(DiscoBallDespawnPatch));
|
harmony.PatchAll(typeof(DiscoBallDespawnPatch));
|
||||||
harmony.PatchAll(typeof(SpawnRatePatch));
|
harmony.PatchAll(typeof(SpawnRatePatch));
|
||||||
|
harmony.PatchAll(typeof(DeathScreenGameOverTextResetPatch));
|
||||||
NetcodePatcher();
|
NetcodePatcher();
|
||||||
Compatibility.Register(this);
|
Compatibility.Register(this);
|
||||||
}
|
}
|
||||||
|
@ -882,6 +888,8 @@ namespace MuzikaGromche
|
||||||
public string[] LyricsLines { get; }
|
public string[] LyricsLines { get; }
|
||||||
|
|
||||||
public Palette Palette { get; }
|
public Palette Palette { get; }
|
||||||
|
|
||||||
|
public string? GameOverText { get => null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// A proxy audio track with default implementation for every IAudioTrack method that simply forwards requests to the inner IAudioTrack.
|
// A proxy audio track with default implementation for every IAudioTrack method that simply forwards requests to the inner IAudioTrack.
|
||||||
|
@ -907,6 +915,7 @@ namespace MuzikaGromche
|
||||||
float[] IAudioTrack.LyricsTimeSeries => Track.LyricsTimeSeries;
|
float[] IAudioTrack.LyricsTimeSeries => Track.LyricsTimeSeries;
|
||||||
string[] IAudioTrack.LyricsLines => Track.LyricsLines;
|
string[] IAudioTrack.LyricsLines => Track.LyricsLines;
|
||||||
Palette IAudioTrack.Palette => Track.Palette;
|
Palette IAudioTrack.Palette => Track.Palette;
|
||||||
|
string? IAudioTrack.GameOverText => Track.GameOverText;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Core audio track implementation with some defaults and config overrides.
|
// Core audio track implementation with some defaults and config overrides.
|
||||||
|
@ -982,6 +991,8 @@ namespace MuzikaGromche
|
||||||
}
|
}
|
||||||
|
|
||||||
public Palette Palette { get; set; } = Palette.DEFAULT;
|
public Palette Palette { get; set; } = Palette.DEFAULT;
|
||||||
|
|
||||||
|
public string? GameOverText { get; init; } = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Standalone, top-level, selectable audio track
|
// Standalone, top-level, selectable audio track
|
||||||
|
@ -1881,6 +1892,7 @@ namespace MuzikaGromche
|
||||||
SetupEntriesToSkipWinding(configFile);
|
SetupEntriesToSkipWinding(configFile);
|
||||||
SetupEntriesForPaletteOverride(configFile);
|
SetupEntriesForPaletteOverride(configFile);
|
||||||
SetupEntriesForTimingsOverride(configFile);
|
SetupEntriesForTimingsOverride(configFile);
|
||||||
|
SetupEntriesForGameOverText(configFile);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var chanceRange = new AcceptableValueRange<int>(0, 100);
|
var chanceRange = new AcceptableValueRange<int>(0, 100);
|
||||||
|
@ -2182,6 +2194,33 @@ namespace MuzikaGromche
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetupEntriesForGameOverText(ConfigFile configFile)
|
||||||
|
{
|
||||||
|
const string section = "Game Over";
|
||||||
|
var gameOverTextConfigEntry = configFile.Bind(section, "Game Over Text", DeathScreenGameOverTextManager.GameOverTextModdedDefault,
|
||||||
|
new ConfigDescription("Custom Game Over text to show."));
|
||||||
|
LethalConfigManager.AddConfigItem(new GenericButtonConfigItem(section, "Game Over Animation",
|
||||||
|
"Run Death Screen / Game Over animation 3 times.", "Trigger", () =>
|
||||||
|
{
|
||||||
|
HUDManager.Instance.StartCoroutine(AnimateGameOverText(gameOverTextConfigEntry.Value));
|
||||||
|
}));
|
||||||
|
LethalConfigManager.AddConfigItem(new TextInputFieldConfigItem(gameOverTextConfigEntry, requiresRestart: false));
|
||||||
|
}
|
||||||
|
|
||||||
|
static IEnumerator AnimateGameOverText(string text)
|
||||||
|
{
|
||||||
|
yield return new WaitForSeconds(1f);
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
DeathScreenGameOverTextManager.SetText(text);
|
||||||
|
HUDManager.Instance.gameOverAnimator.SetTrigger("gameOver");
|
||||||
|
yield return new WaitForSeconds(5f);
|
||||||
|
HUDManager.Instance.gameOverAnimator.SetTrigger("revive");
|
||||||
|
yield return new WaitForSeconds(1f);
|
||||||
|
}
|
||||||
|
DeathScreenGameOverTextManager.Clear();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private T Default<T>(T options) where T : BaseOptions
|
private T Default<T>(T options) where T : BaseOptions
|
||||||
|
@ -2335,6 +2374,16 @@ namespace MuzikaGromche
|
||||||
LoopAudioSource.PlayScheduled(loopStartDspTime);
|
LoopAudioSource.PlayScheduled(loopStartDspTime);
|
||||||
Debug.Log($"{nameof(MuzikaGromche)} Play Intro: dspTime={AudioSettings.dspTime:N4}, intro.time={IntroAudioSource.time:N4}/{IntroAudioSource.clip.length:N4}, scheduled Loop={loopStartDspTime}");
|
Debug.Log($"{nameof(MuzikaGromche)} Play Intro: dspTime={AudioSettings.dspTime:N4}, intro.time={IntroAudioSource.time:N4}/{IntroAudioSource.clip.length:N4}, scheduled Loop={loopStartDspTime}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OverrideDeathScreenGameOverText()
|
||||||
|
{
|
||||||
|
if (CurrentTrack == null)
|
||||||
|
{
|
||||||
|
// Playing as a client with a host who doesn't have the mod
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
StartCoroutine(DeathScreenGameOverTextManager.SetTextAndClear(CurrentTrack.GameOverText));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPatch(typeof(JesterAI))]
|
[HarmonyPatch(typeof(JesterAI))]
|
||||||
|
@ -2484,6 +2533,18 @@ namespace MuzikaGromche
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(nameof(JesterAI.killPlayerAnimation))]
|
||||||
|
[HarmonyPrefix]
|
||||||
|
static void JesterKillPlayerAnimationPrefix(JesterAI __instance, int playerId)
|
||||||
|
{
|
||||||
|
// Note on cast to int: base game already downcasts ulong to int anyway
|
||||||
|
if (playerId == (int)GameNetworkManager.Instance.localPlayerController.playerClientId)
|
||||||
|
{
|
||||||
|
var behaviour = __instance.GetComponent<MuzikaGromcheJesterNetworkBehaviour>();
|
||||||
|
behaviour.OverrideDeathScreenGameOverText();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPatch(typeof(EnemyAI))]
|
[HarmonyPatch(typeof(EnemyAI))]
|
||||||
|
@ -2499,8 +2560,9 @@ namespace MuzikaGromche
|
||||||
{
|
{
|
||||||
PoweredLightsBehaviour.Instance.ResetLightColor();
|
PoweredLightsBehaviour.Instance.ResetLightColor();
|
||||||
DiscoBallManager.Disable();
|
DiscoBallManager.Disable();
|
||||||
|
DeathScreenGameOverTextManager.Clear();
|
||||||
// Just in case if players have spawned multiple Jesters,
|
// Just in case if players have spawned multiple Jesters,
|
||||||
// Don't reset Plugin.CurrentTrack to null,
|
// Don't reset Config.CurrentTrack to null,
|
||||||
// so that the latest chosen track remains set.
|
// so that the latest chosen track remains set.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue