mirror of
https://github.com/Gurge44/EndlessHostRoles.git
synced 2026-10-20 01:46:25 +00:00
323 lines
13 KiB
C#
323 lines
13 KiB
C#
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using BepInEx;
|
||
using EHR.Modules;
|
||
using EHR.Patches;
|
||
using EHR.Roles.AddOns.Crewmate;
|
||
using EHR.Roles.AddOns.Impostor;
|
||
using EHR.Roles.Crewmate;
|
||
using EHR.Roles.Neutral;
|
||
using HarmonyLib;
|
||
using Hazel;
|
||
using UnityEngine;
|
||
|
||
namespace EHR;
|
||
|
||
[HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.FixedUpdate))]
|
||
class ShipFixedUpdatePatch
|
||
{
|
||
public static void Postfix( /*ShipStatus __instance*/)
|
||
{
|
||
if (!AmongUsClient.Instance.AmHost) return;
|
||
if (Main.IsFixedCooldown && Main.RefixCooldownDelay >= 0)
|
||
{
|
||
Main.RefixCooldownDelay -= Time.fixedDeltaTime;
|
||
}
|
||
else if (!float.IsNaN(Main.RefixCooldownDelay))
|
||
{
|
||
Utils.MarkEveryoneDirtySettingsV4();
|
||
Main.RefixCooldownDelay = float.NaN;
|
||
Logger.Info("Refix Cooldown", "CoolDown");
|
||
}
|
||
}
|
||
}
|
||
|
||
[HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.UpdateSystem), typeof(SystemTypes), typeof(PlayerControl), typeof(MessageReader))]
|
||
public static class MessageReaderUpdateSystemPatch
|
||
{
|
||
public static bool Prefix(ShipStatus __instance, [HarmonyArgument(0)] SystemTypes systemType, [HarmonyArgument(1)] PlayerControl player, [HarmonyArgument(2)] MessageReader reader)
|
||
{
|
||
try
|
||
{
|
||
byte amount = MessageReader.Get(reader).ReadByte();
|
||
if (EAC.RpcUpdateSystemCheck(player, systemType, amount)) return false;
|
||
RepairSystemPatch.Prefix(__instance, systemType, player, amount);
|
||
}
|
||
catch
|
||
{
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
public static void Postfix( /*ShipStatus __instance,*/ [HarmonyArgument(0)] SystemTypes systemType, [HarmonyArgument(1)] PlayerControl player, [HarmonyArgument(2)] MessageReader reader)
|
||
{
|
||
try
|
||
{
|
||
RepairSystemPatch.Postfix( /*__instance,*/ systemType, player, MessageReader.Get(reader).ReadByte());
|
||
}
|
||
catch
|
||
{
|
||
}
|
||
}
|
||
}
|
||
|
||
[HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.UpdateSystem), typeof(SystemTypes), typeof(PlayerControl), typeof(byte))]
|
||
class RepairSystemPatch
|
||
{
|
||
public static bool Prefix(ShipStatus __instance,
|
||
[HarmonyArgument(0)] SystemTypes systemType,
|
||
[HarmonyArgument(1)] PlayerControl player,
|
||
[HarmonyArgument(2)] byte amount)
|
||
{
|
||
Logger.Msg("SystemType: " + systemType + ", PlayerName: " + player.GetNameWithRole().RemoveHtmlTags() + ", amount: " + amount, "RepairSystem");
|
||
if (RepairSender.enabled && AmongUsClient.Instance.NetworkMode != NetworkModes.OnlineGame)
|
||
Logger.SendInGame("SystemType: " + systemType + ", PlayerName: " + player.GetNameWithRole().RemoveHtmlTags() + ", amount: " + amount);
|
||
|
||
if (!AmongUsClient.Instance.AmHost) return true; // Execute the following only on the host
|
||
|
||
if ((Options.CurrentGameMode != CustomGameMode.Standard) && systemType == SystemTypes.Sabotage) return false;
|
||
|
||
if (Options.DisableSabotage.GetBool() && systemType == SystemTypes.Sabotage) return false;
|
||
|
||
// Note: "SystemTypes.Laboratory" сauses bugs in the Host, it is better not to use
|
||
if (player.Is(CustomRoles.Fool) &&
|
||
(systemType is
|
||
SystemTypes.Comms or
|
||
SystemTypes.Electrical))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
switch (player.GetCustomRole())
|
||
{
|
||
case CustomRoles.SabotageMaster:
|
||
SabotageMaster.RepairSystem(player.PlayerId, __instance, systemType, amount);
|
||
Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: player);
|
||
break;
|
||
case CustomRoles.Alchemist when Main.PlayerStates[player.PlayerId].Role is Alchemist { IsEnable: true, FixNextSabo: true }:
|
||
Alchemist.RepairSystem(player, systemType, amount);
|
||
Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: player);
|
||
break;
|
||
}
|
||
|
||
switch (systemType)
|
||
{
|
||
case SystemTypes.Doors when player.Is(CustomRoles.Unlucky) && player.IsAlive():
|
||
var Ue = IRandom.Instance;
|
||
if (Ue.Next(0, 100) < Options.UnluckySabotageSuicideChance.GetInt())
|
||
{
|
||
player.Suicide();
|
||
return false;
|
||
}
|
||
|
||
break;
|
||
case SystemTypes.Electrical when amount <= 4 && Main.NormalOptions.MapId == 4:
|
||
if (Options.DisableAirshipViewingDeckLightsPanel.GetBool() && Vector2.Distance(player.transform.position, new(-12.93f, -11.28f)) <= 2f) return false;
|
||
if (Options.DisableAirshipGapRoomLightsPanel.GetBool() && Vector2.Distance(player.transform.position, new(13.92f, 6.43f)) <= 2f) return false;
|
||
if (Options.DisableAirshipCargoLightsPanel.GetBool() && Vector2.Distance(player.transform.position, new(30.56f, 2.12f)) <= 2f) return false;
|
||
break;
|
||
case SystemTypes.Sabotage when AmongUsClient.Instance.NetworkMode != NetworkModes.FreePlay:
|
||
if (Options.CurrentGameMode != CustomGameMode.Standard) return false;
|
||
if (SecurityGuard.BlockSabo.Count > 0) return false;
|
||
if (player.IsRoleBlocked())
|
||
{
|
||
player.Notify(BlockedAction.Sabotage.GetBlockNotify());
|
||
return false;
|
||
}
|
||
|
||
if (player.Is(CustomRoleTypes.Impostor) && !player.IsAlive() && Options.DeadImpCantSabotage.GetBool()) return false;
|
||
return player.GetCustomRole() switch
|
||
{
|
||
CustomRoles.Jackal when Jackal.CanSabotage.GetBool() => true,
|
||
CustomRoles.Sidekick when Jackal.CanSabotageSK.GetBool() => true,
|
||
CustomRoles.Traitor when Traitor.CanSabotage.GetBool() => true,
|
||
CustomRoles.Parasite when player.IsAlive() => true,
|
||
CustomRoles.Refugee when player.IsAlive() => true,
|
||
_ => Main.PlayerStates[player.PlayerId].Role.CanUseSabotage(player)
|
||
};
|
||
case SystemTypes.Security when amount == 1:
|
||
var camerasDisabled = (MapNames)Main.NormalOptions.MapId switch
|
||
{
|
||
MapNames.Skeld => Options.DisableSkeldCamera.GetBool(),
|
||
MapNames.Polus => Options.DisablePolusCamera.GetBool(),
|
||
MapNames.Airship => Options.DisableAirshipCamera.GetBool(),
|
||
_ => false,
|
||
};
|
||
if (camerasDisabled)
|
||
{
|
||
player.Notify(Translator.GetString("CamerasDisabledNotify"), 15f);
|
||
}
|
||
|
||
return !camerasDisabled;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
public static void Postfix( /*ShipStatus __instance,*/
|
||
[HarmonyArgument(0)] SystemTypes systemType,
|
||
[HarmonyArgument(1)] PlayerControl player,
|
||
[HarmonyArgument(2)] byte amount)
|
||
{
|
||
Camouflage.CheckCamouflage();
|
||
|
||
switch (systemType)
|
||
{
|
||
case SystemTypes.Electrical when amount <= 4:
|
||
var SwitchSystem = ShipStatus.Instance?.Systems?[SystemTypes.Electrical]?.Cast<SwitchSystem>();
|
||
if (SwitchSystem is { IsActive: true })
|
||
{
|
||
switch (Main.PlayerStates[player.PlayerId].Role)
|
||
{
|
||
case SabotageMaster:
|
||
Logger.Info($"{player.GetNameWithRole().RemoveHtmlTags()} instant-fix-lights", "SwitchSystem");
|
||
SabotageMaster.SwitchSystemRepair(player.PlayerId, SwitchSystem, amount);
|
||
Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: player);
|
||
break;
|
||
case Alchemist { FixNextSabo: true } am:
|
||
Logger.Info($"{player.GetNameWithRole().RemoveHtmlTags()} instant-fix-lights", "SwitchSystem");
|
||
SwitchSystem.ActualSwitches = 0;
|
||
SwitchSystem.ExpectedSwitches = 0;
|
||
am.FixNextSabo = false;
|
||
Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: player);
|
||
break;
|
||
case Adventurer av:
|
||
Logger.Info($"{player.GetNameWithRole().RemoveHtmlTags()} instant-fix-lights", "SwitchSystem");
|
||
SwitchSystem.ActualSwitches = 0;
|
||
SwitchSystem.ExpectedSwitches = 0;
|
||
av.OnLightsFix();
|
||
Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: player);
|
||
break;
|
||
}
|
||
|
||
if (player.Is(CustomRoles.Damocles) && Damocles.countRepairSabotage) Damocles.OnRepairSabotage(player.PlayerId);
|
||
if (player.Is(CustomRoles.Stressed) && Stressed.countRepairSabotage) Stressed.OnRepairSabotage(player);
|
||
}
|
||
|
||
break;
|
||
case SystemTypes.Reactor:
|
||
case SystemTypes.LifeSupp:
|
||
case SystemTypes.Comms:
|
||
case SystemTypes.Laboratory:
|
||
case SystemTypes.HeliSabotage:
|
||
case SystemTypes.Electrical:
|
||
if (player.Is(CustomRoles.Damocles) && Damocles.countRepairSabotage) Damocles.OnRepairSabotage(player.PlayerId);
|
||
if (player.Is(CustomRoles.Stressed) && Stressed.countRepairSabotage) Stressed.OnRepairSabotage(player);
|
||
break;
|
||
}
|
||
}
|
||
|
||
public static void CheckAndOpenDoorsRange(ShipStatus __instance, int amount, int min, int max)
|
||
{
|
||
var Ids = new List<int>();
|
||
for (var i = min; i <= max; i++)
|
||
{
|
||
Ids.Add(i);
|
||
}
|
||
|
||
CheckAndOpenDoors(__instance, amount, [.. Ids]);
|
||
}
|
||
|
||
private static void CheckAndOpenDoors(ShipStatus __instance, int amount, params int[] DoorIds)
|
||
{
|
||
if (!DoorIds.Contains(amount)) return;
|
||
foreach (int id in DoorIds)
|
||
{
|
||
__instance.RpcUpdateSystem(SystemTypes.Doors, (byte)id);
|
||
}
|
||
}
|
||
}
|
||
|
||
[HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.CloseDoorsOfType))]
|
||
class CloseDoorsPatch
|
||
{
|
||
public static bool Prefix( /*ShipStatus __instance, */ [HarmonyArgument(0)] SystemTypes room)
|
||
{
|
||
bool allow = !Options.DisableSabotage.GetBool() && Options.CurrentGameMode is not CustomGameMode.SoloKombat and not CustomGameMode.FFA and not CustomGameMode.MoveAndStop;
|
||
|
||
if (SecurityGuard.BlockSabo.Count > 0) allow = false;
|
||
if (Options.DisableCloseDoor.GetBool()) allow = false;
|
||
|
||
Logger.Info($"({room}) => {(allow ? "Allowed" : "Blocked")}", "DoorClose");
|
||
return allow;
|
||
}
|
||
}
|
||
|
||
[HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.Start))]
|
||
class StartPatch
|
||
{
|
||
public static void Postfix()
|
||
{
|
||
Logger.CurrentMethod();
|
||
Logger.Info("-----------Game start-----------", "Phase");
|
||
|
||
Utils.CountAlivePlayers(true);
|
||
|
||
if (Options.AllowConsole.GetBool())
|
||
{
|
||
if (!ConsoleManager.ConsoleActive && ConsoleManager.ConsoleEnabled)
|
||
ConsoleManager.CreateConsole();
|
||
}
|
||
else
|
||
{
|
||
if (ConsoleManager.ConsoleActive && !DebugModeManager.AmDebugger)
|
||
{
|
||
ConsoleManager.DetachConsole();
|
||
Logger.SendInGame("Sorry, console use is prohibited in this room, so your console has been turned off");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
[HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.StartMeeting))]
|
||
class StartMeetingPatch
|
||
{
|
||
public static void Prefix( /*ShipStatus __instance, PlayerControl reporter,*/ GameData.PlayerInfo target)
|
||
{
|
||
MeetingStates.ReportTarget = target;
|
||
MeetingStates.DeadBodies = Object.FindObjectsOfType<DeadBody>();
|
||
}
|
||
}
|
||
|
||
[HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.Begin))]
|
||
class BeginPatch
|
||
{
|
||
public static void Postfix()
|
||
{
|
||
Logger.CurrentMethod();
|
||
|
||
//Should I initialize the host role here? - no
|
||
}
|
||
}
|
||
|
||
[HarmonyPatch(typeof(GameManager), nameof(GameManager.CheckTaskCompletion))]
|
||
class CheckTaskCompletionPatch
|
||
{
|
||
public static bool Prefix(ref bool __result)
|
||
{
|
||
if (Options.DisableTaskWin.GetBool() || Options.NoGameEnd.GetBool() || TaskState.InitialTotalTasks == 0 || (Options.DisableTaskWinIfAllCrewsAreDead.GetBool() && !Main.AllAlivePlayerControls.Any(x => x.Is(CustomRoleTypes.Crewmate))) || Options.CurrentGameMode != CustomGameMode.Standard)
|
||
{
|
||
__result = false;
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
}
|
||
|
||
[HarmonyPatch(typeof(HauntMenuMinigame), nameof(HauntMenuMinigame.SetFilterText))]
|
||
public static class HauntMenuMinigameSetFilterTextPatch
|
||
{
|
||
public static bool Prefix(HauntMenuMinigame __instance)
|
||
{
|
||
if (__instance.HauntTarget != null && Options.GhostCanSeeOtherRoles.GetBool())
|
||
{
|
||
var id = __instance.HauntTarget.PlayerId;
|
||
__instance.FilterText.text = Utils.GetDisplayRoleName(id) + Utils.GetProgressText(id);
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
} |