a lot of fixes & improvements

This commit is contained in:
Gurge44 committed 2025-06-23 22:03:53 +02:00
1 parent a70bb0ac8a
commit 9a37f722f8
48 files changed
+307 -77

No files matched your search

+1 -1
View File
@@ -198,7 +198,7 @@ public enum CustomRoles
Lighter,
Lookout,
Luckey,
Lyncher,
Decryptor,
Markseeker,
Marshall,
Mathematician,
+8
View File
@@ -447,6 +447,14 @@ public static class RoomRush
byte tieWith = Points.First(x => x.Key != seer.PlayerId && x.Value == highestPoints).Key;
sb.Append("\n" + string.Format(Translator.GetString("RR_Tie"), tieWith.ColoredPlayerName()));
}
else
{
sb.Append("<size=80%>");
byte first = Points.GetKeyByValue(highestPoints);
if (first != seer.PlayerId) sb.Append("\n" + string.Format(Translator.GetString("RR_FirstPoints"), first.ColoredPlayerName(), highestPoints));
else sb.Append("\n" + Translator.GetString("RR_YouAreFirst"));
sb.Append("</size>");
}
}
if (VentTimes.GetInt() == 0 || dead || seer.IsModdedClient()) return sb.ToString().Trim();
+2 -2
View File
@@ -35,8 +35,8 @@ public class Main : BasePlugin
private const string DebugKeyHash = "c0fd562955ba56af3ae20d7ec9e64c664f0facecef4b3e366e109306adeae29d";
private const string DebugKeySalt = "59687b";
private const string PluginGuid = "com.gurge44.endlesshostroles";
public const string PluginVersion = "5.7.0";
public const string PluginDisplayVersion = "5.7.0";
public const string PluginVersion = "5.7.1";
public const string PluginDisplayVersion = "5.7.1";
public const bool TestBuild = false;
public const string NeutralColor = "#ffab1b";
+2
View File
@@ -986,6 +986,8 @@ internal static class CustomRolesHelper
CustomRoles.Sapper or
CustomRoles.Sniper or
CustomRoles.Twister or
CustomRoles.Swooper or
CustomRoles.Wraith or
CustomRoles.RouleteGrandeur or
CustomRoles.Enderman or
CustomRoles.Hookshot or
+15
View File
@@ -20,6 +20,7 @@ public abstract class CustomSabotage
protected virtual void Fix()
{
Instances.Remove(this);
SabotageSystemTypeRepairDamagePatch.Instance.IsDirty = true;
}
protected virtual string GetSuffix(PlayerControl seer, PlayerControl target, bool hud, bool meeting)
@@ -70,6 +71,13 @@ public abstract class CustomSabotage
try { sabotage.Update(); }
catch (Exception e) { Utils.ThrowException(e); }
}
if (Instances.Count > 0)
{
SabotageSystemTypeRepairDamagePatch.Instance.Timer = SabotageSystemTypeRepairDamagePatch.IsCooldownModificationEnabled
? SabotageSystemTypeRepairDamagePatch.ModifiedCooldownSec
: 30f;
}
}
public static void Reset()
@@ -122,6 +130,13 @@ public class GrabOxygenMaskSabotage : CustomSabotage
playersInRoom.Except(HasMask).Do(x => LocateArrow.Remove(x, RoomPosition));
HasMask.UnionWith(playersInRoom);
if (HasMask.IsSupersetOf(aapc.Select(x => x.PlayerId)))
{
Main.AllPlayerControls.Do(x => LocateArrow.Remove(x.PlayerId, RoomPosition));
Fix();
return;
}
long now = Utils.TimeStamp;
if (DeteriorateTS + TimeLimit <= now)
+42 -2
View File
@@ -533,7 +533,7 @@ internal static class ExtendedPlayerControl
// https://github.com/Ultradragon005/TownofHost-Enhanced/blob/ea5f1e8ea87e6c19466231c305d6d36d511d5b2d/Modules/Utils.cs
public static void SyncGeneralOptions(this CustomRpcSender sender, PlayerControl player)
{
if (!AmongUsClient.Instance.AmHost || !GameStates.IsInGame) return;
if (!AmongUsClient.Instance.AmHost || !GameStates.IsInGame || !DoRPC) return;
sender.AutoStartRpc(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SyncGeneralOptions);
sender.Write(player.PlayerId);
@@ -545,7 +545,7 @@ internal static class ExtendedPlayerControl
sender.EndRpc();
}
// Next 2: https://github.com/0xDrMoe/TownofHost-Enhanced/blob/12487ce1aa7e4f5087f2300be452b5af7c04d1ff/Modules/ExtendedPlayerControl.cs#L239
// Next 3: https://github.com/0xDrMoe/TownofHost-Enhanced/blob/12487ce1aa7e4f5087f2300be452b5af7c04d1ff/Modules/ExtendedPlayerControl.cs#L239
public static void RpcExitVentDesync(this PlayerPhysics physics, int ventId, PlayerControl seer)
{
@@ -565,6 +565,24 @@ internal static class ExtendedPlayerControl
AmongUsClient.Instance.FinishRpcImmediately(writer);
}
public static void RpcEnterVentDesync(this PlayerPhysics physics, int ventId, PlayerControl seer)
{
if (physics == null) return;
int clientId = seer.GetClientId();
if (AmongUsClient.Instance.ClientId == clientId)
{
physics.StopAllCoroutines();
physics.StartCoroutine(physics.CoEnterVent(ventId));
return;
}
MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(physics.NetId, (byte)RpcCalls.EnterVent, SendOption.Reliable, clientId);
writer.WritePacked(ventId);
AmongUsClient.Instance.FinishRpcImmediately(writer);
}
public static void RpcStartAppearDesync(this PlayerControl player, bool shouldAnimate, PlayerControl seer)
{
int clientId = seer.OwnerId;
@@ -585,6 +603,28 @@ internal static class ExtendedPlayerControl
return player.Is(CustomRoles.Bloodlust) || player.GetCustomRole().IsDesyncRole();
}
public static bool IsInsideMap(this PlayerControl player)
{
if (player == null) return false;
var results = new Collider2D[10];
int overlapPointNonAlloc = Physics2D.OverlapPointNonAlloc(player.transform.position, results, Constants.ShipOnlyMask);
PlainShipRoom room = player.GetPlainShipRoom();
Vector2 pos = player.Pos();
return Main.CurrentMap switch
{
MapNames.Fungle when overlapPointNonAlloc >= 2 => true,
MapNames.MiraHQ when overlapPointNonAlloc >= 1 => true,
MapNames.MiraHQ when room != null && room.RoomId is SystemTypes.MedBay or SystemTypes.Comms => true,
MapNames.Airship when overlapPointNonAlloc >= 1 => true,
MapNames.Skeld or MapNames.Dleks when room != null => true,
MapNames.Polus when overlapPointNonAlloc >= 1 => true,
MapNames.Polus when pos.y is >= -26.11f and <= -6.41f && pos.x is >= 3.56f and <= 32.68f => true,
_ => false
};
}
public static void KillFlash(this PlayerControl player)
{
if (GameStates.IsLobby) return;
+28 -12
View File
@@ -205,18 +205,6 @@ public static class Options
"pet_RANDOM_FOR_EVERYONE"
];
public static float DefaultKillCooldown = Main.NormalOptions == null ? 25f : Main.NormalOptions.KillCooldown;
public static float AdjustedDefaultKillCooldown => !GameStates.InGame
? DefaultKillCooldown
: DefaultKillCooldown + Main.CurrentMap switch
{
MapNames.Polus => ExtraKillCooldownOnPolus?.GetFloat() ?? 0f,
MapNames.Airship => ExtraKillCooldownOnAirship?.GetFloat() ?? 0f,
MapNames.Fungle => ExtraKillCooldownOnFungle?.GetFloat() ?? 0f,
_ => 0f
};
public static OptionItem ModLanguage;
public static readonly Dictionary<GameStateInfo, OptionItem> GameStateSettings = [];
@@ -607,6 +595,8 @@ public static class Options
public static OptionItem DisableAirshipCargoLightsPanel;
public static OptionItem WhoWinsBySabotageIfNoImpAlive;
public static OptionItem IfSelectedTeamIsDead;
public static OptionItem EnableCustomSabotages;
public static OptionItem EnableGrabOxygenMaskCustomSabotage;
// Guesser Mode
public static OptionItem GuesserMode;
@@ -695,6 +685,7 @@ public static class Options
public static OptionItem FixFirstKillCooldown;
public static OptionItem StartingKillCooldown;
public static OptionItem FallBackKillCooldownValue;
public static OptionItem ShieldPersonDiedFirst;
public static OptionItem GhostCanSeeOtherRoles;
public static OptionItem GhostCanSeeOtherVotes;
@@ -877,6 +868,18 @@ public static class Options
_ => CustomGameMode.Standard
};
public static float DefaultKillCooldown = Main.NormalOptions == null ? FallBackKillCooldownValue?.GetFloat() ?? 25f : Main.NormalOptions.KillCooldown;
public static float AdjustedDefaultKillCooldown => !GameStates.InGame
? DefaultKillCooldown
: DefaultKillCooldown + Main.CurrentMap switch
{
MapNames.Polus => ExtraKillCooldownOnPolus?.GetFloat() ?? 0f,
MapNames.Airship => ExtraKillCooldownOnAirship?.GetFloat() ?? 0f,
MapNames.Fungle => ExtraKillCooldownOnFungle?.GetFloat() ?? 0f,
_ => 0f
};
[HarmonyPatch(typeof(TranslationController), nameof(TranslationController.Initialize))]
[HarmonyPostfix]
public static void OptionsLoadStart()
@@ -2063,6 +2066,15 @@ public static class Options
.SetColor(new Color32(243, 96, 96, byte.MaxValue))
.SetGameMode(CustomGameMode.Standard);
EnableCustomSabotages = new BooleanOptionItem(22530, "EnableCustomSabotages", false, TabGroup.GameSettings)
.SetColor(new Color32(243, 96, 96, byte.MaxValue))
.SetGameMode(CustomGameMode.Standard);
EnableGrabOxygenMaskCustomSabotage = new BooleanOptionItem(22531, "EnableGrabOxygenMaskCustomSabotage", false, TabGroup.GameSettings)
.SetParent(EnableCustomSabotages)
.SetColor(new Color32(243, 96, 96, byte.MaxValue))
.SetGameMode(CustomGameMode.Standard);
LoadingPercentage = 73;
@@ -2781,6 +2793,10 @@ public static class Options
.SetColor(new Color32(193, 255, 209, byte.MaxValue))
.SetValueFormat(OptionFormat.Seconds);
FallBackKillCooldownValue = new FloatOptionItem(23951, "FallBackKillCooldownValue", new(0.5f, 60f, 0.5f), 25f, TabGroup.GameSettings)
.SetColor(new Color32(193, 255, 209, byte.MaxValue))
.SetValueFormat(OptionFormat.Seconds);
ShieldPersonDiedFirst = new BooleanOptionItem(24000, "ShieldPersonDiedFirst", false, TabGroup.GameSettings)
.SetColor(new Color32(193, 255, 209, byte.MaxValue));
+4 -1
View File
@@ -11,13 +11,15 @@ public static class PrivateTagManager
public static void AddTag(string friendcode, string tag)
{
LoadTagsFromFile();
Tags[friendcode] = tag;
SaveTagsToFile();
}
public static void DeleteTag(string friendcode)
{
Tags.Remove(friendcode);
LoadTagsFromFile();
if (!Tags.Remove(friendcode)) return;
SaveTagsToFile();
}
@@ -36,6 +38,7 @@ public static class PrivateTagManager
Tags = File.ReadAllLines(TagFile)
.Select(x => x.Split('='))
.Where(x => x.Length == 2)
.ToDictionary(x => x[0], x => x[1]);
}
catch (Exception e) { Utils.ThrowException(e); }
+5 -2
View File
@@ -2020,6 +2020,8 @@ public static class Utils
}
}
public static HashSet<byte> DirtyName = [];
public static bool ApplySuffix(PlayerControl player, out string name)
{
name = string.Empty;
@@ -2031,6 +2033,8 @@ public static class Utils
bool hasTag = devUser.HasTag();
bool hasPrivateTag = PrivateTagManager.Tags.TryGetValue(player.FriendCode, out string privateTag);
if (!player.AmOwner && !hasTag && !mod && !vip && !hasPrivateTag && !DirtyName.Contains(player.PlayerId)) return false;
if (!Main.AllPlayerNames.TryGetValue(player.PlayerId, out name)) return false;
if (Main.NickName != string.Empty && player.AmOwner) name = Main.NickName;
@@ -2100,7 +2104,7 @@ public static class Utils
}
}
return name != player.name && player.CurrentOutfitType == PlayerOutfitType.Default;
return DirtyName.Remove(player.PlayerId) || (name != player.name && player.CurrentOutfitType == PlayerOutfitType.Default);
}
public static Dictionary<string, int> GetAllPlayerLocationsCount()
@@ -3226,7 +3230,6 @@ public static class Utils
LateTask.New(() =>
{
if (pc.CurrentOutfit.PetId != "") return;
string petId = PetsHelper.GetPetId();
PetsHelper.SetPet(pc, petId);
}, 3f, "No Pet Reassign");
+4 -20
View File
@@ -530,12 +530,6 @@ internal static class ChatCommands
private static void AddTagCommand(PlayerControl player, string text, string[] args)
{
if (!AmongUsClient.Instance.AmHost)
{
RequestCommandProcessingFromHost(nameof(AddTagCommand), text);
return;
}
if (args.Length < 4 || !byte.TryParse(args[1], out byte id)) return;
PlayerControl pc = id.GetPlayer();
@@ -543,6 +537,7 @@ internal static class ChatCommands
Color color = ColorUtility.TryParseHtmlString($"#{args[2].ToLower()}", out Color c) ? c : Color.red;
string tag = Utils.ColorString(color, string.Join(' ', args[3..]));
if (!tag.EndsWith(' ') && !tag.EndsWith('-') && !tag.EndsWith('>')) tag += " ";
PrivateTagManager.AddTag(pc.FriendCode, tag);
Utils.SendMessage("\n", player.PlayerId, string.Format(GetString("AddTagSuccess"), tag, id.ColoredPlayerName(), id));
@@ -550,12 +545,6 @@ internal static class ChatCommands
private static void DeleteTagCommand(PlayerControl player, string text, string[] args)
{
if (!AmongUsClient.Instance.AmHost)
{
RequestCommandProcessingFromHost(nameof(DeleteTagCommand), text);
return;
}
if (args.Length < 2 || !byte.TryParse(args[1], out byte id)) return;
PlayerControl pc = id.GetPlayer();
@@ -563,6 +552,7 @@ internal static class ChatCommands
PrivateTagManager.DeleteTag(pc.FriendCode);
Utils.SendMessage("\n", player.PlayerId, string.Format(GetString("DeleteTagSuccess"), id.ColoredPlayerName()));
Utils.DirtyName.Add(pc.PlayerId);
}
private static void EightBallCommand(PlayerControl player, string text, string[] args)
@@ -1463,13 +1453,7 @@ internal static class ChatCommands
string subArgs = args.Length != 2 ? "" : args[1];
if (subArgs == "" || !int.TryParse(subArgs, out int guessedNo))
{
Utils.SendMessage(GetString("GNoCommandInfo"), player.PlayerId, sendOption: SendOption.None);
return;
}
if (guessedNo is < 0 or > 99)
if (subArgs == "" || !int.TryParse(subArgs, out int guessedNo) || guessedNo is < 0 or > 99)
{
Utils.SendMessage(GetString("GNoCommandInfo"), player.PlayerId, sendOption: SendOption.None);
return;
@@ -3271,7 +3255,7 @@ internal static class ChatCommands
var commandEntered = false;
if (text.StartsWith('/') && (!GameStates.IsMeeting || MeetingHud.Instance.state is not MeetingHud.VoteStates.Results and not MeetingHud.VoteStates.Proceeding))
if (text.StartsWith('/') && !player.IsModdedClient() && (!GameStates.IsMeeting || MeetingHud.Instance.state is not MeetingHud.VoteStates.Results and not MeetingHud.VoteStates.Proceeding))
{
foreach (Command command in AllCommands)
{
+10 -2
View File
@@ -43,13 +43,13 @@ internal static class HudManagerPatch
if (Input.GetKeyDown(KeyCode.LeftControl))
{
if ((!AmongUsClient.Instance.IsGameStarted || !GameStates.IsOnlineGame) && player.CanMove)
//if ((!AmongUsClient.Instance.IsGameStarted || !GameStates.IsOnlineGame) && player.CanMove)
player.Collider.offset = new(0f, 127f);
}
if (Math.Abs(player.Collider.offset.y - 127f) < 0.1f)
{
if (!Input.GetKey(KeyCode.LeftControl) || (AmongUsClient.Instance.IsGameStarted && GameStates.IsOnlineGame))
if (!Input.GetKey(KeyCode.LeftControl) /*|| (AmongUsClient.Instance.IsGameStarted && GameStates.IsOnlineGame)*/)
player.Collider.offset = new(0f, -0.3636f);
}
@@ -774,6 +774,8 @@ internal static class MapRoomDoorsUpdatePatch
}
}
[HarmonyPatch(typeof(CrewmateGhostRole), nameof(CrewmateGhostRole.SpawnTaskHeader))]
[HarmonyPatch(typeof(ImpostorGhostRole), nameof(ImpostorGhostRole.SpawnTaskHeader))]
[HarmonyPatch(typeof(ImpostorRole), nameof(ImpostorRole.SpawnTaskHeader))]
internal static class SpawnTaskHeaderPatch
{
@@ -792,6 +794,12 @@ internal static class TaskPanelBehaviourPatch
if (taskList == "None" || GameStates.IsLobby || player == null) return;
if (MeetingStates.FirstMeeting)
{
NetworkedPlayerInfo data = PlayerControl.LocalPlayer.Data;
if (data && data.Role) taskList = taskList.Replace($"\n{data.Role.NiceName} {FastDestroyableSingleton<TranslationController>.Instance.GetString(StringNames.RoleHint)}\n{data.Role.BlurbMed}", string.Empty);
}
CustomRoles role = player.GetCustomRole();
if (!role.IsVanilla() && role != CustomRoles.NotAssigned)
-3
View File
@@ -1055,7 +1055,6 @@ internal static class IntroCutsceneDestroyPatch
foreach (PlayerControl pc in aapc)
{
if (pc.Is(CustomRoles.GM)) continue;
if (pc.CurrentOutfit.PetId != "") continue;
string petId = PetsHelper.GetPetId();
PetsHelper.SetPet(pc, petId);
@@ -1065,9 +1064,7 @@ internal static class IntroCutsceneDestroyPatch
Main.ProcessShapeshifts = false;
LateTask.New(GrantPetForEveryone, 0.3f, "Grant Pet For Everyone");
LateTask.New(GrantPetForEveryone, 0.7f, "Grant Pet For Everyone");
LateTask.New(GrantPetForEveryone, 1.1f, "Grant Pet For Everyone");
LateTask.New(() =>
{
+1 -1
View File
@@ -542,7 +542,7 @@ internal static class CheckForEndVotingPatch
if (Virus.PlayerIdList.Count > 0) Virus.OnCheckForEndVoting(deathReason, playerIds);
if (deathReason == PlayerState.DeathReason.Vote) Gaslighter.OnExile(playerIds);
if (Wasp.On && deathReason == PlayerState.DeathReason.Vote) Wasp.OnExile(playerIds);
if (CustomRoles.SpellCaster.RoleExist()) SpellCaster.OnExile(playerIds);
if (CustomRoles.SpellCaster.RoleExist() && deathReason == PlayerState.DeathReason.Vote) SpellCaster.OnExile(playerIds);
foreach (byte playerId in playerIds)
{
+1 -1
View File
@@ -61,7 +61,7 @@ public static class PhantomRolePatch
PlayerControl phantom = __instance;
Logger.Info($"Player: {phantom.GetNameWithRole()}", "CheckVanish");
if (!Rhapsode.CheckAbilityUse(phantom) || Stasis.IsTimeFrozen || TimeMaster.Rewinding || !Main.PlayerStates[__instance.PlayerId].Role.OnVanish(__instance))
if ((phantom.Is(CustomRoles.Trainee) && MeetingStates.FirstMeeting) || !Rhapsode.CheckAbilityUse(phantom) || Stasis.IsTimeFrozen || TimeMaster.Rewinding || !Main.PlayerStates[__instance.PlayerId].Role.OnVanish(__instance))
{
if (phantom.AmOwner)
{
+10 -5
View File
@@ -1219,8 +1219,6 @@ internal static class ReportDeadBodyPatch
PhantomRolePatch.OnReportDeadBody(pc);
}
CustomSabotage.Reset();
MeetingTimeManager.OnReportDeadBody();
NameNotifyManager.Reset();
@@ -1324,6 +1322,8 @@ internal static class FixedUpdatePatch
try { DoPostfix(__instance, lowLoad); }
catch (Exception ex)
{
if (OnGameJoinedPatch.JoiningGame && ex is NullReferenceException) return;
long now = TimeStamp;
string nameWithRole = __instance.GetNameWithRole();
if (string.IsNullOrEmpty(nameWithRole.Trim())) return;
@@ -1424,11 +1424,16 @@ internal static class FixedUpdatePatch
QuizMaster.Data.LastSabotage = QuizMaster.AllSabotages.FirstOrDefault(IsActive);
}
if (!lowLoad && player.IsModdedClient() && player.Is(CustomRoles.Haste)) player.ForceKillTimerContinue = true;
if (!lowLoad && player.IsModdedClient() && player.Is(CustomRoles.Haste))
player.ForceKillTimerContinue = true;
if (DoubleTrigger.FirstTriggerTimer.Count > 0) DoubleTrigger.OnFixedUpdate(player);
if (DoubleTrigger.FirstTriggerTimer.Count > 0)
DoubleTrigger.OnFixedUpdate(player);
if (Main.PlayerStates.TryGetValue(playerId, out PlayerState s) && s.Role.IsEnable) s.Role.OnFixedUpdate(player);
SabotageSystemTypeRepairDamagePatch.SabotageDoubleTrigger.Update(Time.deltaTime);
if (Main.PlayerStates.TryGetValue(playerId, out PlayerState s) && s.Role.IsEnable)
s.Role.OnFixedUpdate(player);
if (inTask && player.Is(CustomRoles.PlagueBearer) && PlagueBearer.IsPlaguedAll(player))
{
+7 -3
View File
@@ -40,6 +40,8 @@ internal static class OnGameJoinedPatch
GameStates.InGame = false;
ErrorText.Instance?.Clear();
Utils.DirtyName = [];
LateTask.New(Achievements.ShowWaitingAchievements, 8f, log: false);
if (AmongUsClient.Instance.AmHost)
@@ -58,6 +60,8 @@ internal static class OnGameJoinedPatch
LateTask.New(() =>
{
JoiningGame = false;
if (BanManager.CheckEACList(PlayerControl.LocalPlayer.FriendCode, PlayerControl.LocalPlayer.GetClient().GetHashedPuid()) && GameStates.IsOnlineGame)
{
AmongUsClient.Instance.ExitGame(DisconnectReasons.Banned);
@@ -77,8 +81,6 @@ internal static class OnGameJoinedPatch
LateTask.New(() =>
{
JoiningGame = false;
if (GameStates.IsOnlineGame && GameStates.CurrentServerType != GameStates.ServerType.Custom)
{
try
@@ -211,6 +213,8 @@ internal static class OnPlayerJoinedPatch
{
if (!AmongUsClient.Instance.AmHost) return;
Utils.DirtyName.Add(PlayerControl.LocalPlayer.PlayerId);
if (Options.KickSlowJoiningPlayers.GetBool() && ((!client.IsDisconnected() && client.Character.Data.IsIncomplete) || ((client.Character.Data.DefaultOutfit.ColorId < 0 || Palette.PlayerColors.Length <= client.Character.Data.DefaultOutfit.ColorId) && Main.AllPlayerControls.Length <= 15)))
{
Logger.SendInGame(GetString("Error.InvalidColor") + $" {client.Id}/{client.PlayerName}");
@@ -415,7 +419,7 @@ internal static class InnerNetClientSpawnPatch
else
{
MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SyncLobbyTimer, SendOption.Reliable, client.Id);
writer.WritePacked((int)GameStartManagerPatch.TimerStartTS);
writer.Write(GameStartManagerPatch.TimerStartTS.ToString());
AmongUsClient.Instance.FinishRpcImmediately(writer);
}
}
+85 -5
View File
@@ -1,3 +1,5 @@
using System;
using System.Linq;
using AmongUs.GameOptions;
using EHR.Crewmate;
using EHR.Impostor;
@@ -135,6 +137,8 @@ public static class MushroomMixupSabotageSystemUpdateSystemPatch
Utils.NotifyRoles(SpecifySeer: pc, ForceLoop: true, MushroomMixup: true);
}
}
ReportDeadBodyPatch.CanReport.SetAllValues(false);
}
}
@@ -149,10 +153,6 @@ public static class MushroomMixupSabotageSystemPatch
if (Options.UsePets.GetBool()) __instance.petEmptyChance = 0;
ReportDeadBodyPatch.CanReport.SetAllValues(false);
Logger.Info("Disable Reporting", "MushroomMixupSabotageSystem");
LateTask.New(() => ReportDeadBodyPatch.CanReport.SetAllValues(true), (Options.SabotageTimeControl.GetBool() ? Options.FungleMushroomMixupDuration.GetFloat() : 10f) + 1.5f, "Enable Reporting After Mushroom Mixup");
if (!Options.SabotageTimeControl.GetBool()) return;
if ((MapNames)Main.NormalOptions.MapId is not MapNames.Fungle) return;
@@ -182,6 +182,8 @@ public static class MushroomMixupSabotageSystemPatch
{
// After MushroomMixup sabotage, shapeshift cooldown sets to 0
Main.AllAlivePlayerControls.DoIf(x => x.GetRoleTypes() != RoleTypes.Engineer, x => x.RpcResetAbilityCooldown());
ReportDeadBodyPatch.CanReport.SetAllValues(true);
}, 1.2f, "Reset Ability Cooldown Arter Mushroom Mixup");
foreach (PlayerControl pc in Main.AllAlivePlayerControls)
@@ -301,6 +303,16 @@ public static class ElectricTaskCompletePatch
}
}
[HarmonyPatch(typeof(SabotageSystemType), nameof(SabotageSystemType.AnyActive), MethodType.Getter)]
internal static class SabotageSystemTypeAnyActivePatch
{
public static bool Prefix(SabotageSystemType __instance, ref bool __result)
{
__result = __instance.specials.ToArray().Any(s => s.IsActive) || CustomSabotage.Instances.Count > 0;
return false;
}
}
// https://github.com/tukasa0001/TownOfHost/blob/357f7b5523e4bdd0bb58cda1e0ff6cceaa84813d/Patches/SabotageSystemPatch.cs
// Method called when sabotage occurs
[HarmonyPatch(typeof(SabotageSystemType), nameof(SabotageSystemType.UpdateSystem))]
@@ -309,15 +321,55 @@ public static class SabotageSystemTypeRepairDamagePatch
public static bool IsCooldownModificationEnabled;
public static float ModifiedCooldownSec;
public static SabotageSystemType Instance;
public static void Initialize()
{
IsCooldownModificationEnabled = Options.SabotageCooldownControl.GetBool();
ModifiedCooldownSec = Options.SabotageCooldown.GetFloat();
}
public static class SabotageDoubleTrigger
{
public static bool WaitingForDoubleTrigger;
public static PlayerControl TriggeringPlayer;
public static float TimeSinceFirstTrigger;
public static Action SingleTriggerAction;
public static void SetUp(PlayerControl player, Action singleTriggerAction)
{
WaitingForDoubleTrigger = true;
TriggeringPlayer = player;
TimeSinceFirstTrigger = 0f;
SingleTriggerAction = singleTriggerAction;
}
public static void Update(float deltaTime)
{
if (!WaitingForDoubleTrigger || TriggeringPlayer == null) return;
TimeSinceFirstTrigger += deltaTime;
if (TimeSinceFirstTrigger > 1f)
{
SingleTriggerAction();
Reset();
}
}
public static void Reset()
{
WaitingForDoubleTrigger = false;
TriggeringPlayer = null;
TimeSinceFirstTrigger = 0f;
SingleTriggerAction = null;
}
}
public static bool Prefix(SabotageSystemType __instance, [HarmonyArgument(0)] PlayerControl player, [HarmonyArgument(1)] MessageReader msgReader)
{
if (Options.CurrentGameMode != CustomGameMode.Standard) return false;
Instance = __instance;
if (Options.CurrentGameMode != CustomGameMode.Standard || __instance.Timer > 0f) return false;
SystemTypes systemTypes;
{
@@ -326,6 +378,25 @@ public static class SabotageSystemTypeRepairDamagePatch
newReader.Recycle();
}
if (Options.EnableCustomSabotages.GetBool())
{
if (Options.EnableGrabOxygenMaskCustomSabotage.GetBool() && systemTypes == SystemTypes.Comms)
{
if (!SabotageDoubleTrigger.WaitingForDoubleTrigger)
{
SabotageDoubleTrigger.SetUp(player, () =>
{
new GrabOxygenMaskSabotage().Deteriorate();
__instance.Timer = IsCooldownModificationEnabled ? ModifiedCooldownSec : 30f;
__instance.IsDirty = true;
});
return false;
}
SabotageDoubleTrigger.Reset();
}
}
return CheckSabotage(__instance, player, systemTypes);
}
@@ -453,4 +524,13 @@ public static class SecurityCameraPatch
return true;
}
}
[HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.RepairCriticalSabotages))]
internal static class ShipStatusRepairCriticalSabotagesPatch
{
public static void Postfix(ShipStatus __instance)
{
CustomSabotage.Reset();
}
}
+1
View File
@@ -254,6 +254,7 @@ internal static class CloseDoorsPatch
if (SecurityGuard.BlockSabo.Count > 0) allow = false;
if (Options.DisableCloseDoor.GetBool()) allow = false;
if (Main.CurrentMap != MapNames.Polus && SabotageSystemTypeRepairDamagePatch.Instance != null && SabotageSystemTypeRepairDamagePatch.Instance.AnyActive) allow = false;
Logger.Info($"({room}) => {(allow ? "Allowed" : "Blocked")}", "DoorClose");
return allow;
+1 -1
View File
@@ -217,7 +217,7 @@ public static class TextBoxPatch
"{role}" or "[role]" => ChatCommands.GetRoleByName(arg, out _),
"{addon}" => ChatCommands.GetRoleByName(arg, out CustomRoles role) && role.IsAdditionRole(),
"{chance}" => int.TryParse(arg, out int chance) && chance is >= 0 and <= 100 && chance % 5 == 0,
"{color}" => arg.Length == 6 && arg.All(x => char.IsDigit(x) || x is >= 'a' and <= 'f') && ColorUtility.TryParseHtmlString($"#{arg}", out _),
"{color}" => arg.Length == 6 && arg.All(x => char.IsDigit(x) || x is >= 'a' and <= 'f') && ColorUtility.TryParseHtmlString($"#{arg.ToLower()}", out _),
_ => false
};
+8 -4
View File
@@ -1929,6 +1929,7 @@
"DeathReason.Stung": "Stung",
"DeathReason.Scavenged": "Scavenged",
"DeathReason.Allergy": "Allergy",
"DeathReason.OutOfOxygen": "Out Of Oxygen",
"DeathReason.Meteor": "Meteor Strike",
"DeathReason.Lava": "Lava",
"DeathReason.Tornado": "Tornado",
@@ -2075,9 +2076,6 @@
"StressedExtraTimeAfterFixingSabotage": "Time Gained For Fixing a Sabotage",
"StressedExtraTimeAfterReporting": "Time Gained For Reporting a Dead Body",
"StressedTimePenaltyAfterCrewmateEjected": "Time Penalty When a Crewmate Gets Ejected",
"CustomSabotageActivated": "<#ffff00>Custom Sabotage Activated!</color>",
"CustomSabotage.GrabOxygenMask": "Grab Oxygen Mask",
"CustomSabotage.GrabOxygenMask.Done": "<#00ff00>Oxygen Mask Grabbed! You are safe.</color>",
"SabotageCooldownControl": "Modify Sabotage Cooldown",
"SabotageCooldown": "Sabotage Cooldown",
"SabotageTimeControl": "Modify Sabotage Time Limit",
@@ -2165,6 +2163,10 @@
"SabotageTimeLimitWinners.Imps": "<#ff1919>Impostors</color>",
"SabotageTimeLimitWinners.NKs": "<#ffab1b>Neutral</color> <#ff1919>Killers</color>",
"SabotageTimeLimitWinners.Coven": "<#7b3fbb>Coven</color>",
"EnableCustomSabotages": "Enable Custom Sabotages",
"EnableGrabOxygenMaskCustomSabotage": "Enable Grab Oxygen Mask (call by sabotaging comms - to sabotage comms normally, click on the button twice)",
"CustomSabotage.GrabOxygenMask": "Grab Oxygen Mask",
"CustomSabotage.GrabOxygenMask.Done": "<#00ff00>Oxygen Mask Grabbed! You are safe.</color>",
"MorticianGetNoInfo": "According to your inspection, <b>{0}</b> did not seem to have contact with anyone during their lifetime.",
"MorticianGetInfo": "According to your inspection, the last person <b>{0}</b> came into contact with during their lifetime was <b>{1}</b>.",
"MediumshipHelp": "<b>/ms yes</b> to agree\\n<b>/ms no</b> to disagree",
@@ -4914,6 +4916,8 @@
"RR_YouWereLast": "<#ff1919>You were the last to get to the room</color>",
"RR_ReadyQM": "Ready?\\nStarting in <#ffff44>{0}</color>",
"RR_Points": "Points: {0}/{1}",
"RR_FirstPoints": "1st place: {0} with {1} points",
"RR_YouAreFirst": "You are in the 1st place",
"RR_Tie": "<size=80%><#00a5ff>In tie with {0}\\nWaiting for the tie to break....</color></size>",
"RRPlayer": "ROOM RUSH",
"RRPlayerInfo": "GET TO THE ROOM ASAP",
@@ -8759,7 +8763,7 @@
"RookieInfoLong": "(Add-ons):\\nYou can't kill on the first round.",
"Prefix.Rookie": "Rookie",
"Trainee": "Trainee",
"TraineeInfo": "You Can't Vent/Sabotage/SS/Pet Round 1",
"TraineeInfo": "You Can't Vent/Sabotage/SS/Pet/Vanish Round 1",
"TraineeInfoLong": "(Add-ons):\\nYou can't vent, sabotage, shapeshift, or pet on the first round.",
"Prefix.Trainee": "Trainee",
"TraineeNotify": "<#ffff00>As the <#4287f5>Trainee</color>, you can't vent, sabotage, shapeshift, or pet on the first round!</color>",
+2
View File
@@ -84,6 +84,8 @@ public class SpellCaster : Coven
{
try
{
if (!On) return;
if (exileIds.Any(PlayerIdList.Contains))
HexedPlayers.Clear();
+1
View File
@@ -165,6 +165,7 @@ public class Alchemist : RoleBase
public override void OnEnterVent(PlayerControl pc, Vent vent)
{
if (OnCoEnterVent(pc.MyPhysics, vent.Id)) return;
if (UsePets.GetBool()) return;
DrinkPotion(pc, vent.Id);
}
+3 -2
View File
@@ -96,14 +96,14 @@ public class Altruist : RoleBase
}
PlayerControl rtg = ReviveTarget.GetPlayer();
PlayerControl killer = rtg == null ? null : rtg.GetRealKiller();
rtg?.RpcRevive();
rtg?.TP(ReviveTargetPos);
rtg?.Notify(Translator.GetString("RevivedByAltruist"), 15f);
RevivedPlayers.Add(ReviveTarget);
PlayerControl killer = rtg == null ? null : rtg.GetRealKiller();
if (killer != null && ReviveTargetsKillerGetsAlert.GetBool())
{
if (ReviveTargetsKillerGetsArrow.GetBool()) TargetArrow.Add(killer.PlayerId, ReviveTarget);
@@ -144,6 +144,7 @@ public class Altruist : RoleBase
public override void OnEnterVent(PlayerControl pc, Vent vent)
{
if (Options.UsePets.GetBool()) return;
OnPet(pc);
}
+14 -3
View File
@@ -1,6 +1,8 @@
using AmongUs.GameOptions;
using System.Linq;
using AmongUs.GameOptions;
using EHR.Modules;
using Hazel;
using UnityEngine;
namespace EHR.Crewmate;
@@ -56,6 +58,7 @@ public class Astral : RoleBase
public override void OnEnterVent(PlayerControl pc, Vent vent)
{
if (Options.UsePets.GetBool()) return;
LateTask.New(() => BecomeGhostTemporarily(pc), 2f, log: false);
}
@@ -85,7 +88,7 @@ public class Astral : RoleBase
Utils.SendRPC(CustomRPC.SyncRoleData, AstralId, BackTS);
GhostRolesManager.RemoveGhostRole(pc.PlayerId);
pc.RpcChangeRoleBasis(pc.GetRoleMap().CustomRole);
pc.RpcChangeRoleBasis(CustomRoles.Astral);
Camouflage.RpcSetSkin(pc);
if (onMeeting) return;
@@ -97,6 +100,14 @@ public class Astral : RoleBase
Utils.NotifyRoles(SpecifySeer: pc);
Utils.NotifyRoles(SpecifyTarget: pc);
if (!pc.IsInsideMap())
{
Vector2 playerPosition = pc.Pos();
Vector2 closestSpawnPosition = RandomSpawn.SpawnMap.GetSpawnMap().Positions.Values.MinBy(x => Vector2.Distance(playerPosition, x));
Vector3 closestVentPosition = pc.GetClosestVent()?.transform.position ?? closestSpawnPosition;
pc.TP(Vector2.Distance(playerPosition, closestVentPosition) < Vector2.Distance(playerPosition, closestSpawnPosition) ? closestVentPosition : closestSpawnPosition);
}
}
public override void OnFixedUpdate(PlayerControl pc)
@@ -132,6 +143,6 @@ public class Astral : RoleBase
public override string GetSuffix(PlayerControl seer, PlayerControl target, bool hud = false, bool meeting = false)
{
if (seer.PlayerId != AstralId || seer.PlayerId != target.PlayerId || hud || meeting || BackTS == 0) return string.Empty;
return string.Format(Translator.GetString("AstralSuffix"), BackTS - Utils.TimeStamp);
return string.Format(Translator.GetString("AstralSuffix"), BackTS - Utils.TimeStamp - 1);
}
}
+1
View File
@@ -83,6 +83,7 @@ public class CameraMan : RoleBase
public override void OnEnterVent(PlayerControl pc, Vent vent)
{
if (UsePets.GetBool()) return;
if (pc == null) return;
if (pc.GetAbilityUseLimit() >= 1)
+1
View File
@@ -107,6 +107,7 @@ public class Catcher : RoleBase
public override void OnEnterVent(PlayerControl pc, Vent vent)
{
if (Options.UsePets.GetBool()) return;
DelayStartTS = Utils.TimeStamp + 1;
SendRPC();
}
+1
View File
@@ -56,6 +56,7 @@ public class Clairvoyant : RoleBase
public override void OnEnterVent(PlayerControl pc, Vent vent)
{
if (Options.UsePets.GetBool()) return;
UseAbility(pc);
}
+1
View File
@@ -57,6 +57,7 @@ internal class Convener : RoleBase
public override void OnEnterVent(PlayerControl pc, Vent vent)
{
if (Options.UsePets.GetBool()) return;
PullEveryone(pc);
}
+1
View File
@@ -67,6 +67,7 @@ internal class DovesOfNeace : RoleBase
public override void OnEnterVent(PlayerControl pc, Vent vent)
{
if (UsePets.GetBool()) return;
ResetCooldowns(pc);
}
+1
View File
@@ -125,6 +125,7 @@ public class Druid : RoleBase
public override void OnEnterVent(PlayerControl pc, Vent vent)
{
if (UsePets.GetBool()) return;
PlaceTrigger(pc);
}
+1
View File
@@ -90,6 +90,7 @@ internal class Grenadier : RoleBase
public override void OnEnterVent(PlayerControl pc, Vent vent)
{
if (UsePets.GetBool()) return;
BlindPlayers(pc);
}
+1
View File
@@ -102,6 +102,7 @@ internal class Lighter : RoleBase
public override void OnEnterVent(PlayerControl pc, Vent vent)
{
if (UsePets.GetBool()) return;
Light(pc);
}
+1
View File
@@ -63,6 +63,7 @@ internal class Mayor : RoleBase
public override void OnEnterVent(PlayerControl pc, Vent vent)
{
if (UsePets.GetBool()) return;
pc.MyPhysics?.RpcBootFromVent(vent.Id);
Button(pc);
}
+1
View File
@@ -111,6 +111,7 @@ public class NiceHacker : RoleBase
public override void OnEnterVent(PlayerControl pc, Vent vent)
{
if (UsePets.GetBool()) return;
UseAbility(pc);
}
+1
View File
@@ -67,6 +67,7 @@ internal class Paranoia : RoleBase
public override void OnEnterVent(PlayerControl pc, Vent vent)
{
if (UsePets.GetBool()) return;
pc.MyPhysics?.RpcBootFromVent(vent.Id);
Panic(pc);
}
+1
View File
@@ -65,6 +65,7 @@ internal class Perceiver : RoleBase
public override void OnEnterVent(PlayerControl pc, Vent vent)
{
if (Options.UsePets.GetBool()) return;
UseAbility(pc);
}
+1
View File
@@ -85,6 +85,7 @@ public class Rhapsode : RoleBase
public override void OnEnterVent(PlayerControl pc, Vent vent)
{
if (Options.UsePets.GetBool()) return;
ActivateAbility(pc);
}
+1
View File
@@ -80,6 +80,7 @@ internal class SecurityGuard : RoleBase
public override void OnEnterVent(PlayerControl pc, Vent vent)
{
if (UsePets.GetBool()) return;
Guard(pc);
}
+1
View File
@@ -152,6 +152,7 @@ internal class Sentinel : RoleBase
public override void OnEnterVent(PlayerControl pc, Vent vent)
{
if (UsePets.GetBool()) return;
GetPatrollingState(pc.PlayerId)?.StartPatrolling();
}
+1
View File
@@ -89,6 +89,7 @@ public class Tether : RoleBase
public override void OnEnterVent(PlayerControl pc, Vent vent)
{
if (UsePets.GetBool()) return;
Teleport(pc, vent.Id);
}
+1
View File
@@ -87,6 +87,7 @@ internal class TimeMaster : RoleBase
public override void OnEnterVent(PlayerControl pc, Vent vent)
{
if (UsePets.GetBool()) return;
if (pc.GetAbilityUseLimit() < 1) return;
pc.RpcRemoveAbilityUse();
+1
View File
@@ -82,6 +82,7 @@ internal class Veteran : RoleBase
public override void OnEnterVent(PlayerControl pc, Vent vent)
{
if (UsePets.GetBool()) return;
Alert(pc);
}
+1
View File
@@ -308,6 +308,7 @@ internal class AntiAdminer : RoleBase
public override void OnEnterVent(PlayerControl pc, Vent vent)
{
if (Options.UsePets.GetBool()) return;
if (!IsMonitor) return;
OpenDoors(pc);
}
+1
View File
@@ -98,6 +98,7 @@ internal class Changeling : RoleBase
public override void OnEnterVent(PlayerControl pc, Vent vent)
{
if (UsePets.GetBool()) return;
SelectNextRole(pc);
}
+30 -4
View File
@@ -116,6 +116,11 @@ public class Swooper : RoleBase
{
if (UsedRole == CustomRoles.Chameleon)
AURoleOptions.EngineerCooldown = Cooldown + 1f;
else if (UsePhantomBasis.GetBool() && (UsedRole == CustomRoles.Swooper || UsePhantomBasisForNKs.GetBool()))
{
AURoleOptions.PhantomCooldown = Cooldown;
AURoleOptions.PhantomDuration = 0.1f;
}
}
catch (Exception e) { Utils.ThrowException(e); }
}
@@ -182,7 +187,6 @@ public class Swooper : RoleBase
if (lastFixedTime != now && IsInvis)
{
lastFixedTime = now;
var refresh = false;
long remainTime = InvisTime + (long)Duration - now;
switch (remainTime)
@@ -192,16 +196,14 @@ public class Swooper : RoleBase
int ventId = ventedId == -10 ? Main.LastEnteredVent[player.PlayerId].Id : ventedId;
Main.AllPlayerControls.Without(player).Do(x => player.MyPhysics.RpcExitVentDesync(ventId, x));
player.Notify(GetString("SwooperInvisStateOut"));
player.RpcResetAbilityCooldown();
InvisTime = -10;
SendRPC();
refresh = true;
break;
case <= 10 when !player.IsModdedClient():
player.Notify(string.Format(GetString("SwooperInvisStateCountdown"), remainTime + 1), overrideAll: true);
break;
}
if (refresh) SendRPC();
}
}
@@ -248,6 +250,30 @@ public class Swooper : RoleBase
SendRPC();
pc.Notify(GetString("SwooperInvisStateOut"), 10f);
pc.RpcResetAbilityCooldown();
}
public override bool OnVanish(PlayerControl pc)
{
if (IsInvis) return false;
float limit = pc.GetAbilityUseLimit();
bool wraith = UsedRole == CustomRoles.Wraith;
if (CanGoInvis && (wraith || limit >= 1))
{
int? ventId = pc.GetClosestVent()?.Id;
Main.AllPlayerControls.Without(pc).Do(x => pc.MyPhysics.RpcEnterVentDesync(ventId ?? 2, x));
ventedId = ventId ?? -10;
InvisTime = Utils.TimeStamp;
if (!wraith) pc.RpcRemoveAbilityUse();
SendRPC();
pc.Notify(GetString("SwooperInvisState"), Duration);
}
return false;
}
public override string GetSuffix(PlayerControl seer, PlayerControl target, bool hud = false, bool meeting = false)
+1
View File
@@ -100,6 +100,7 @@ internal class Arsonist : RoleBase
public override void OnEnterVent(PlayerControl pc, Vent vent)
{
if (UsePets.GetBool()) return;
if (AmongUsClient.Instance.IsGameStarted)
Ignite(pc.MyPhysics);
}
+1 -1
View File
@@ -83,7 +83,7 @@ public class Lawyer : RoleBase
SendRPC(playerId, selectedTarget.PlayerId, "SetTarget");
Logger.Info($"{Utils.GetPlayerById(playerId)?.GetNameWithRole().RemoveHtmlTags()}:{selectedTarget.GetNameWithRole().RemoveHtmlTags()}", "Lawyer");
LateTask.New(() => playerId.GetPlayer()?.Notify(string.Format(Translator.GetString("YourLawyerIsNotify"), LawyerId.ColoredPlayerName())), 18f, log: false);
LateTask.New(() => selectedTarget.Notify(string.Format(Translator.GetString("YourLawyerIsNotify"), LawyerId.ColoredPlayerName())), 18f, log: false);
}
}
catch (Exception ex) { Utils.ThrowException(ex); }
-2
View File
@@ -89,8 +89,6 @@ public class Shifter : RoleBase
killer.RpcSetCustomRole(targetRole);
killer.RpcChangeRoleBasis(targetRole);
Main.PlayerStates[killer.PlayerId].Role = Main.PlayerStates[target.PlayerId].Role;
killer.SetAbilityUseLimit(target.GetAbilityUseLimit());
TaskState taskState = target.GetTaskState();