fixes & optimizations

This commit is contained in:
Gurge44 committed 2025-04-19 13:03:15 +02:00
1 parent 115efb42ab
commit ae3016df6b
12 files changed
+130 -58

No files matched your search

-3
View File
@@ -12,7 +12,6 @@ namespace EHR;
public static class AntiBlackout
{
public static int ExilePlayerId = -1;
public static bool SkipTasks;
private static Dictionary<byte, (bool IsDead, bool Disconnected)> IsDeadCache = [];
private static readonly LogHandler Logger = EHR.Logger.Handler("AntiBlackout");
@@ -354,7 +353,6 @@ public static class AntiBlackout
public static void ResetAfterMeeting()
{
SkipTasks = false;
ExilePlayerId = -1;
ResetAllCooldowns();
}
@@ -364,7 +362,6 @@ public static class AntiBlackout
IsDeadCache ??= [];
IsDeadCache.Clear();
IsCached = false;
ExilePlayerId = -1;
SkipTasks = false;
}
}
+3
View File
@@ -536,6 +536,9 @@ internal static class RPCHandlerPatch
PlayerControl player = reader.ReadByte().GetPlayer();
string text = reader.ReadString();
var modCommands = ChatCommands.AllCommands.Where(x => x.UsageLevel == Command.UsageLevels.HostOrModerator).Select(x => x.CommandForms[0]).Select(x => $"{char.ToUpper(x[0])}{x[1..]}Command").ToList();
if (modCommands.Contains(methodName) && !ChatCommands.IsPlayerModerator(player.FriendCode)) break;
const BindingFlags flags = BindingFlags.Static | BindingFlags.NonPublic;
typeof(ChatCommands).GetMethod(methodName, flags)?.Invoke(null, [player, text, text.Split(' ')]);
Logger.Info($"Invoke Command: {methodName} ({player?.Data?.PlayerName}, {text})", "RequestCommandProcessing");
+1 -1
View File
@@ -210,7 +210,7 @@ public static class Statistics
{
PlayerControl voteTarget = lpVS.VotedForId.GetPlayer();
if (!voteTarget.IsCrewmate() && !voteTarget.IsConverted())
if (voteTarget != null && !voteTarget.IsCrewmate() && !voteTarget.IsConverted())
OnlyVotingForKillersAsCrew = false;
}
+31 -8
View File
@@ -1332,7 +1332,8 @@ public static class Utils
}
}
new List<Message> {
new List<Message>
{
new($"<size=80%>{sb.Append("\n.").ToString().RemoveHtmlTags()}</size>", PlayerId, GetString("GMRoles")),
new($"<size=80%>{impsb.Append("\n.").ToString().RemoveHtmlTags()}</size>", PlayerId, ColorString(GetRoleColor(CustomRoles.Impostor), GetString("ImpostorRoles"))),
new($"<size=80%>{crewsb.Append("\n.").ToString().RemoveHtmlTags()}</size>", PlayerId, ColorString(GetRoleColor(CustomRoles.Crewmate), GetString("CrewmateRoles"))),
@@ -1742,14 +1743,15 @@ public static class Utils
return writer;
}
int targetClientId = receiver.GetClientId();
if (sendTo != byte.MaxValue)
{
writer ??= CustomRpcSender.Create("Utils.SendMessage", sendOption);
if (writer.CurrentState == CustomRpcSender.State.Ready) writer.StartMessage(receiver.GetClientId());
if (!noSplit)
{
writer.StartRpc(sender.NetId, (byte)RpcCalls.SetName)
writer.AutoStartRpc(sender.NetId, (byte)RpcCalls.SetName, targetClientId)
.Write(sender.Data.NetId)
.Write(title)
.EndRpc();
@@ -1789,7 +1791,7 @@ public static class Utils
if (shortenedText.Length > 0) SendMessage(shortenedText, sendTo, title, true, writer, true, sendOption: sendOption);
else if (writer != null && sendTo != byte.MaxValue && writer.CurrentState == CustomRpcSender.State.InRootMessage)
{
writer.StartRpc(sender.NetId, (byte)RpcCalls.SetName)
writer.AutoStartRpc(sender.NetId, (byte)RpcCalls.SetName, targetClientId)
.Write(sender.Data.NetId)
.Write(sender.Data.PlayerName)
.EndRpc();
@@ -1816,13 +1818,13 @@ public static class Utils
if (sendTo == byte.MaxValue) Main.MessagesToSend.Add((text, sendTo, title));
else
{
writer.StartRpc(sender.NetId, (byte)RpcCalls.SendChat)
writer.AutoStartRpc(sender.NetId, (byte)RpcCalls.SendChat, targetClientId)
.Write(text)
.EndRpc();
if ((noSplit && final) || !noSplit)
{
writer.StartRpc(sender.NetId, (byte)RpcCalls.SetName)
writer.AutoStartRpc(sender.NetId, (byte)RpcCalls.SetName, targetClientId)
.Write(sender.Data.NetId)
.Write(sender.Data.PlayerName)
.EndRpc();
@@ -1845,7 +1847,6 @@ public static class Utils
{
writer.SendMessage();
writer = CustomRpcSender.Create("Utils.SendMessage", sendOption);
writer.StartMessage(receiver.GetClientId());
}
}
}
@@ -2423,6 +2424,26 @@ public static class Utils
sender.RpcSetName(seer, SelfName, seer);
bool onlySelfNameUpdateRequired = Options.CurrentGameMode switch
{
CustomGameMode.Standard => false,
CustomGameMode.SoloKombat => false,
CustomGameMode.FFA => !FreeForAll.FFATeamMode.GetBool(),
CustomGameMode.MoveAndStop => true,
CustomGameMode.HotPotato => false,
CustomGameMode.HideAndSeek => false,
CustomGameMode.Speedrun => false,
CustomGameMode.CaptureTheFlag => true,
CustomGameMode.NaturalDisasters => true,
CustomGameMode.RoomRush => true,
CustomGameMode.KingOfTheZones => true,
CustomGameMode.Quiz => true,
CustomGameMode.AllInOne => false,
_ => false
};
if (onlySelfNameUpdateRequired) return;
// Run the second loop only when necessary, such as when seer is dead
if (seer.Data.IsDead || !seer.IsAlive() || noCache || camouflageIsForMeeting || mushroomMixup || IsActive(SystemTypes.MushroomMixupSabotage) || forceLoop || seerList.Length == 1 || targetList.Length == 1)
{
@@ -2963,7 +2984,9 @@ public static class Utils
else
{
TaskState taskState = pc.GetTaskState();
if (pc.IsCrewmate() && !taskState.IsTaskFinished && taskState.HasTasks) pc.Notify(GetString("DoYourTasksPlease"), 8f);
if (pc.IsCrewmate() && !taskState.IsTaskFinished && taskState.HasTasks)
pc.Notify(GetString("DoYourTasksPlease"), 8f);
GhostRolesManager.NotifyAboutGhostRole(pc);
}
+23 -16
View File
@@ -44,7 +44,7 @@ internal class Command(string[] commandForms, string arguments, string descripti
public string Arguments => arguments;
public string Description => description;
public string[] ArgsDescriptions => argsDescriptions ?? [];
private UsageLevels UsageLevel => usageLevel;
public UsageLevels UsageLevel => usageLevel;
private UsageTimes UsageTime => usageTime;
public Action<PlayerControl, string, string[]> Action => action;
public bool IsCanceled => isCanceled;
@@ -68,7 +68,7 @@ internal class Command(string[] commandForms, string arguments, string descripti
{
case UsageLevels.Host when !pc.IsHost():
case UsageLevels.Modded when !pc.IsModdedClient():
case UsageLevels.HostOrModerator when !pc.IsHost() && !ChatCommands.IsPlayerModerator(pc.FriendCode):
case UsageLevels.HostOrModerator when !pc.IsHost() && (AmongUsClient.Instance.AmHost && !ChatCommands.IsPlayerModerator(pc.FriendCode)):
return false;
}
@@ -152,7 +152,7 @@ internal static class ChatCommands
new(["target", "цель", "腹语者标记", "alvo"], "{id}", GetString("CommandDescription.Target"), Command.UsageLevels.Everyone, Command.UsageTimes.InMeeting, TargetCommand, true, true, [GetString("CommandArgs.Target.Id")]),
new(["chat", "сообщение", "腹语者发送消息"], "{message}", GetString("CommandDescription.Chat"), Command.UsageLevels.Everyone, Command.UsageTimes.InMeeting, ChatCommand, true, true, [GetString("CommandArgs.Chat.Message")]),
new(["check", "проверить", "检查", "veificar"], "{id} {role}", GetString("CommandDescription.Check"), Command.UsageLevels.Everyone, Command.UsageTimes.InMeeting, CheckCommand, true, true, [GetString("CommandArgs.Check.Id"), GetString("CommandArgs.Check.Role")]),
new(["ban", "kick", "бан", "кик", "забанить", "кикнуть", "封禁", "踢出", "banir", "expulsar"], "{id}", GetString("CommandDescription.Ban"), Command.UsageLevels.HostOrModerator, Command.UsageTimes.Always, BanKickCommand, true, false, [GetString("CommandArgs.Ban.Id")]),
new(["ban", "kick", "бан", "кик", "забанить", "кикнуть", "封禁", "踢出", "banir", "expulsar"], "{id}", GetString("CommandDescription.Ban"), Command.UsageLevels.HostOrModerator, Command.UsageTimes.Always, BanCommand, true, false, [GetString("CommandArgs.Ban.Id")]),
new(["exe", "выкинуть", "驱逐", "executar"], "{id}", GetString("CommandDescription.Exe"), Command.UsageLevels.Host, Command.UsageTimes.Always, ExeCommand, true, false, [GetString("CommandArgs.Exe.Id")]),
new(["kill", "убить", "击杀", "matar"], "{id}", GetString("CommandDescription.Kill"), Command.UsageLevels.Host, Command.UsageTimes.Always, KillCommand, true, false, [GetString("CommandArgs.Kill.Id")]),
new(["colour", "color", "цвет", "更改颜色", "cor"], "{color}", GetString("CommandDescription.Colour"), Command.UsageLevels.Everyone, Command.UsageTimes.InLobby, ColorCommand, true, false, [GetString("CommandArgs.Colour.Color")]),
@@ -337,7 +337,17 @@ internal static class ChatCommands
__instance.freeChatField.textArea.Clear();
__instance.freeChatField.textArea.SetText(cancelVal);
}
else ChatManager.SendMessage(PlayerControl.LocalPlayer, text);
else
{
if (GameStates.IsLobby)
{
Utils.ApplySuffix(PlayerControl.LocalPlayer, out string name);
Utils.SendMessage(text, title: name);
canceled = true;
}
ChatManager.SendMessage(PlayerControl.LocalPlayer, text);
}
if (text.Contains("666") && PlayerControl.LocalPlayer.Is(CustomRoles.Gamer))
Achievements.Type.WhatTheHell.Complete();
@@ -846,14 +856,14 @@ internal static class ChatCommands
for (var index = 0; index < 3; index++)
{
List<Message> messages = [];
foreach ((byte id, List<CustomRoles> roles) in DraftRoles)
{
IEnumerable<string> roleList = roles.Select((x, i) => $"{i + 1}. {x.ToColoredString()}");
string msg = string.Format(GetString(index == 0 ? "DraftStart" : "DraftResend"), string.Join('\n', roleList));
messages.Add(new Message(msg, id, GetString("DraftTitle")));
}
messages.SendMultipleMessages(index == 0 ? SendOption.Reliable : SendOption.None);
yield return new WaitForSeconds(20f);
@@ -1143,13 +1153,13 @@ internal static class ChatCommands
{
if (PollVotes.Count == 0) yield break;
bool playervoted = Main.AllPlayerControls.Length - 1 > PollVotes.Values.Sum();
bool notEveryoneVoted = Main.AllPlayerControls.Length - 1 > PollVotes.Values.Sum();
var resendTimer = 0f;
while (playervoted && PollTimer > 0f)
while ((notEveryoneVoted || gmPoll) && PollTimer > 0f)
{
playervoted = Main.AllPlayerControls.Length - 1 > PollVotes.Values.Sum();
notEveryoneVoted = Main.AllPlayerControls.Length - 1 > PollVotes.Values.Sum();
PollTimer -= Time.deltaTime;
resendTimer += Time.deltaTime;
@@ -1183,11 +1193,8 @@ internal static class ChatCommands
if (winners.Length == 1 && gmPoll)
{
int modeIndex = winners[0].Key - 65;
StringOption gmOption = GameSettingMenuPatch.GameModeBehaviour;
gmOption.Value = modeIndex;
gmOption.UpdateValue();
gmOption.OnValueChanged?.Invoke(gmOption);
int winnerIndex = winners[0].Key - 65;
if (winnerIndex != 0) Options.GameMode.SetValue(winnerIndex - 1);
}
}
@@ -1528,11 +1535,11 @@ internal static class ChatCommands
}
}
private static void BanKickCommand(PlayerControl player, string text, string[] args)
private static void BanCommand(PlayerControl player, string text, string[] args)
{
if (!AmongUsClient.Instance.AmHost)
{
RequestCommandProcessingFromHost(nameof(BanKickCommand), text);
RequestCommandProcessingFromHost(nameof(BanCommand), text);
return;
}
+10 -1
View File
@@ -178,14 +178,23 @@ internal static class ExileControllerWrapUpPatch
text = $"<#ffffff>{text}</color>";
var r = IRandom.Instance;
var sender = CustomRpcSender.Create("ExileControllerWrapUpPatch.WrapUpFinalizer - 2", SendOption.Reliable);
var hasValue = false;
foreach (PlayerControl pc in Main.AllAlivePlayerControls)
{
string finalText = ejectionNotify ? CheckForEndVotingPatch.EjectionText.Trim() : text;
sender.Notify(pc, finalText, r.Next(7, 13));
hasValue = true;
if (sender.stream.Length > 800)
{
sender.SendMessage();
sender = CustomRpcSender.Create("ExileControllerWrapUpPatch.WrapUpFinalizer - 2", SendOption.Reliable);
hasValue = false;
}
}
sender.SendMessage();
sender.SendMessage(dispose: !hasValue);
}
LateTask.New(() => ChatManager.SendPreviousMessagesToAll(true), 3f, log: false);
+11 -9
View File
@@ -9,7 +9,7 @@ using HarmonyLib;
using Il2CppSystem.Collections.Generic;
using TMPro;
using UnityEngine;
using Type = Il2CppSystem.Type;
// ReSharper disable PossibleLossOfFraction
namespace EHR;
@@ -721,10 +721,10 @@ public static class StringOptionPatch
GameObject.Find("PlayerOptionsMenu(Clone)").transform.FindChild("What Is This?").gameObject.SetActive(true);
GameSettingMenuPatch.GMButtons.ForEach(x => x.gameObject.SetActive(false));
var info = $"{value.ToColoredString()}: {infoLong}";
GameSettingMenu.Instance.MenuDescriptionText.text = info;
LateTask.New(() =>
{
GameObject gameObject = GameObject.Find("PlayerOptionsMenu(Clone)");
@@ -734,7 +734,7 @@ public static class StringOptionPatch
Transform findChild = gameObject.transform.FindChild("What Is This?");
if (findChild != null) findChild.gameObject.SetActive(false);
}
GameSettingMenuPatch.GMButtons.ForEach(x => x.gameObject.SetActive(true));
}, 15f, log: false);
}
@@ -888,7 +888,7 @@ public static class StringOptionPatch
public static class GameSettingMenuPatch
{
public static System.Collections.Generic.List<GameObject> GMButtons = [];
private static readonly Vector3 ButtonPositionLeft = new(-3.9f, -0.4f, 0f);
private static readonly Vector3 ButtonPositionRight = new(-2.4f, -0.4f, 0f);
@@ -1068,12 +1068,12 @@ public static class GameSettingMenuPatch
GameObject.Find("PlayerOptionsMenu(Clone)").transform.FindChild("What Is This?").gameObject.SetActive(false);
var gameSettingsLabel = __instance.GameSettingsButton.transform.parent.parent.FindChild("GameSettingsLabel").GetComponent<TextMeshPro>();
gameSettingsLabel.DestroyTranslator();
gameSettingsLabel.text = $"<size=50%>{Translator.GetString($"Mode{Options.CurrentGameMode}")}</size>\n";
gameSettingsLabel.transform.localPosition += new Vector3(0f, 0.1f, 0f);
if (russian)
{
gameSettingsLabel.transform.localScale = new(0.7f, 0.7f, 1f);
@@ -1107,7 +1107,7 @@ public static class GameSettingMenuPatch
for (var index = 0; index < gms.Length; index++)
{
CustomGameMode gm = gms[index];
var gmButton = Object.Instantiate(gMinus, gameSettingsLabel.transform, true);
gmButton.transform.localPosition = new Vector3((((index / 7) - ((totalCols - 1) / 2f)) * 1.4f) + 0.86f, gameSettingsLabelPos.y - 1.9f - (0.22f * (index % 7)), -1f);
@@ -1129,7 +1129,7 @@ public static class GameSettingMenuPatch
LateTask.New(() => GameObject.Find("PlayerOptionsMenu(Clone)").transform.FindChild("What Is This?").gameObject.SetActive(false), 0.02f);
}));
gmPassiveButton.activeTextColor = gmPassiveButton.inactiveTextColor = gmPassiveButton.disabledTextColor = gmPassiveButton.selectedTextColor = gmColors[gm];
GMButtons.Add(gmButton);
}
@@ -1336,9 +1336,11 @@ public static class GameSettingMenuPatch
{
foreach (PassiveButton button in ModSettingsButtons.Values) Object.Destroy(button);
foreach (GameOptionsMenu tab in ModSettingsTabs.Values) Object.Destroy(tab);
foreach (GameObject button in GMButtons) Object.Destroy(button);
ModSettingsButtons = [];
ModSettingsTabs = [];
GMButtons = [];
if ((CustomGameMode.NaturalDisasters.IsActiveOrIntegrated() || CustomGameMode.CaptureTheFlag.IsActiveOrIntegrated()) && GameStates.CurrentServerType == GameStates.ServerType.ModdedWithoutCNOSupport && GameOptionsMenuPatch.UIReloadTS + 1 < Utils.TimeStamp)
FastDestroyableSingleton<HudManager>.Instance.ShowPopUp(Translator.GetString("ModdedServerDoesntSupportCNOMessage"));
+4 -10
View File
@@ -78,7 +78,6 @@ internal static class CheckForEndVotingPatch
voteTarget.SetRealKiller(pc);
Main.LastVotedPlayerInfo = voteTarget.Data;
AntiBlackout.ExilePlayerId = voteTarget.PlayerId;
if (Main.LastVotedPlayerInfo != null)
ConfirmEjections(Main.LastVotedPlayerInfo, false);
@@ -326,13 +325,8 @@ internal static class CheckForEndVotingPatch
exiledPlayer?.Object.SetRealKiller(null);
Main.LastVotedPlayerInfo = exiledPlayer;
AntiBlackout.ExilePlayerId = exileId;
if (Main.LastVotedPlayerInfo != null)
{
AntiBlackout.ExilePlayerId = exileId;
ConfirmEjections(Main.LastVotedPlayerInfo, braked);
}
if (Main.LastVotedPlayerInfo != null) { ConfirmEjections(Main.LastVotedPlayerInfo, braked); }
__instance.RpcVotingComplete(states.ToArray(), exiledPlayer, tie);
@@ -364,7 +358,7 @@ internal static class CheckForEndVotingPatch
string realName = exiledPlayer.Object.GetRealName(true);
PlayerControl player = Utils.GetPlayerById(exiledPlayer.PlayerId);
PlayerControl player = exiledPlayer.Object;
CustomRoles crole = exiledPlayer.GetCustomRole();
string coloredRole = Utils.GetDisplayRoleName(exileId, true, true);
@@ -670,7 +664,7 @@ internal static class MeetingHudStartPatch
if (Options.SendRoleDescriptionFirstMeeting.GetBool() && MeetingStates.FirstMeeting && Options.CurrentGameMode == CustomGameMode.Standard)
{
List<Message> roleDescMsgs = [];
foreach (PlayerControl pc in Main.AllAlivePlayerControls)
{
if (pc.IsModdedClient()) continue;
@@ -705,7 +699,7 @@ internal static class MeetingHudStartPatch
roleDescMsgs.Add(new(sb.Append("</size>").ToString(), pc.PlayerId, titleSb.ToString()));
}
LateTask.New(() => roleDescMsgs.SendMultipleMessages(SendOption.None), 6f, "Send Role Descriptions Round 1");
}
+1 -1
View File
@@ -149,7 +149,7 @@ internal static class TextBoxTMPSetTextPatch
}
string inputForm = input.TrimStart('/');
string text = "/" + (exactMatch ? inputForm : command.CommandForms.Where(x => x.All(char.IsAscii) && x.StartsWith(inputForm)).MaxBy(x => x.Length));
string text = "/" + (exactMatch ? inputForm : command.CommandForms.TakeWhile(x => x.All(char.IsAscii) && x.StartsWith(inputForm)).MaxBy(x => x.Length));
var info = $"<b>{command.Description}</b>";
var additionalInfo = string.Empty;
+4 -4
View File
@@ -2994,7 +2994,7 @@
"Preset_10": "Preset 10",
"YouAreHostSuffix": "YOU!",
"Standard": "Standard",
"SoloKombat": "Solo PVP",
"SoloKombat": "SOLO PVP",
"ModeSoloKombat": "Gamemode: Solo PVP",
"GameMode": "Game Mode",
"PressTabToNextPage": "Press <color=#ff1919>Tab</color> or <color=#ff1919>Number</color> for Next Page...",
@@ -4635,7 +4635,7 @@
"GameModeTutorial.NaturalDisasters": "<size=90%>The current game mode is <#03fc4a>Natural Disasters</color>.</size>\\n<size=80%>Various disasters will constantly spawn on the map.\\nSome kill you instantly, some just debuff you temporarily.\\nBe the last player alive to win!</size>",
"GameModeListTitle": "Game Modes",
"ModeStandard": "Gamemode: Standard",
"FFA": "Free For All",
"FFA": "FREE FOR ALL",
"ModeFFA": "Gamemode: FFA",
"ModeDescribe.FFA": "In the FFA (Free For All) gamemode, everyone is a killer and everyone can kill anyone. The last player alive wins!\\n\\nSome random events make this even more fun in the mean time!",
"FFA_GameTime": "Maximum Game Length",
@@ -8692,8 +8692,8 @@
"AgitaterPassCooldown": "Bomb pass cooldown",
"BombExplodeCooldown": "Bomb explode cooldown",
"AgitaterPassNotify": "Bomb successfully passed",
"AgitaterTargetNotify": "YOU HAVE THE BOMB!! Pass it to someone else",
"AgitaterCanGetBombed": "<color=#F4A460>Agitator</color> can get bomb",
"AgitaterTargetNotify": "<size=110%><#ffff00>YOU HAVE THE BOMB!!</color>\\n<#ffa500>Pass it to someone else or die!</color></size>",
"AgitaterCanGetBombed": "<color=#F4A460>Agitator</color> can get the bomb",
"AgitaterAutoReportBait": "<color=#F4A460>Agitator</color> Auto Report Bait",
"Cleansed": "Cleansed",
"CleansedInfo": "Your add-ons were cleansed",
+41 -4
View File
@@ -3,6 +3,7 @@ using System.Collections;
using System.Collections.Generic;
using System.Linq;
using AmongUs.GameOptions;
using Hazel;
using UnityEngine;
using static EHR.Options;
@@ -58,6 +59,7 @@ internal class TimeMaster : RoleBase
public override void Init()
{
On = false;
Rewinding = false;
}
public override void ApplyGameOptions(IGameOptions opt, byte playerId)
@@ -108,29 +110,49 @@ internal class TimeMaster : RoleBase
ReportDeadBodyPatch.CanReport.SetAllValues(false);
string notify = Utils.ColorString(Color.yellow, string.Format(Translator.GetString("TimeMasterRewindStart"), CustomRoles.TimeMaster.ToColoredString()));
var sender = CustomRpcSender.Create("TimeMaster.Rewind", SendOption.Reliable);
var hasValue = false;
foreach (PlayerControl player in Main.AllPlayerControls)
{
player.ReactorFlash(flashDuration: length * delay);
player.Notify(notify, Math.Max(length * delay, 4f));
sender.Notify(player, notify, Math.Max(length * delay, 4f));
player.MarkDirtySettings();
hasValue = true;
if (sender.stream.Length > 800)
{
sender.SendMessage();
sender = CustomRpcSender.Create("TimeMaster.Rewind", SendOption.Reliable);
hasValue = false;
}
}
sender.SendMessage(dispose: !hasValue);
for (long i = now - 1; i >= now - length; i--)
{
if (!BackTrack.TryGetValue(i, out Dictionary<byte, Vector2> track)) continue;
sender = CustomRpcSender.Create("TimeMaster.Rewind - 2", SendOption.Reliable);
hasValue = false;
foreach ((byte playerId, Vector2 pos) in track)
{
PlayerControl player = playerId.GetPlayer();
if (player == null || !player.IsAlive()) continue;
player.TP(pos);
hasValue |= sender.TP(player, pos);
}
sender.SendMessage(dispose: !hasValue);
yield return new WaitForSeconds(delay);
}
sender = CustomRpcSender.Create("TimeMaster.Rewind - 3", SendOption.Reliable);
hasValue = false;
foreach (DeadBody deadBody in Object.FindObjectsOfType<DeadBody>())
{
if (!Main.PlayerStates.TryGetValue(deadBody.ParentId, out PlayerState ps)) continue;
@@ -138,11 +160,21 @@ internal class TimeMaster : RoleBase
if (ps.RealKiller.TimeStamp.AddSeconds(length) >= DateTime.Now)
{
ps.Player.RpcRevive();
ps.Player.TP(deadBody.TruePosition);
ps.Player.Notify(Translator.GetString("RevivedByTimeMaster"), 15f);
sender.TP(ps.Player, deadBody.TruePosition);
sender.Notify(ps.Player, Translator.GetString("RevivedByTimeMaster"), 15f);
hasValue = true;
if (sender.stream.Length > 800)
{
sender.SendMessage();
sender = CustomRpcSender.Create("TimeMaster.Rewind - 3", SendOption.Reliable);
hasValue = false;
}
}
}
sender.SendMessage(dispose: !hasValue);
Main.AllPlayerSpeed.SetAllValues(Main.RealOptionsData.GetFloat(FloatOptionNames.PlayerSpeedMod));
ReportDeadBodyPatch.CanReport.SetAllValues(true);
Utils.MarkEveryoneDirtySettings();
@@ -150,6 +182,11 @@ internal class TimeMaster : RoleBase
finally { Rewinding = false; }
}
public override void AfterMeetingTasks()
{
Rewinding = false;
}
public override void OnFixedUpdate(PlayerControl player)
{
if (GameStates.IsMeeting || ExileController.Instance || !player.IsAlive()) return;
+1 -1
View File
@@ -47,7 +47,7 @@ public abstract class RoleBase : IComparable<RoleBase>
public virtual bool CanUseKillButton(PlayerControl pc)
{
return pc.IsAlive() && (pc.Is(CustomRoleTypes.Impostor) || pc.IsNeutralKiller());
return pc.IsAlive() && (pc.Is(CustomRoleTypes.Impostor) || pc.Is(CustomRoles.Bloodlust) || pc.GetCustomRole().IsNK());
}
public virtual bool CanUseImpostorVentButton(PlayerControl pc)