Compare commits

...
13 Commits
Author SHA1 Message Date
Gurge44 4e80042324 a 2026-01-15 14:34:36 +01:00
Gurge44 e135e75efc remove HTML tags on vanilla servers 2026-01-15 14:33:25 +01:00
Gurge44 ed02400090 version 2026-01-15 14:06:37 +01:00
Gurge44 15f229e458 changelog 2026-01-15 14:06:18 +01:00
Gurge44 f7dffc84e8 fix 2026-01-15 14:02:29 +01:00
Gurge44 3c0b86ab14 fix flaws 2026-01-15 13:57:35 +01:00
Gurge44 ef8f0e1337 Merge remote-tracking branch 'origin/main' 2026-01-15 12:10:41 +01:00
Gurge44 28da21dfb4 fix 2026-01-15 12:10:32 +01:00
Crowdin Bot 81e2d4e2d5 chore: update translations for release 7.1.3 2026-01-15 11:04:31 +00:00
Gurge44 2c05cd6b99 changelog 2026-01-15 12:01:39 +01:00
Gurge44 c458d15c02 swap 2026-01-15 12:00:36 +01:00
Gurge44 4ba0049bf3 wait a bit just to make sure 2026-01-15 11:58:51 +01:00
Gurge44 a962374eeb ACTUALLY FIX KICKING OMG 2026-01-15 11:55:17 +01:00
18 changed files with 149 additions and 61 deletions

No files matched your search

