From a37a8a8e1b388b27473621507e1fdd3516aa716f Mon Sep 17 00:00:00 2001
From: XtraCube <72575280+XtraCube@users.noreply.github.com>
Date: Tue, 20 Aug 2024 00:05:00 -0400
Subject: [PATCH] options fixes + start re implement custom game modes
---
MiraAPI.Example/CustomRoleSettings.cs | 19 +++++
MiraAPI/GameModes/CustomGameModeManager.cs | 19 ++---
MiraAPI/GameOptions/IModdedOption.cs | 2 +-
MiraAPI/GameOptions/ModdedOptionsManager.cs | 14 +++-
.../GameOptions/OptionTypes/ModdedOption.cs | 3 +-
MiraAPI/Patches/GameModes/ConsolePatches.cs | 76 +++++++++++++++++++
MiraAPI/Patches/GameModes/GameLogicPatches.cs | 24 ++++++
.../Patches/GameModes/ImpostorTargetPatch.cs | 28 +++++++
.../Patches/GameModes/MapBehaviourPatch.cs | 22 ++++++
MiraAPI/Patches/HudManagerPatches.cs | 19 ++---
MiraAPI/Patches/IntroCutscenePatches.cs | 57 ++++++++++++++
.../Patches/Options/RoleSettingMenuPatches.cs | 2 +-
MiraAPI/Patches/Roles/NameTagPatch.cs | 9 ++-
MiraAPI/PluginLoading/MiraPluginManager.cs | 1 +
14 files changed, 268 insertions(+), 27 deletions(-)
create mode 100644 MiraAPI.Example/CustomRoleSettings.cs
create mode 100644 MiraAPI/Patches/GameModes/ConsolePatches.cs
create mode 100644 MiraAPI/Patches/GameModes/GameLogicPatches.cs
create mode 100644 MiraAPI/Patches/GameModes/ImpostorTargetPatch.cs
create mode 100644 MiraAPI/Patches/GameModes/MapBehaviourPatch.cs
create mode 100644 MiraAPI/Patches/IntroCutscenePatches.cs
diff --git a/MiraAPI.Example/CustomRoleSettings.cs b/MiraAPI.Example/CustomRoleSettings.cs
new file mode 100644
index 00000000..34cb47af
--- /dev/null
+++ b/MiraAPI.Example/CustomRoleSettings.cs
@@ -0,0 +1,19 @@
+using System;
+using MiraAPI.GameOptions;
+using MiraAPI.GameOptions.Attributes;
+using MiraAPI.GameOptions.OptionTypes;
+
+namespace MiraAPI.Example;
+
+public class CustomRoleSettings : IModdedOptionGroup
+{
+ public string GroupName => "Custom Role";
+
+ public Type AdvancedRole => typeof(CustomRole);
+
+ [ModdedNumberOption("amogus", min: 3, max: 9)] public float amogus { get; set; } = 1;
+
+ [ModdedEnumOption("dwayne the rock johnson", typeof(TestEnum))] public TestEnum dwayneTheRockJohnson { get; set; } = TestEnum.Hello;
+
+ public ModdedToggleOption testToggle { get; } = new ("test toggle", false);
+}
\ No newline at end of file
diff --git a/MiraAPI/GameModes/CustomGameModeManager.cs b/MiraAPI/GameModes/CustomGameModeManager.cs
index f453ccaa..bec9d846 100644
--- a/MiraAPI/GameModes/CustomGameModeManager.cs
+++ b/MiraAPI/GameModes/CustomGameModeManager.cs
@@ -1,4 +1,5 @@
-using Reactor.Utilities;
+#nullable enable
+using Reactor.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -17,13 +18,13 @@ public static class CustomGameModeManager
public static bool IsDefault()
{
- return ActiveMode.Id == 0;
+ return ActiveMode?.Id == 0;
}
///
/// Current gamemode
///
- public static CustomGameMode ActiveMode;
+ public static CustomGameMode? ActiveMode;
///
/// Set current gamemode
@@ -52,17 +53,17 @@ public static class CustomGameModeManager
return;
}
- var gameMode = (CustomGameMode)Activator.CreateInstance(gameModeType);
+ var modeObj = Activator.CreateInstance(gameModeType);
- if (GameModes.Any(x => x.Key == gameMode?.Id))
+ if (modeObj is not CustomGameMode gameMode)
{
- Logger.Error($"ID for gamemode {gameMode?.Name} already exists!");
+ Logger.Error($"Failed to create instance of {gameModeType.Name}");
return;
}
-
- if (gameMode == null)
+
+ if (GameModes.Any(x => x.Key == gameMode.Id))
{
- Logger.Error($"GAMEMODE WITH TYPE {gameModeType.Name} IS NULL");
+ Logger.Error($"ID for gamemode {gameMode.Name} already exists!");
return;
}
diff --git a/MiraAPI/GameOptions/IModdedOption.cs b/MiraAPI/GameOptions/IModdedOption.cs
index 9822eb12..232cf5a4 100644
--- a/MiraAPI/GameOptions/IModdedOption.cs
+++ b/MiraAPI/GameOptions/IModdedOption.cs
@@ -11,7 +11,7 @@ public interface IModdedOption
public BaseGameSetting Data { get; }
public IModdedOptionGroup Group { get; set; }
public IMiraPlugin ParentMod { get; set; }
- public Type AdvancedRole { get; }
+ public Type AdvancedRole { get; set; }
public OptionBehaviour OptionBehaviour { get; protected set; }
public string Title { get; }
public StringNames StringName { get; }
diff --git a/MiraAPI/GameOptions/ModdedOptionsManager.cs b/MiraAPI/GameOptions/ModdedOptionsManager.cs
index 02e99f97..0d8e15f2 100644
--- a/MiraAPI/GameOptions/ModdedOptionsManager.cs
+++ b/MiraAPI/GameOptions/ModdedOptionsManager.cs
@@ -23,7 +23,18 @@ public class ModdedOptionsManager
{
if (OptionAttributes.ContainsKey(property)) return null;
object newObj = Activator.CreateInstance(type);
- IModdedOption result = attribute.CreateOption(property.GetValue(newObj), property);
+
+ IModdedOption result;
+
+ try
+ {
+ result = attribute.CreateOption(property.GetValue(newObj), property);
+ }
+ catch (Exception e)
+ {
+ Logger.Error(e);
+ return null;
+ }
if (result != null)
{
@@ -43,6 +54,7 @@ public class ModdedOptionsManager
{
Logger.Error($"Grouping {attribute.Title} with {OriginalTypes[type].GroupName}");
result.Group = OriginalTypes[type];
+ result.AdvancedRole = OriginalTypes[type].AdvancedRole;
}
}
diff --git a/MiraAPI/GameOptions/OptionTypes/ModdedOption.cs b/MiraAPI/GameOptions/OptionTypes/ModdedOption.cs
index 366ab2d5..386cc7c3 100644
--- a/MiraAPI/GameOptions/OptionTypes/ModdedOption.cs
+++ b/MiraAPI/GameOptions/OptionTypes/ModdedOption.cs
@@ -19,7 +19,7 @@ public abstract class ModdedOption : IModdedOption
public string Title { get; }
public StringNames StringName { get; }
public Func Visible { get; set; }
- public Type AdvancedRole { get; }
+ public Type AdvancedRole { get; set; }
public OptionBehaviour OptionBehaviour { get; set; }
public IModdedOptionGroup Group { get; set; } = null;
public IMiraPlugin ParentMod { get; set; } = null;
@@ -40,7 +40,6 @@ public abstract class ModdedOption : IModdedOption
private ModdedOption()
{
- Logger.Error("created modded option");
Id = ModdedOptionsManager.NextId++;
ModdedOptionsManager.Options.Add(this);
ModdedOptionsManager.ModdedOptions.Add(Id, this);
diff --git a/MiraAPI/Patches/GameModes/ConsolePatches.cs b/MiraAPI/Patches/GameModes/ConsolePatches.cs
new file mode 100644
index 00000000..d37f9405
--- /dev/null
+++ b/MiraAPI/Patches/GameModes/ConsolePatches.cs
@@ -0,0 +1,76 @@
+using HarmonyLib;
+using InnerNet;
+using MiraAPI.GameModes;
+
+namespace MiraAPI.Patches.GameModes;
+
+[HarmonyPatch]
+public static class ConsolePatches
+{
+ [HarmonyPrefix]
+ [HarmonyPatch(typeof(Console), nameof(Console.CanUse))]
+ public static bool CanUsePatch(Console __instance, [HarmonyArgument(0)] NetworkedPlayerInfo pc, [HarmonyArgument(1)] out bool canUse, [HarmonyArgument(2)] out bool couldUse)
+ {
+ if (AmongUsClient.Instance.GameState == InnerNetClient.GameStates.Started && ShipStatus.Instance)
+ {
+ if (CustomGameModeManager.ActiveMode != null && CustomGameModeManager.ActiveMode.CanUseConsole(__instance))
+ {
+ var task = __instance.FindTask(pc.Object);
+
+ if (task && task.GetComponent())
+ {
+ canUse = couldUse = true;
+ return true;
+ }
+
+ canUse = false;
+ couldUse = false;
+ return true;
+ }
+
+ canUse = couldUse = false;
+ return false;
+ }
+
+ canUse = couldUse = true;
+ return true;
+ }
+
+ [HarmonyPrefix]
+ [HarmonyPatch(typeof(SystemConsole), nameof(SystemConsole.CanUse))]
+ public static bool SystemCanUsePatch(SystemConsole __instance, [HarmonyArgument(0)] NetworkedPlayerInfo pc, [HarmonyArgument(1)] out bool canUse, [HarmonyArgument(2)] out bool couldUse)
+ {
+ if (AmongUsClient.Instance.GameState == InnerNetClient.GameStates.Started && ShipStatus.Instance)
+ {
+ if (CustomGameModeManager.ActiveMode != null && CustomGameModeManager.ActiveMode.CanUseSystemConsole(__instance))
+ {
+ return canUse = couldUse = true;
+ }
+
+ canUse = couldUse = false;
+ return false;
+ }
+
+ canUse = couldUse = true;
+ return true;
+ }
+
+ [HarmonyPrefix]
+ [HarmonyPatch(typeof(MapConsole), nameof(MapConsole.CanUse))]
+ public static bool MapCanUsePatch(MapConsole __instance, [HarmonyArgument(0)] NetworkedPlayerInfo pc, [HarmonyArgument(1)] out bool canUse, [HarmonyArgument(2)] out bool couldUse)
+ {
+ if (AmongUsClient.Instance.GameState == InnerNetClient.GameStates.Started && ShipStatus.Instance)
+ {
+ if (CustomGameModeManager.ActiveMode != null && CustomGameModeManager.ActiveMode.CanUseMapConsole(__instance))
+ {
+ return canUse = couldUse = true;
+ }
+
+ canUse = couldUse = false;
+ return false;
+ }
+
+ canUse = couldUse = true;
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/MiraAPI/Patches/GameModes/GameLogicPatches.cs b/MiraAPI/Patches/GameModes/GameLogicPatches.cs
new file mode 100644
index 00000000..d60a70d3
--- /dev/null
+++ b/MiraAPI/Patches/GameModes/GameLogicPatches.cs
@@ -0,0 +1,24 @@
+using HarmonyLib;
+using MiraAPI.GameModes;
+
+namespace MiraAPI.Patches.GameModes;
+
+[HarmonyPatch]
+public static class GameLogicPatches
+{
+ [HarmonyPrefix, HarmonyPatch(typeof(LogicGameFlowNormal), nameof(LogicGameFlowNormal.CheckEndCriteria))]
+ public static bool EndCritPatch(LogicGameFlowNormal __instance)
+ {
+ var runOriginal = true;
+ CustomGameModeManager.ActiveMode?.CheckGameEnd(out runOriginal, __instance);
+ return runOriginal;
+ }
+
+ [HarmonyPrefix, HarmonyPatch(typeof(LogicRoleSelectionNormal), nameof(LogicRoleSelectionNormal.AssignRolesFromList))]
+ public static bool AssignRolesPatch(LogicRoleSelectionNormal __instance)
+ {
+ var runOriginal = true;
+ CustomGameModeManager.ActiveMode?.AssignRoles(out runOriginal, __instance);
+ return runOriginal;
+ }
+}
\ No newline at end of file
diff --git a/MiraAPI/Patches/GameModes/ImpostorTargetPatch.cs b/MiraAPI/Patches/GameModes/ImpostorTargetPatch.cs
new file mode 100644
index 00000000..899006dd
--- /dev/null
+++ b/MiraAPI/Patches/GameModes/ImpostorTargetPatch.cs
@@ -0,0 +1,28 @@
+using HarmonyLib;
+using MiraAPI.GameModes;
+
+namespace MiraAPI.Patches.GameModes;
+
+///
+/// Allow Impostors to kill each other if can kill is enabled in gamemode or friendly fire is toggled on
+///
+[HarmonyPatch(typeof(ImpostorRole), "IsValidTarget")]
+public static class ImpostorTargetPatch
+{
+ public static bool Prefix(ImpostorRole __instance, [HarmonyArgument(0)] NetworkedPlayerInfo target, ref bool __result)
+ {
+ var runOriginal = true;
+ var result = false;
+ CustomGameModeManager.ActiveMode?.CanKill(out runOriginal, out result, target.Object);
+ if (runOriginal || !result)
+ {
+ return true;
+ }
+
+ __result = target is { Disconnected: false, IsDead: false } &&
+ target.PlayerId != __instance.Player.PlayerId && !(target.Role == null) &&
+ !(target.Object == null) && !target.Object.inVent && !target.Object.inMovingPlat;
+ return false;
+
+ }
+}
\ No newline at end of file
diff --git a/MiraAPI/Patches/GameModes/MapBehaviourPatch.cs b/MiraAPI/Patches/GameModes/MapBehaviourPatch.cs
new file mode 100644
index 00000000..e7629ef0
--- /dev/null
+++ b/MiraAPI/Patches/GameModes/MapBehaviourPatch.cs
@@ -0,0 +1,22 @@
+using HarmonyLib;
+using MiraAPI.GameModes;
+
+namespace MiraAPI.Patches.GameModes;
+
+[HarmonyPatch(typeof(MapBehaviour))]
+public class MapBehaviourPatch
+{
+ [HarmonyPrefix]
+ [HarmonyPatch(nameof(MapBehaviour.ShowSabotageMap))]
+ public static bool ShowSabotagePatch(MapBehaviour __instance)
+ {
+ var shouldShow = CustomGameModeManager.ActiveMode?.ShouldShowSabotageMap(__instance);
+ if (shouldShow.HasValue && !shouldShow.Value)
+ {
+ __instance.ShowNormalMap();
+ return false;
+ }
+
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/MiraAPI/Patches/HudManagerPatches.cs b/MiraAPI/Patches/HudManagerPatches.cs
index b7c5a0e7..019ebd9f 100644
--- a/MiraAPI/Patches/HudManagerPatches.cs
+++ b/MiraAPI/Patches/HudManagerPatches.cs
@@ -1,5 +1,6 @@
using HarmonyLib;
using InnerNet;
+using MiraAPI.GameModes;
using MiraAPI.Hud;
using MiraAPI.Roles;
using Reactor.Utilities.Extensions;
@@ -56,15 +57,15 @@ public static class HudManagerPatches
}
}
- /* ///
- /// Trigger hudstart on current custom gamemode
- ///
- [HarmonyPostfix]
- [HarmonyPatch("OnGameStart")]
- public static void GameStartPatch(HudManager __instance)
- {
- CustomGameModeManager.ActiveMode.HudStart(__instance);
- }*/
+ ///
+ /// Trigger hudstart on current custom gamemode
+ ///
+ [HarmonyPostfix]
+ [HarmonyPatch(nameof(HudManager.OnGameStart))]
+ public static void GameStartPatch(HudManager __instance)
+ {
+ CustomGameModeManager.ActiveMode?.HudStart(__instance);
+ }
///
/// Create custom buttons parent
diff --git a/MiraAPI/Patches/IntroCutscenePatches.cs b/MiraAPI/Patches/IntroCutscenePatches.cs
new file mode 100644
index 00000000..1af8acfc
--- /dev/null
+++ b/MiraAPI/Patches/IntroCutscenePatches.cs
@@ -0,0 +1,57 @@
+using HarmonyLib;
+using MiraAPI.GameModes;
+using MiraAPI.Roles;
+using MiraAPI.Utilities;
+using UnityEngine;
+
+namespace MiraAPI.Patches;
+
+[HarmonyPatch(typeof(IntroCutscene))]
+public static class IntroCutscenePatches
+{
+ [HarmonyPostfix]
+ [HarmonyPatch(nameof(IntroCutscene.BeginImpostor))]
+ public static void BeginImpostorPatch(IntroCutscene __instance)
+ {
+ if (CustomGameModeManager.ActiveMode != null && CustomGameModeManager.ActiveMode.ShowCustomRoleScreen())
+ {
+ var mode = CustomGameModeManager.ActiveMode;
+ __instance.TeamTitle.text = $"{mode.Name}\n{mode.Description}";
+ }
+ }
+
+ [HarmonyPrefix]
+ [HarmonyPatch(nameof(IntroCutscene.BeginCrewmate))]
+ public static bool BeginCrewmatePatch(IntroCutscene __instance)
+ {
+ if (PlayerControl.LocalPlayer.Data.Role is ICustomRole customRole)
+ {
+ if (!customRole.IsNeutral)
+ {
+ return true;
+ }
+
+ var barTransform = __instance.BackgroundBar.transform;
+ var position = barTransform.position;
+ position.y -= 0.25f;
+ barTransform.position = position;
+
+ __instance.BackgroundBar.material.SetColor(ShaderID.Color, Color.gray);
+ __instance.TeamTitle.text = "OUTCAST";
+ __instance.impostorScale = 1f;
+ __instance.ImpostorText.text = "You are an Outcast. You do not have a team.";
+ __instance.TeamTitle.color = Color.gray;
+
+ __instance.ourCrewmate = __instance.CreatePlayer(0, Mathf.CeilToInt(7.5f), PlayerControl.LocalPlayer.Data, false);
+ return false;
+ }
+ return true;
+ }
+
+ [HarmonyPostfix]
+ [HarmonyPatch(nameof(IntroCutscene.OnDestroy))]
+ public static void GameBeginPatch()
+ {
+ CustomGameModeManager.ActiveMode?.Initialize();
+ }
+}
\ No newline at end of file
diff --git a/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs b/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs
index 0b3b6fb5..23508011 100644
--- a/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs
+++ b/MiraAPI/Patches/Options/RoleSettingMenuPatches.cs
@@ -132,7 +132,7 @@ public static class RoleSettingMenuPatches
__instance.advancedSettingChildren.Clear();
float num = -0.872f;
- foreach (var option in GameSettingMenuPatches.SelectedMod.Options.Where(option => option.AdvancedRole == role.GetType()))
+ foreach (var option in GameSettingMenuPatches.SelectedMod.Options.Where(option => option.AdvancedRole != null && option.AdvancedRole == role.GetType()))
{
OptionBehaviour newOpt = option.CreateOption(__instance.checkboxOrigin, __instance.numberOptionOrigin, __instance.stringOptionOrigin, __instance.AdvancedRolesSettings.transform);
newOpt.transform.localPosition = new Vector3(2.17f, num, -2f);
diff --git a/MiraAPI/Patches/Roles/NameTagPatch.cs b/MiraAPI/Patches/Roles/NameTagPatch.cs
index d74a88c7..35664162 100644
--- a/MiraAPI/Patches/Roles/NameTagPatch.cs
+++ b/MiraAPI/Patches/Roles/NameTagPatch.cs
@@ -1,4 +1,6 @@
using HarmonyLib;
+using MiraAPI.GameModes;
+using MiraAPI.GameOptions;
using UnityEngine;
namespace MiraAPI.Patches.Roles;
@@ -13,13 +15,12 @@ public static class NameTagPatch
[HarmonyPatch(nameof(PlayerNameColor.Get), typeof(RoleBehaviour))]
public static bool GetPatch([HarmonyArgument(0)] RoleBehaviour otherPlayerRole, ref Color __result)
{
- if (PlayerControl.LocalPlayer.Data.IsDead)
+ if (PlayerControl.LocalPlayer.Data.Role.IsImpostor && otherPlayerRole.IsImpostor)
{
- __result = otherPlayerRole.NameColor;
- return false;
+ return true;
}
- if (PlayerControl.LocalPlayer.Data.Role.IsImpostor && otherPlayerRole.IsImpostor)
+ if (GameManager.Instance.IsHideAndSeek())
{
return true;
}
diff --git a/MiraAPI/PluginLoading/MiraPluginManager.cs b/MiraAPI/PluginLoading/MiraPluginManager.cs
index 51788732..1c37baba 100644
--- a/MiraAPI/PluginLoading/MiraPluginManager.cs
+++ b/MiraAPI/PluginLoading/MiraPluginManager.cs
@@ -85,6 +85,7 @@ public class MiraPluginManager
{
IModdedOption option = (IModdedOption)property.GetValue(group);
option.Group = group;
+ option.AdvancedRole = group.AdvancedRole;
}
}
}