Files
ADOFAIRenderer/Patch/Game/scrControllerPatch.cs
T
2026-10-15 16:17:13 +09:00

125 lines
5.1 KiB
C#

using ADOFAIRenderer.Core;
using HarmonyLib;
namespace ADOFAIRenderer.Patch.Game;
/// <summary>
/// Keeps the game controller (<c>scrController</c>) in uninterrupted play during a render: no pause, no failure,
/// no scene change after the clear, and no clear texts.
/// <para>
/// All patches are active while <see cref="RenderManager.IsActive"/> (stage &gt;= OnScene). RenderManager also sets
/// <c>noFail</c>, <c>noFailInfiniteMargin</c> and <c>disableCongratsMessage</c> on the controller when the scene is ready.
/// </para>
/// </summary>
[HarmonyPatch(typeof(scrController))]
// ReSharper disable once InconsistentNaming
public static class scrControllerPatch
{
/// <summary>
/// Prefix of <c>scrController.TogglePauseGame()</c> (pause menu toggle; sets <c>Time.timeScale</c> to 0 or 1 and shows the
/// pause menu; also called from the pause button, the pause key and <c>OnApplicationPauseCallback</c>). Skipped while
/// rendering, so the level cannot be paused. The skipped call returns
/// false (Harmony default for the unset bool result).
/// </summary>
/// <returns>True to run the original method (not rendering); false to skip it (rendering).</returns>
[HarmonyPrefix]
[HarmonyPatch("TogglePauseGame")]
public static bool PreventPause()
{
return !RenderManager.IsActive;
}
/// <summary>
/// Prefix of <c>scrController.PortalTravelAction(Portal)</c>, which leaves the level through a portal (next level,
/// level select, main menu, ...); the game calls it on entering the Won state for non-world levels and on input after a win.
/// Skipped while rendering, so the scene stays loaded for the delay after the level end.
/// </summary>
/// <returns>True to run the original method (not rendering); false to skip it (rendering).</returns>
[HarmonyPrefix]
[HarmonyPatch("PortalTravelAction")]
public static bool PreventPortalTravel()
{
return !RenderManager.IsActive;
}
/// <summary>
/// Prefix of <c>scrController.FailAction(...)</c>, which enters the Fail state: stops the song and all sounds, pauses the
/// VFX video and shows the failure texts. Skipped while rendering.
/// </summary>
/// <returns>True to run the original method (not rendering); false to skip it (rendering).</returns>
[HarmonyPrefix]
[HarmonyPatch("FailAction")]
public static bool PreventFailAction()
{
return !RenderManager.IsActive;
}
/// <summary>
/// Prefix of <c>scrController.Fail2Action()</c>, which moves from Fail to Fail2 (accuracy calculation, saving of the
/// best result for boss/custom boss levels, death counter). Skipped while rendering.
/// </summary>
/// <returns>True to run the original method (not rendering); false to skip it (rendering).</returns>
[HarmonyPrefix]
[HarmonyPatch("Fail2Action")]
public static bool PreventFail2Action()
{
return !RenderManager.IsActive;
}
/// <summary>
/// Prefix of <c>scrController.OnPlayerDied(...)</c>, which kills the remaining players and calls FailAction when no other
/// player is alive. Skipped while rendering.
/// </summary>
/// <returns>True to run the original method (not rendering); false to skip it (rendering).</returns>
[HarmonyPrefix]
[HarmonyPatch("OnPlayerDied")]
public static bool PreventPlayerDied()
{
return !RenderManager.IsActive;
}
/// <summary>
/// Postfix of <c>scrController.OnLandOnPortal(...)</c>, the win handler on the last tile: it sets and activates
/// <c>txtCongrats</c> / <c>txtAprilCongrats</c> / <c>txtAllStrictClear</c>, may show the detailed results and end-screen
/// lanterns, saves the result and changes the state to Won.
/// <para>
/// While rendering, clears and deactivates the three clear texts and disables the detailed results panel after the
/// original has run, so they do not appear in the rendered video. The Won state itself is kept: the default render end
/// condition (<c>RenderContext.EndCondition</c>) waits for it.
/// </para>
/// </summary>
/// <param name="__instance">The game controller.</param>
[HarmonyPostfix]
[HarmonyPatch("OnLandOnPortal")]
public static void PreventWinTextsPostfix(scrController __instance)
{
if (!RenderManager.IsActive || __instance == null) return;
if (__instance.txtCongrats)
{
__instance.txtCongrats.text = string.Empty;
__instance.txtCongrats.gameObject.SetActive(false);
}
if (__instance.txtAprilCongrats)
{
__instance.txtAprilCongrats.text = string.Empty;
__instance.txtAprilCongrats.gameObject.SetActive(false);
}
if (__instance.txtAllStrictClear)
{
__instance.txtAllStrictClear.text = string.Empty;
__instance.txtAllStrictClear.gameObject.SetActive(false);
}
if (__instance.detailedResults)
{
__instance.detailedResults.enabled = false;
if (__instance.detailedResults.gameObject != null)
{
__instance.detailedResults.gameObject.SetActive(false);
}
}
}
}