+5 -1
View File
@@ -1,5 +1,9 @@
# Thank you so much for finding and using EHR!
- Another attempt at fixing the host getting kicked on vanilla regions
- Fixed flaws with kick-prevention logic
- Fixed messages sometimes not appearing (HTML tag = entire message gone, ty innersloth)
- Fixed non-ASCII characters in the host's name causing errors
(you better not complain about the frequency of updates)
---
+2 -2
View File
@@ -42,8 +42,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 = "7.1.2";
public const string PluginDisplayVersion = "7.1.2";
public const string PluginVersion = "7.1.4";
public const string PluginDisplayVersion = "7.1.4";
public const bool TestBuild = false;
public const string NeutralColor = "#ffab1b";
+8 -4
View File
@@ -25,7 +25,7 @@ public static class AntiBlackout
PlayerControl[] players = Main.AllAlivePlayerControls;
if (CheckForEndVotingPatch.TempExiledPlayer != null) players = players.Where(x => x.PlayerId != CheckForEndVotingPatch.TempExiledPlayer.PlayerId).ToArray();
PlayerControl dummyImp = players.OrderByDescending(x => x.GetRoleMap().RoleType != RoleTypes.Detective).ThenByDescending(x => x.IsModdedClient()).MinBy(x => x.PlayerId);
PlayerControl dummyImp = players.OrderByDescending(x => x.GetCustomRole() is not (CustomRoles.DetectiveEHR or CustomRoles.Detective) && !x.Is(CustomRoles.Examiner)).ThenByDescending(x => x.IsModdedClient()).MinBy(x => x.PlayerId);
if (players.Length == 2)
{
@@ -49,9 +49,9 @@ public static class AntiBlackout
}
dummyImp.RpcSetRoleGlobal(RoleTypes.Impostor);
players.Without(dummyImp).Where(x => x.GetRoleMap().RoleType != RoleTypes.Detective).Do(x => x.RpcSetRoleGlobal(RoleTypes.Crewmate));
players.Without(dummyImp).Where(x => x.GetCustomRole() is not (CustomRoles.DetectiveEHR or CustomRoles.Detective) && !x.Is(CustomRoles.Examiner)).Do(x => x.RpcSetRoleGlobal(RoleTypes.Crewmate));
Main.AllPlayerControls.DoIf(x => !x.IsAlive() && x.Data != null && x.Data.IsDead, x => x.RpcSetRoleGlobal(GhostRolesManager.AssignedGhostRoles.TryGetValue(x.PlayerId, out var ghostRole) ? ghostRole.Instance.RoleTypes : RoleTypes.CrewmateGhost));
Main.AllPlayerControls.DoIf(x => !x.IsAlive() && x.Data != null && x.Data.IsDead && (!x.AmOwner || !Utils.TempReviveHostRunning), x => x.RpcSetRoleGlobal(GhostRolesManager.AssignedGhostRoles.TryGetValue(x.PlayerId, out var ghostRole) ? ghostRole.Instance.RoleTypes : RoleTypes.CrewmateGhost));
}
// After the ejection screen, we revert the role types to their actual values.
@@ -69,6 +69,8 @@ public static class AntiBlackout
{
try
{
if (pc.AmOwner && Utils.TempReviveHostRunning) continue;
NetworkedPlayerInfo data = pc.Data;
if (data != null && !data.IsDead && !data.Disconnected && !pc.IsAlive())
@@ -87,7 +89,7 @@ public static class AntiBlackout
{
PlayerControl seer = seerId.GetPlayer();
PlayerControl target = targetId.GetPlayer();
if (seer == null || target == null) continue;
if (seer == null || target == null || (seerId == targetId && seer.AmOwner && Utils.TempReviveHostRunning)) continue;
if (target.IsAlive()) target.RpcSetRoleDesync(roleType, seer.OwnerId);
else target.RpcSetRoleDesync(GhostRolesManager.AssignedGhostRoles.TryGetValue(targetId, out var ghostRole) ? ghostRole.Instance.RoleTypes : seerId == targetId && !(target.Is(CustomRoleTypes.Impostor) && Options.DeadImpCantSabotage.GetBool()) && Main.PlayerStates.TryGetValue(targetId, out var state) && state.Role.CanUseSabotage(target) ? RoleTypes.ImpostorGhost : RoleTypes.CrewmateGhost, seer.OwnerId);
@@ -123,6 +125,8 @@ public static class AntiBlackout
}
else
{
if (pc.AmOwner && Utils.TempReviveHostRunning) continue;
// Ensure that the players who are considered dead by the mod are actually dead in the game.
pc.Exiled();
MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(pc.NetId, 4, SendOption.Reliable);
+2 -1
View File
@@ -103,8 +103,9 @@ internal static class CustomRoleSelector
switch (role)
{
case CustomRoles.Ventriloquist when GameStates.CurrentServerType == GameStates.ServerType.Vanilla:
case CustomRoles.Weatherman when Main.LIMap || GameStates.CurrentServerType == GameStates.ServerType.Vanilla:
case CustomRoles.RoomRusher when Main.LIMap:
case CustomRoles.Weatherman when Main.LIMap:
case CustomRoles.Doctor when Options.EveryoneSeesDeathReasons.GetBool():
case CustomRoles.LovingCrewmate or CustomRoles.LovingImpostor when !loversData.Spawning:
case CustomRoles.Commander when optImpNum <= 1 && Commander.CannotSpawnAsSoloImp.GetBool():
@@ -594,7 +594,7 @@ public sealed class PlayerGameOptionsSender(PlayerControl player) : GameOptionsS
}
state.TaskState.HasTasks = Utils.HasTasks(player.Data, false);
if (Options.GhostCanSeeOtherVotes.GetBool() && player.Data.IsDead) opt.SetBool(BoolOptionNames.AnonymousVotes, false);
if (Options.GhostCanSeeOtherVotes.GetBool() && !player.IsAlive()) opt.SetBool(BoolOptionNames.AnonymousVotes, false);
if (Options.AdditionalEmergencyCooldown.GetBool() &&
Options.AdditionalEmergencyCooldownThreshold.GetInt() <= Utils.AllAlivePlayersCount)
+2 -1
View File
@@ -3,6 +3,7 @@ using System.Collections;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using HarmonyLib;
using InnerNet;
using UnityEngine;
@@ -54,7 +55,7 @@ public static class LobbySharingAPI
};
request.SetRequestHeader("Content-Type", "application/json");
request.SetRequestHeader("User-Agent", $"{Main.ModName} v{Main.PluginVersion} - {hostName}");
request.SetRequestHeader("User-Agent", $"{Main.ModName} v{Main.PluginVersion} - {Regex.Replace(hostName, @"[^\x20-\x7E]", "")}");
yield return request.SendWebRequest();
LastRequestTimeStamp = Utils.TimeStamp;
+72 -9
View File
@@ -1037,7 +1037,7 @@ public static class Utils
return true;
}
if ((Main.VisibleTasksCount && !PlayerControl.LocalPlayer.IsAlive() && Options.GhostCanSeeOtherRoles.GetBool() && (!IsRevivingRoleAlive() || !Main.DiedThisRound.Contains(PlayerControl.LocalPlayer.PlayerId))) || (PlayerControl.LocalPlayer.Is(CustomRoles.Mimic) && Main.VisibleTasksCount && __instance.Data.IsDead && Options.MimicCanSeeDeadRoles.GetBool())) return true;
if ((Main.VisibleTasksCount && !PlayerControl.LocalPlayer.IsAlive() && Options.GhostCanSeeOtherRoles.GetBool() && (!IsRevivingRoleAlive() || !Main.DiedThisRound.Contains(PlayerControl.LocalPlayer.PlayerId))) || (PlayerControl.LocalPlayer.Is(CustomRoles.Mimic) && Main.VisibleTasksCount && !__instance.IsAlive() && Options.MimicCanSeeDeadRoles.GetBool())) return true;
if (__instance.AmOwner) return true;
@@ -1796,17 +1796,23 @@ public static class Utils
catch (Exception e) { ThrowException(e); }
}
public static bool TempReviveHostRunning;
private static Stopwatch TempReviveHostStopwatch = new();
public static void SendMultipleMessages(this IEnumerable<Message> messages, SendOption sendOption = SendOption.Reliable)
{
var sender = CustomRpcSender.Create("Utils.SendMultipleMessages", sendOption);
sender = messages.Aggregate(sender, (current, message) => SendMessage(message.Text, message.SendTo, message.Title, writer: current, multiple: true, sendOption: sendOption));
sender.SendMessage(dispose: sender.stream.Length <= 3);
messages.Do(x => SendMessage(x.Text, x.SendTo, x.Title, sendOption: sendOption));
}
public static CustomRpcSender SendMessage(string text, byte sendTo = byte.MaxValue, string title = "", bool noSplit = false, CustomRpcSender writer = null, bool final = false, bool multiple = false, SendOption sendOption = SendOption.Reliable, bool addtoHistory = true)
public static CustomRpcSender SendMessage(string text, byte sendTo = byte.MaxValue, string title = "", bool noSplit = false, CustomRpcSender writer = null, bool final = false, bool multiple = false, SendOption sendOption = SendOption.Reliable, bool addToHistory = true, [CallerFilePath] string callerFilePath = "", [CallerLineNumber] int callerLineNumber = 0)
{
try
{
Logger.Info($"SendMessage called from {callerFilePath.Split('\\')[^1]} at line {callerLineNumber}", "SendMessage");
if (GameStates.CurrentServerType == GameStates.ServerType.Vanilla)
text = text.RemoveHtmlTags();
PlayerControl receiver = GetPlayerById(sendTo, false);
if (sendTo != byte.MaxValue && receiver == null || title.RemoveHtmlTags().Trim().Length == 0 && text.RemoveHtmlTags().Trim().Length == 0) return writer;
@@ -1838,7 +1844,64 @@ public static class Utils
text = text.Replace("color=", string.Empty);
title = title.Replace("color=", string.Empty);
PlayerControl sender = !addtoHistory ? PlayerControl.LocalPlayer : Main.AllAlivePlayerControls.MinBy(x => x.PlayerId) ?? Main.AllPlayerControls.MinBy(x => x.PlayerId) ?? PlayerControl.LocalPlayer;
PlayerControl sender = !addToHistory || GameStates.CurrentServerType == GameStates.ServerType.Vanilla ? PlayerControl.LocalPlayer : Main.AllAlivePlayerControls.MinBy(x => x.PlayerId) ?? Main.AllPlayerControls.MinBy(x => x.PlayerId) ?? PlayerControl.LocalPlayer;
if (sender.AmOwner && sender.Data.IsDead)
{
bool delayMessage = false;
if (!TempReviveHostRunning)
{
delayMessage = true;
Main.Instance.StartCoroutine(TempReviveHost());
}
else
{
if (TempReviveHostStopwatch.ElapsedMilliseconds < 200)
delayMessage = true;
TempReviveHostStopwatch.Restart();
}
if (delayMessage)
{
Main.Instance.StartCoroutine(DelaySend());
return writer;
IEnumerator DelaySend()
{
yield return new WaitForSeconds(0.3f);
SendMessage(text, sendTo, title, noSplit, writer, final, multiple, sendOption, addToHistory);
}
}
IEnumerator TempReviveHost()
{
TempReviveHostRunning = true;
TempReviveHostStopwatch = Stopwatch.StartNew();
Logger.Msg("Temporarily reviving host to send message....", "TempReviveHost");
sender.Data.IsDead = false;
sender.Data.SendGameData();
while (TempReviveHostStopwatch.ElapsedMilliseconds < 1000)
yield return null;
Logger.Msg("Re-killing host after message sent.", "TempReviveHost");
if (!AmongUsClient.Instance.AmHost || GameStates.IsEnded || GameStates.IsLobby)
{
TempReviveHostRunning = false;
yield break;
}
sender.Data.IsDead = true;
sender.Data.SendGameData();
TempReviveHostRunning = false;
}
}
if (sendTo != byte.MaxValue && receiver.AmOwner)
{
@@ -1858,7 +1921,7 @@ public static class Utils
}
catch { Logger.Info(" Message sent", "SendMessage"); }
if (addtoHistory) ChatUpdatePatch.LastMessages.Add((text, sendTo, title, TimeStamp));
if (addToHistory) ChatUpdatePatch.LastMessages.Add((text, sendTo, title, TimeStamp));
return writer;
}
@@ -1967,7 +2030,7 @@ public static class Utils
}
catch { Logger.Info(" Message sent", "SendMessage"); }
if (addtoHistory) ChatUpdatePatch.LastMessages.Add(("\n", sendTo, tempTitle, TimeStamp));
if (addToHistory) ChatUpdatePatch.LastMessages.Add(("\n", sendTo, tempTitle, TimeStamp));
return writer;
}
}
@@ -2075,7 +2138,7 @@ public static class Utils
}
catch (Exception e) { ThrowException(e); }
if (addtoHistory) ChatUpdatePatch.LastMessages.Add((text, sendTo, title, TimeStamp));
if (addToHistory) ChatUpdatePatch.LastMessages.Add((text, sendTo, title, TimeStamp));
return writer;
void RestartMessageIfTooLong()
+19 -1
View File
@@ -125,6 +125,8 @@ internal static class ChatCommands
public static bool HasMessageDuringEjectionScreen;
private static bool WaitingToSend;
public static void LoadCommands()
{
Command.AllCommands = new Dictionary<string, Command>
@@ -451,7 +453,7 @@ internal static class ChatCommands
if (!Main.AllPlayerNames.TryGetValue(PlayerControl.LocalPlayer.PlayerId, out string name))
Utils.ApplySuffix(PlayerControl.LocalPlayer, out name);
Utils.SendMessage(text.Insert(0, new('\n', name.Count(x => x == '\n'))), title: name, addtoHistory: false);
Utils.SendMessage(text.Insert(0, new('\n', name.Count(x => x == '\n'))), title: name, addToHistory: false);
canceled = true;
__instance.freeChatField.textArea.Clear();
@@ -466,6 +468,22 @@ internal static class ChatCommands
if (text.Contains("666") && PlayerControl.LocalPlayer.Is(CustomRoles.Demon))
Achievements.Type.WhatTheHell.Complete();
if (!canceled && AmongUsClient.Instance.AmHost && Utils.TempReviveHostRunning)
{
if (!WaitingToSend) Main.Instance.StartCoroutine(Wait());
return false;
IEnumerator Wait()
{
WaitingToSend = true;
while (Utils.TempReviveHostRunning && AmongUsClient.Instance.AmHost) yield return null;
yield return new WaitForSeconds(0.5f);
if (GameStates.IsEnded || GameStates.IsLobby) yield break;
WaitingToSend = false;
if (HudManager.InstanceExists) HudManager.Instance.Chat.SendChat();
}
}
return !canceled;
}
+2 -9
View File
@@ -72,10 +72,10 @@ internal static class GameEndChecker
Ended = true;
LoadingEndScreen = true;
//Main.AllPlayerControls.Do(pc => Camouflage.RpcSetSkin(pc, true, true, true));
Main.AllPlayerControls.Do(pc => Camouflage.RpcSetSkin(pc, true, true, true));
NameNotifyManager.Reset();
//NotifyRoles(ForceLoop: true);
NotifyRoles(ForceLoop: true);
CustomSabotage.Reset();
@@ -359,13 +359,6 @@ internal static class GameEndChecker
try { LobbySharingAPI.NotifyLobbyStatusChanged(LobbyStatus.Ended); }
catch (Exception e) { ThrowException(e); }
string msg = GetString("NotifyGameEnding");
Main.AllPlayerControls
.Where(x => x.GetClient() != null && !x.Data.Disconnected)
.Select(x => new Message("\n", x.PlayerId, msg))
.SendMultipleMessages();
SetEverythingUpPatch.LastWinsReason = WinnerTeam is CustomWinner.Crewmate or CustomWinner.Impostor ? GetString($"GameOverReason.{reason}") : string.Empty;
var self = AmongUsClient.Instance;
self.StartCoroutine(CoEndGame(self, reason).WrapToIl2Cpp());
+1 -1
View File
@@ -1192,7 +1192,7 @@ public static class GameSettingMenuPatch
gms.Remove(CustomGameMode.Deathrace);
}
int totalCols = 2;
int totalCols = 3;
GMButtons = [];
+1 -1
View File
@@ -40,7 +40,7 @@ public class FallFromLadder
if (TargetLadderData.TryGetValue(player.PlayerId, out Vector3 targetLadderData) && Vector2.Distance(targetLadderData, player.Pos()) < 0.5f)
{
if (player.Data.IsDead) return;
if (player.Data.IsDead || !player.IsAlive()) return;
// To insert LateTask, first enter the death judgment.
player.Data.IsDead = true;
+18 -12
View File
@@ -44,7 +44,7 @@ internal static class CheckForEndVotingPatch
// Dictators who are not dead have already voted.
// Take the initiative to rebel
if (pva.DidVote && pc.PlayerId == pva.VotedFor && pva.VotedFor < 253 && !pc.Data.IsDead)
if (pva.DidVote && pc.PlayerId == pva.VotedFor && pva.VotedFor < 253 && pc.IsAlive())
{
if (Options.MadmateSpawnMode.GetInt() == 2 && Main.MadmateNum < CustomRoles.Madmate.GetCount() && pc.CanBeMadmate())
{
@@ -121,7 +121,7 @@ internal static class CheckForEndVotingPatch
if (Options.VoteMode.GetBool())
{
if (ps.VotedFor == 253 && !voter.Data.IsDead &&
if (ps.VotedFor == 253 && voter.IsAlive() &&
!(Options.WhenSkipVoteIgnoreFirstMeeting.GetBool() && MeetingStates.FirstMeeting) &&
!(Options.WhenSkipVoteIgnoreNoDeadBody.GetBool() && !MeetingStates.IsExistDeadBody) &&
!(Options.WhenSkipVoteIgnoreEmergency.GetBool() && MeetingStates.IsEmergencyMeeting)
@@ -140,7 +140,7 @@ internal static class CheckForEndVotingPatch
}
}
if (ps.VotedFor == 254 && !voter.Data.IsDead)
if (ps.VotedFor == 254 && voter.IsAlive())
{
switch (Options.GetWhenNonVote())
{
@@ -160,7 +160,7 @@ internal static class CheckForEndVotingPatch
}
}
if (ps.VotedFor == 254 && !voter.Data.IsDead && voter.Is(CustomRoles.Compelled))
if (ps.VotedFor == 254 && voter.IsAlive() && voter.Is(CustomRoles.Compelled))
TryAddAfterMeetingDeathPlayers(PlayerState.DeathReason.DidntVote, ps.TargetPlayerId);
if (CheckRole(ps.TargetPlayerId, CustomRoles.FortuneTeller) && FortuneTeller.HideVote.GetBool()) continue;
@@ -886,9 +886,9 @@ internal static class MeetingHudStartPatch
roleTextMeeting.enabled =
target.AmOwner ||
(Main.VisibleTasksCount && seer.Data.IsDead && Options.GhostCanSeeOtherRoles.GetBool()) ||
(seer.Is(CustomRoles.Mimic) && Main.VisibleTasksCount && target.Data.IsDead && Options.MimicCanSeeDeadRoles.GetBool()) ||
(target.Is(CustomRoles.Gravestone) && Main.VisibleTasksCount && target.Data.IsDead) ||
(Main.VisibleTasksCount && !seer.IsAlive() && Options.GhostCanSeeOtherRoles.GetBool()) ||
(seer.Is(CustomRoles.Mimic) && Main.VisibleTasksCount && !target.IsAlive() && Options.MimicCanSeeDeadRoles.GetBool()) ||
(target.Is(CustomRoles.Gravestone) && Main.VisibleTasksCount && !target.IsAlive()) ||
(Main.LoversPlayers.TrueForAll(x => x.PlayerId == target.PlayerId || x.PlayerId == seer.PlayerId) && Main.LoversPlayers.Count == 2 && Lovers.LoverKnowRoles.GetBool()) ||
(seer.Is(CustomRoleTypes.Coven) && target.Is(CustomRoleTypes.Coven)) ||
(target.Is(CustomRoleTypes.Impostor) && seer.Is(CustomRoleTypes.Impostor) && Options.ImpKnowAlliesRole.GetBool() && CustomTeamManager.ArentInCustomTeam(seer.PlayerId, target.PlayerId)) ||
@@ -914,7 +914,7 @@ internal static class MeetingHudStartPatch
Main.GodMode.Value;
if (!seer.Data.IsDead && seer.IsRevealedPlayer(target) && target.Is(CustomRoles.Trickster))
if (seer.IsAlive() && seer.IsRevealedPlayer(target) && target.Is(CustomRoles.Trickster))
{
roleTextMeeting.text = Investigator.RandomRole[seer.PlayerId];
roleTextMeeting.text += Investigator.GetTaskState();
@@ -1086,7 +1086,7 @@ internal static class MeetingHudStartPatch
case CustomRoles.Revolutionist when seer.IsDrawPlayer(target):
sb.Append(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Revolutionist), "●"));
break;
case CustomRoles.Psychic when Psychic.IsRedForPsy(target, seer) && !seer.Data.IsDead:
case CustomRoles.Psychic when Psychic.IsRedForPsy(target, seer) && seer.IsAlive():
pva.NameText.text = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Impostor), pva.NameText.text);
break;
case CustomRoles.Demon:
@@ -1101,7 +1101,7 @@ internal static class MeetingHudStartPatch
if (Silencer.ForSilencer.Contains(target.PlayerId))
sb.Append(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Silencer), "╳"));
if (Main.LoversPlayers.Exists(x => x.PlayerId == target.PlayerId) && (Main.LoversPlayers.Exists(x => x.PlayerId == seer.PlayerId) || seer.Data.IsDead))
if (Main.LoversPlayers.Exists(x => x.PlayerId == target.PlayerId) && (Main.LoversPlayers.Exists(x => x.PlayerId == seer.PlayerId) || !seer.IsAlive()))
sb.Append(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Lovers), "♥"));
sb.Append(Executioner.TargetMark(seer, target));
@@ -1122,7 +1122,7 @@ internal static class MeetingHudStartPatch
if (seer.Is(CustomRoles.Medic) && (Medic.InProtect(target.PlayerId) || Medic.TempMarkProtectedList.Contains(target.PlayerId)) && Medic.WhoCanSeeProtect.GetInt() is 0 or 1)
sb.Append(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Medic), " ●"));
if (seer.Data.IsDead && Medic.InProtect(target.PlayerId) && !seer.Is(CustomRoles.Medic))
if (!seer.IsAlive() && Medic.InProtect(target.PlayerId) && !seer.Is(CustomRoles.Medic))
sb.Append(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Medic), " ●"));
sb.Append(Follower.TargetMark(seer, target));
@@ -1206,7 +1206,7 @@ internal static class MeetingHudUpdatePatch
{
PlayerControl player = Utils.GetPlayerById(x.TargetPlayerId);
if (player != null && !player.Data.IsDead)
if (player != null && player.IsAlive())
{
Main.PlayerStates[player.PlayerId].deathReason = PlayerState.DeathReason.Execution;
player.RpcExileV2();
@@ -1381,6 +1381,12 @@ internal static class MeetingHudCastVotePatch
skip = true;
}
if (!pcSrc.IsAlive())
{
ShouldCancelVoteList.TryAdd(srcPlayerId, (__instance, pvaSrc, pcSrc));
return false;
}
var voteCanceled = false;
if (!Main.DontCancelVoteList.Contains(srcPlayerId) && !skip && pcSrc.GetCustomRole().CancelsVote() && !pcSrc.UsesMeetingShapeshift() && Main.PlayerStates[srcPlayerId].Role.OnVote(pcSrc, pcTarget))
+1 -1
View File
@@ -105,7 +105,7 @@ public static class PhantomRoleUseAbilityPatch
{
if (!AmongUsClient.Instance.AmHost || !HudManager.InstanceExists) return true;
if (__instance.Player.AmOwner && !__instance.Player.Data.IsDead && __instance.Player.moveable && !Minigame.Instance && !__instance.IsCoolingDown && !__instance.fading)
if (__instance.Player.AmOwner && !__instance.Player.Data.IsDead && __instance.Player.IsAlive() && __instance.Player.moveable && !Minigame.Instance && !__instance.IsCoolingDown && !__instance.fading)
{
bool RoleEffectAnimation(RoleEffectAnimation x) => x.effectType == global::RoleEffectAnimation.EffectType.Vanish_Charge;
+3 -3
View File
@@ -24,7 +24,7 @@ internal static class CheckProtectPatch
{
public static bool Prefix(PlayerControl __instance, [HarmonyArgument(0)] PlayerControl target)
{
if (!AmongUsClient.Instance.AmHost || target.Data.IsDead) return false;
if (!AmongUsClient.Instance.AmHost || target.Data.IsDead || !target.IsAlive()) return false;
Logger.Info($"CheckProtect: {__instance.GetNameWithRole().RemoveHtmlTags()} => {target.GetNameWithRole().RemoveHtmlTags()}", "CheckProtect");
@@ -990,7 +990,7 @@ internal static class ReportDeadBodyPatch
try
{
// If the caller is dead, this process will cancel the meeting, so stop here.
if (__instance.Data.IsDead) return false;
if (__instance.Data.IsDead || !__instance.IsAlive()) return false;
//=============================================
// Next, check whether this meeting is allowed
@@ -1378,7 +1378,7 @@ internal static class ReportDeadBodyPatch
if (Main.CheckShapeshift.ContainsKey(pc.PlayerId))
pc.RpcShapeshift(pc, false);
}
else if (!pc.Data.IsDead)
else if (!pc.Data.IsDead && (!pc.AmOwner || !TempReviveHostRunning))
pc.RpcExileV2();
}
catch (Exception e) { ThrowException(e); }
+8 -8
View File
@@ -2,7 +2,7 @@
"LanguageID": "0",
"TextBelowVersionText": "",
"HostText": "مضيف - EHR",
"IconColor": "",
"IconColor": "00a5ff",
"HostColor": "#00ffa5",
"Icon": " | ",
"NameColor": "#00ffff",
@@ -59,19 +59,19 @@
"ROT.Impostor_Killing": "★ الأدوار القاتلة",
"ROT.Impostor_Support": "★ الأدوار الداعمة",
"ROT.Impostor_Concealing": "أدوار الإخفاء",
"ROT.Impostor_Miscellaneous": "★ Miscellaneous Roles",
"ROT.Impostor_Miscellaneous": "أدوار متنوعة",
"ROT.Impostor_Madmate": "ادوار الطاقم الغاضب",
"ROT.Crewmate_Investigate": "★ أدوار التحقق",
"ROT.Crewmate_Support": "★ أدوار الدعم",
"ROT.Crewmate_Power": "★ أدوار القوة",
"ROT.Crewmate_Killing": "★ الأدوار القاتلة",
"ROT.Crewmate_Chaos": "★ أدوار الفوضى",
"ROT.Crewmate_Miscellaneous": "★ Miscellaneous Roles",
"ROT.Crewmate_Miscellaneous": "أدوار متنوعة",
"ROT.Neutral_Evil": "★ الأدوار الشريرة",
"ROT.Neutral_Pariah": "★ Pariah Roles",
"ROT.Neutral_Benign": "★ Benign Roles",
"ROT.Neutral_Killing": "★ الأدوار القاتلة",
"ROT.Coven_Miscellaneous": "★ Miscellaneous Roles",
"ROT.Coven_Miscellaneous": "أدوار متنوعة",
"ROT.Vanilla": "★ Vanilla Roles",
"ROT.Basic": "★ الأدوار العادية",
"ROT.AddonType.ImpOnly": "★ زوائد المحتال-فقط",
@@ -121,8 +121,8 @@
"RoleSubCategoryLimitOptions.Neutral_Pariah.Max": "Maximum Neutral Pariah Roles",
"RoleSubCategoryLimitOptions.Neutral_Benign.Min": "Minimum Neutral Benign Roles",
"RoleSubCategoryLimitOptions.Neutral_Benign.Max": "Maximum Neutral Benign Roles",
"RoleSubCategoryLimitOptions.Neutral_Killing.Min": "Minimum Neutral Killing Roles",
"RoleSubCategoryLimitOptions.Neutral_Killing.Max": "Maximum Neutral Killing Roles",
"RoleSubCategoryLimitOptions.Neutral_Killing.Min": "أدنى حد للأدوار القاتلين المحايدين",
"RoleSubCategoryLimitOptions.Neutral_Killing.Max": "أقصى حد للأدوار القاتلين المحايدين",
"FactionLimits.Impostor.Min": "<#00ffa5>Minimum</color> <#ffffff>amount of</color> Impostor Roles",
"FactionLimits.Impostor.Max": "<#00a5ff>Maximum</color> <#ffffff>amount of</color> Impostor Roles",
"FactionLimits.Neutral.Min": "<#00ffa5>Minimum</color> <#ffffff>amount of</color> Neutral Roles",
@@ -10232,7 +10232,7 @@
"EnableAutoFactionMinMaxSettings": "Enable Automatic Team Size Adjustment Based on Player Count",
"AutoFactionMinMaxSettings.PlayerCap": "Minimum Player Threshold for These Settings to Apply (0 = unused)",
"AutoFactionMinMaxSettings.Applied": "[Auto Team Sizes] {0} players (>={1}) = {2} (<#ffff00>NNK</color>: <#ffffff>{3}-{4}</color>)",
"GMPoll.Allow": "Show {gm} in /gmpoll choices",
"GMPoll.Allow": "عرض {gm} في خيارات /gmpoll",
"MPoll.Allow": "Show {m} in /mpoll choices",
"MenuTitle.GMPoll": "Game Mode Poll",
"MenuTitle.MPoll": "Map Poll",
@@ -10268,6 +10268,6 @@
"Hungarian": "Hungarian",
"Polish": "Polish",
"Indonesian": "Indonesian",
"Persian": "Persian",
"Persian": "الفارسية",
"NotAssigned": "-"
}
+2 -4
View File
@@ -32,11 +32,9 @@ public abstract class CovenBase : RoleBase
LateTask.New(() =>
{
var sender = CustomRpcSender.Create("CovenGiveNecronomicon", SendOption.Reliable);
string[] holders = Main.PlayerStates.Where(s => s.Value.Role is CovenBase { HasNecronomicon: true }).Select(s => s.Key.ColoredPlayerName()).ToArray();
Main.AllPlayerControls.Where(x => x.Is(Team.Coven)).Select(x => x.PlayerId).Without(receiver.Key).Do(x => sender = Utils.SendMessage("\n", x, string.Format(Translator.GetString("PlayerReceivedTheNecronomicon"), receiver.Key.ColoredPlayerName(), Main.CovenColor, holders.Length, string.Join(", ", holders)), writer: sender, multiple: true));
sender = Utils.SendMessage("\n", receiver.Key, string.Format(Translator.GetString("YouReceivedTheNecronomicon"), Main.CovenColor), writer: sender, multiple: true);
sender.SendMessage(dispose: sender.stream.Length <= 3);
Main.AllPlayerControls.Where(x => x.Is(Team.Coven)).Select(x => x.PlayerId).Without(receiver.Key).Do(x => Utils.SendMessage("\n", x, string.Format(Translator.GetString("PlayerReceivedTheNecronomicon"), receiver.Key.ColoredPlayerName(), Main.CovenColor, holders.Length, string.Join(", ", holders))));
Utils.SendMessage("\n", receiver.Key, string.Format(Translator.GetString("YouReceivedTheNecronomicon"), Main.CovenColor));
}, 12f, log: false);
}
+1 -1
View File
@@ -100,7 +100,7 @@ public class Disperser : RoleBase
foreach (PlayerControl pc in PlayerControl.AllPlayerControls)
{
if (player.PlayerId == pc.PlayerId || pc.Data.IsDead || pc.onLadder || pc.inMovingPlat || pc.inVent || GameStates.IsMeeting)
if (player.PlayerId == pc.PlayerId || pc.Data.IsDead || !pc.IsAlive() || pc.onLadder || pc.inMovingPlat || pc.inVent || GameStates.IsMeeting)
{
if (!pc.Is(CustomRoles.Disperser)) pc.Notify(ColorString(GetRoleColor(CustomRoles.Disperser), string.Format(GetString("ErrorTeleport"), pc.GetRealName())));
continue;
@@ -193,7 +193,7 @@ internal class Revolutionist : RoleBase
}
}
if (GameStates.IsInTask && player.IsDrawDone() && player.IsAlive() && !player.Data.IsDead)
if (GameStates.IsInTask && player.IsDrawDone() && player.IsAlive() && player.IsAlive())
{
if (RevolutionistStart.TryGetValue(playerId, out var start))
{