I can't even count how many things I just fixed

This commit is contained in:
Gurge44 committed 2024-05-08 18:58:19 +02:00
1 parent 9d7bfa93a1
commit be1ec871fe
45 files changed
+522 -474

No files matched your search

+14 -7
View File
@@ -88,8 +88,6 @@ namespace EHR
.Where(x => x.Interface.Team == Team.Impostor)
.Do(x => x.pc.MarkDirtySettings());
}, Seeker.BlindTime.GetFloat() + 8f, "Blind Time Expire");
AssignRoles();
}
public static List<CustomRoles> GetAllHnsRoles(IEnumerable<Type> types)
@@ -109,7 +107,7 @@ namespace EHR
.ToArray();
}
private static void AssignRoles()
public static void AssignRoles()
{
Dictionary<PlayerControl, CustomRoles> result = [];
List<PlayerControl> allPlayers = [.. Main.AllAlivePlayerControls];
@@ -199,6 +197,8 @@ namespace EHR
.Where(x => x != null)
.ToDictionary(x => x.GetType().Name, x => x);
PlayerRoles = result.ToDictionary(x => x.Key.PlayerId, x => (roleInterfaces[x.Value.ToString()], x.Value));
result.IntersectBy(Main.PlayerStates.Keys, x => x.Key.PlayerId).Do(x => x.Key.RpcSetCustomRole(x.Value));
}
public static void ApplyGameOptions(IGameOptions opt, PlayerControl pc)
@@ -343,11 +343,18 @@ namespace EHR
name = Utils.ColorString(Main.PlayerColors.GetValueOrDefault(state.Key, Color.white), name);
bool isSeeker = PlayerRoles[state.Key].Interface.Team == Team.Impostor;
bool alive = !state.Value.IsDead;
string stateText;
if (isSeeker) stateText = $" ({Utils.ColorString(Utils.GetRoleColor(CustomRoles.Seeker), Translator.GetString("Seeker"))})";
else stateText = alive ? string.Empty : " <#ff1313>DEAD</color>";
TaskState ts = state.Value.TaskState;
string stateText = string.Empty;
if (PlayersSeeRoles.GetBool()) stateText = $" ({GetRole()}){GetTaskCount()}";
else if (isSeeker) stateText = $" ({CustomRoles.Seeker.ToString()})";
if (!alive) stateText += $" <color=#ff0000>{Translator.GetString("Dead")}</color>";
stateText = $"{name}{stateText}";
return stateText;
CustomRoles GetRole() => state.Value.MainRole == CustomRoles.Agent ? CustomRoles.Hider : state.Value.MainRole;
string GetTaskCount() => CustomRoles.Agent.IsEnable() || !ts.hasTasks ? string.Empty : $" ({ts.CompletedTasksCount}/{ts.AllTasksCount})";
}
}
@@ -375,7 +382,7 @@ namespace EHR
{
public static void Postfix(PlayerControl __instance)
{
if (!AmongUsClient.Instance.AmHost || Options.CurrentGameMode != CustomGameMode.HideAndSeek) return;
if (!AmongUsClient.Instance.AmHost || !GameStates.IsInTask || Options.CurrentGameMode != CustomGameMode.HideAndSeek) return;
long now = Utils.TimeStamp;
if (LastUpdate == now) return;
+11 -10
View File
@@ -9,6 +9,9 @@ namespace EHR;
public static class AntiBlackout
{
private static Dictionary<byte, (bool isDead, bool Disconnected)> IsDeadCache = [];
private static readonly LogHandler Logger = EHR.Logger.Handler("AntiBlackout");
///<summary>
///Whether to override the ejection process
///</summary>
@@ -44,9 +47,7 @@ public static class AntiBlackout
}
}
public static bool IsCached { get; private set; }
private static Dictionary<byte, (bool isDead, bool Disconnected)> isDeadCache = [];
private static readonly LogHandler Logger = EHR.Logger.Handler("AntiBlackout");
private static bool IsCached { get; set; }
public static void SetIsDead(bool doSend = true, [CallerMemberName] string callerMethodName = "")
{
@@ -57,11 +58,11 @@ public static class AntiBlackout
return;
}
isDeadCache.Clear();
IsDeadCache.Clear();
foreach (var info in GameData.Instance.AllPlayers)
{
if (info == null) continue;
isDeadCache[info.PlayerId] = (info.IsDead, info.Disconnected);
IsDeadCache[info.PlayerId] = (info.IsDead, info.Disconnected);
info.IsDead = false;
info.Disconnected = false;
}
@@ -76,14 +77,14 @@ public static class AntiBlackout
foreach (var info in GameData.Instance.AllPlayers)
{
if (info == null) continue;
if (isDeadCache.TryGetValue(info.PlayerId, out var val))
if (IsDeadCache.TryGetValue(info.PlayerId, out var val))
{
info.IsDead = val.isDead;
info.Disconnected = val.Disconnected;
}
}
isDeadCache.Clear();
IsDeadCache.Clear();
IsCached = false;
if (doSend) SendGameData();
}
@@ -113,7 +114,7 @@ public static class AntiBlackout
{
// Execution conditions: client is host, IsDead is overwritten, player is disconnected
if (!AmongUsClient.Instance.AmHost || !IsCached || !player.Disconnected) return;
isDeadCache[player.PlayerId] = (true, true);
IsDeadCache[player.PlayerId] = (true, true);
player.IsDead = player.Disconnected = false;
SendGameData();
}
@@ -149,8 +150,8 @@ public static class AntiBlackout
public static void Reset()
{
Logger.Info("==Reset==");
isDeadCache ??= [];
isDeadCache.Clear();
IsDeadCache ??= [];
IsDeadCache.Clear();
IsCached = false;
}
}
+6 -17
View File
@@ -78,6 +78,7 @@ internal static class CustomRoleSelector
AssignRoleToEveryone(CustomRoles.Potato);
return;
case CustomGameMode.HideAndSeek:
CustomHideAndSeekManager.AssignRoles();
RoleResult = CustomHideAndSeekManager.PlayerRoles.ToDictionary(x => Utils.GetPlayerById(x.Key), x => x.Value.Role);
return;
}
@@ -611,7 +612,7 @@ internal static class CustomRoleSelector
public static void SelectAddonRoles()
{
if (Options.CurrentGameMode is CustomGameMode.SoloKombat or CustomGameMode.FFA or CustomGameMode.MoveAndStop) return;
if (Options.CurrentGameMode is CustomGameMode.SoloKombat or CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HideAndSeek) return;
foreach (var id in Main.SetAddOns.Keys.Where(id => Utils.GetPlayerById(id) == null).ToArray()) Main.SetAddOns.Remove(id);
@@ -640,25 +641,13 @@ internal static class CustomRoleSelector
Crewmate
}
public class RoleAssignInfo(CustomRoles role, int spawnChance, int maxCount, int assignedCount = 0)
private class RoleAssignInfo(CustomRoles role, int spawnChance, int maxCount, int assignedCount = 0)
{
public CustomRoles Role
{
get => role;
set => role = value;
}
public CustomRoles Role => role;
public int SpawnChance
{
get => spawnChance;
set => spawnChance = value;
}
public int SpawnChance => spawnChance;
public int MaxCount
{
get => maxCount;
set => maxCount = value;
}
public int MaxCount => maxCount;
public int AssignedCount
{
+13 -14
View File
@@ -82,7 +82,7 @@ internal static class CustomRolesHelper
CustomRoles.Lawyer => CustomRoles.Crewmate,
CustomRoles.NiceSwapper => CustomRoles.Crewmate,
CustomRoles.Ignitor => CustomRoles.Crewmate,
CustomRoles.Jailor => CustomRoles.Impostor,
CustomRoles.Jailor => UsePets && Jailor.UsePet.GetBool() ? CustomRoles.Crewmate : CustomRoles.Impostor,
CustomRoles.Vampire => CustomRoles.Impostor,
CustomRoles.BountyHunter => CustomRoles.Impostor,
CustomRoles.Trickster => CustomRoles.Impostor,
@@ -258,9 +258,20 @@ internal static class CustomRolesHelper
CustomRoles.Silencer => Silencer.SilenceMode.GetValue() == 1 ? CustomRoles.Shapeshifter : CustomRoles.Impostor,
// Hide And Seek
CustomRoles.Hider => CustomRoles.Crewmate,
CustomRoles.Seeker => CustomRoles.Impostor,
CustomRoles.Fox => CustomRoles.Crewmate,
CustomRoles.Troll => CustomRoles.Crewmate,
CustomRoles.Jumper => CustomRoles.Engineer,
CustomRoles.Detector => CustomRoles.Crewmate,
CustomRoles.Jet => CustomRoles.Crewmate,
CustomRoles.Dasher => CustomRoles.Impostor,
CustomRoles.Locator => CustomRoles.Impostor,
CustomRoles.Venter => CustomRoles.Impostor,
CustomRoles.Agent => CustomRoles.Impostor,
CustomRoles.Taskinator => CustomRoles.Crewmate,
_ => role.IsImpostor() ? CustomRoles.Impostor : CustomRoles.Crewmate,
_ => role.IsImpostor() ? CustomRoles.Impostor : CustomRoles.Crewmate
};
}
@@ -294,18 +305,6 @@ internal static class CustomRolesHelper
CustomRoles.Tasker => RoleTypes.Crewmate,
// Hot Potato
CustomRoles.Potato => RoleTypes.Crewmate,
// Hide And Seek
CustomRoles.Hider => RoleTypes.Crewmate,
CustomRoles.Seeker => RoleTypes.Impostor,
CustomRoles.Fox => RoleTypes.Crewmate,
CustomRoles.Troll => RoleTypes.Crewmate,
CustomRoles.Detector => RoleTypes.Crewmate,
CustomRoles.Jet => RoleTypes.Crewmate,
CustomRoles.Dasher => RoleTypes.Impostor,
CustomRoles.Locator => RoleTypes.Impostor,
CustomRoles.Venter => RoleTypes.Impostor,
CustomRoles.Agent => RoleTypes.Impostor,
CustomRoles.Taskinator => RoleTypes.Crewmate,
// Standard
CustomRoles.Executioner => Executioner.CRoleChangeRoles[Executioner.ChangeRolesAfterTargetKilled.GetValue()].GetDYRole(),
CustomRoles.Sheriff => UsePets && Sheriff.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
+77 -46
View File
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using AmongUs.GameOptions;
@@ -10,11 +9,11 @@ using static EHR.Translator;
namespace EHR;
internal class EAC
internal static class EAC
{
public static int DeNum;
public static void WarnHost(int denum = 1)
private static void WarnHost(int denum = 1)
{
DeNum += denum;
if (ErrorText.Instance != null)
@@ -120,9 +119,7 @@ internal class EAC
return true;
}
if (pc.Data.DefaultOutfit.ColorId != -1 &&
(Main.AllPlayerControls.Count(x => x.Data.DefaultOutfit.ColorId == color) >= 5
|| color < 0 || color > 18))
if (pc.Data.DefaultOutfit.ColorId != -1 && (Main.AllPlayerControls.Count(x => x.Data.DefaultOutfit.ColorId == color) >= 5 || color > 18))
{
WarnHost();
Report(pc, "Illegal color setting");
@@ -180,12 +177,56 @@ internal class EAC
switch (callId)
{
case 101:
var AUMChat = sr.ReadString();
WarnHost();
Report(pc, "AUM");
HandleCheat(pc, GetString("EAC.CheatDetected.EAC"));
return true;
case 101: // Aum Chat
try
{
var firstString = reader.ReadString();
var secondString = reader.ReadString();
reader.ReadInt32();
var flag = string.IsNullOrEmpty(firstString) && string.IsNullOrEmpty(secondString);
if (!flag)
{
Report(pc, "Aum Chat RPC");
HandleCheat(pc, "Aum Chat RPC");
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] sent an AUM chat, which was rejected", "EAC");
return true;
}
}
catch
{
}
break;
case unchecked((byte)42069): // 85 AUM
try
{
var aumid = reader.ReadByte();
if (aumid == pc.PlayerId)
{
Report(pc, "Aum RPC");
HandleCheat(pc, "Aum RPC");
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] sent AUM RPC, which was rejected", "EAC");
return true;
}
}
catch
{
}
break;
case unchecked((byte)420): // 164 Sicko
if (reader.BytesRemaining == 0)
{
Report(pc, "Sicko RPC");
HandleCheat(pc, "Sicko RPC");
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] sent Sicko RPC, which was rejected", "EAC");
return true;
}
break;
case 7:
case 8:
if (!GameStates.IsLobby)
@@ -198,7 +239,7 @@ internal class EAC
break;
case 5:
string name = sr.ReadString();
sr.ReadString();
if (GameStates.IsInGame)
{
WarnHost();
@@ -282,32 +323,14 @@ internal class EAC
return false;
}
public static Dictionary<byte, CustomRoles> OriginalRoles = [];
public static void LogAllRoles()
{
foreach (var pc in Main.AllPlayerControls.ToArray())
{
try
{
OriginalRoles.Add(pc.PlayerId, pc.GetCustomRole());
}
catch (Exception error)
{
Logger.Fatal(error.ToString(), "EAC.LogAllRoles");
}
}
}
public static bool RpcUpdateSystemCheck(PlayerControl player, SystemTypes systemType, byte amount)
{
//Update system rpc can not get received by playercontrol.handlerpc
var Mapid = Main.NormalOptions.MapId;
Logger.Info("Check sabotage RPC" + ", PlayerName: " + player.GetNameWithRole() + ", SabotageType: " + systemType + ", amount: " + amount, "EAC");
// UpdateSystem RPC cannot be received by PlayerControl.HandleRpc
if (!AmongUsClient.Instance.AmHost) return false;
switch (systemType) //Normal sabotage using buttons
var Mapid = Main.NormalOptions.MapId;
switch (systemType)
{
case SystemTypes.Sabotage:
case SystemTypes.Sabotage: // Normal sabotage using buttons
if (!player.HasKillButton() && !player.CanUseSabotage())
{
WarnHost();
@@ -342,7 +365,7 @@ internal class EAC
break;
case SystemTypes.Electrical:
if (Mapid == 5) goto YesCheat;
if (amount >= 5) //0 - 4 normal lights. other sabotage, Should never be sent by client
if (amount >= 5) // 0 - 4 normal lights. Other sabotage should never be sent by client
{
goto YesCheat;
}
@@ -350,21 +373,22 @@ internal class EAC
break;
case SystemTypes.Laboratory:
if (Mapid != 2) goto YesCheat;
if (!(amount is 64 or 65 or 32 or 33)) goto YesCheat;
if (amount is not (64 or 65 or 32 or 33)) goto YesCheat;
break;
case SystemTypes.Reactor:
if (Mapid is 2 or 4) goto YesCheat;
if (!(amount is 64 or 65 or 32 or 33)) goto YesCheat;
//Airship use heli sabotage /Other use 64,65 | 32,33
if (amount is not (64 or 65 or 32 or 33)) goto YesCheat;
// Airship uses heli sabotage / Other maps use 64,65 | 32,33
break;
case SystemTypes.HeliSabotage:
if (Mapid != 4) goto YesCheat;
if (!(amount is 64 or 65 or 16 or 17 or 32 or 33)) goto YesCheat;
if (amount is not (64 or 65 or 16 or 17 or 32 or 33)) goto YesCheat;
break;
case SystemTypes.MushroomMixupSabotage:
goto YesCheat;
}
// There may be cases where a player is fixing reactor and a meeting starts, triggering EAC check in a meeting
if ((GameStates.IsMeeting && MeetingHud.Instance.state != MeetingHud.VoteStates.Animating) || ExileController.Instance != null)
{
WarnHost();
@@ -372,7 +396,6 @@ internal class EAC
Logger.Fatal($"Player【{player.GetClientId()}:{player.GetRealName()}】Bad Sabotage D, rejected", "EAC");
return true;
}
//There may be cases where a player is fixing reactor and a meeting start, triggering EAC check in meeting
return false;
@@ -386,12 +409,12 @@ internal class EAC
}
}
public static void Report(PlayerControl pc, string reason)
private static void Report(PlayerControl pc, string reason)
{
string msg = $"{pc.GetClientId()}|{pc.FriendCode}|{pc.Data.PlayerName}|{pc.GetClient().GetHashedPuid()}|{reason}";
//Cloud.SendData(msg);
Logger.Fatal($"EAC report: {msg}", "EAC Cloud");
if (Options.CheatResponses.GetInt() != 5) Logger.SendInGame(string.Format(GetString("Message.NoticeByEAC"), $"{pc?.Data?.PlayerName} | {pc.GetClient().GetHashedPuid()}", reason));
if (Options.CheatResponses.GetInt() != 5) Logger.SendInGame(string.Format(GetString("Message.NoticeByEAC"), $"{pc.Data?.PlayerName} | {pc.GetClient().GetHashedPuid()}", reason));
}
public static bool ReceiveInvalidRpc(PlayerControl pc, byte callId)
@@ -407,7 +430,7 @@ internal class EAC
return true;
}
public static void HandleCheat(PlayerControl pc, string text)
private static void HandleCheat(PlayerControl pc, string text)
{
switch (Options.CheatResponses.GetInt())
{
@@ -427,8 +450,16 @@ internal class EAC
Utils.SendMessage(string.Format(GetString("Message.NoticeByEAC"), pc?.Data?.PlayerName, text), PlayerControl.LocalPlayer.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Impostor), GetString("MessageFromEAC")));
break;
case 3:
foreach (var apc in Main.AllPlayerControls.Where(x => x.PlayerId != pc?.Data?.PlayerId).ToArray())
Utils.SendMessage(string.Format(GetString("Message.NoticeByEAC"), pc?.Data?.PlayerName, text), pc.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Impostor), GetString("MessageFromEAC")));
foreach (var player in Main.AllPlayerControls)
{
if (player.PlayerId != pc?.Data?.PlayerId)
{
var message = string.Format(GetString("Message.NoticeByEAC"), pc?.Data?.PlayerName, text);
var title = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Impostor), GetString("MessageFromEAC"));
Utils.SendMessage(message, player.PlayerId, title);
}
}
break;
case 4:
if (!BanManager.TempBanWhiteList.Contains(pc.GetClient().GetHashedPuid()))
+4
View File
@@ -606,6 +606,10 @@ static class ExtendedPlayerControl
}
}
public static bool IsRoleBlocked(this PlayerControl pc) => RoleBlockManager.RoleBlockedPlayers.ContainsKey(pc.PlayerId);
public static bool IsPlayerRoleBlocked(this byte id) => RoleBlockManager.RoleBlockedPlayers.ContainsKey(id);
public static void BlockRole(this PlayerControl pc, float duration) => RoleBlockManager.AddRoleBlock(pc, duration);
public static bool HasKillButton(this PlayerControl pc)
{
CustomRoles role = pc.GetCustomRole();
+55 -20
View File
@@ -1,28 +1,17 @@
using System.Collections.Generic;
using System.Linq;
using EHR.Modules;
using Hazel;
using UnityEngine;
namespace EHR;
static class LocateArrow
{
class ArrowInfo(byte from, Vector3 to)
{
public byte From = from;
public Vector3 To = to;
public bool Equals(ArrowInfo obj)
{
return From == obj.From && To == obj.To;
}
public override string ToString()
{
return $"(From:{From} To:{To})";
}
}
static readonly Dictionary<ArrowInfo, string> LocateArrows = [];
static readonly string[] Arrows = [
static readonly string[] Arrows =
[
"↑",
"↗",
"→",
@@ -38,23 +27,43 @@ static class LocateArrow
{
LocateArrows.Clear();
}
public static void ReceiveRPC(MessageReader reader)
{
switch (reader.ReadPackedInt32())
{
case 1:
Add(reader.ReadByte(), Utils.ReadVector3(reader));
break;
case 2:
Remove(reader.ReadByte(), Utils.ReadVector3(reader));
break;
case 3:
RemoveAllTarget(reader.ReadByte());
break;
}
}
/// <summary>
/// Register a new target arrow object
/// </summary>
/// <param name="seer"></param>
/// <param name="target"></param>
/// <param name="coloredArrow"></param>
/// <param name="locate"></param>
public static void Add(byte seer, Vector3 locate)
{
var arrowInfo = new ArrowInfo(seer, locate);
if (!LocateArrows.Any(a => a.Key.Equals(arrowInfo)))
{
LocateArrows[arrowInfo] = "・";
Utils.SendRPC(CustomRPC.Arrow, false, 1, seer, locate);
}
}
/// <summary>
/// Delete target
/// </summary>
/// <param name="seer"></param>
/// <param name="target"></param>
/// <param name="locate"></param>
public static void Remove(byte seer, Vector3 locate)
{
var arrowInfo = new ArrowInfo(seer, locate);
@@ -63,7 +72,10 @@ static class LocateArrow
{
LocateArrows.Remove(a);
}
Utils.SendRPC(CustomRPC.Arrow, false, 2, seer, locate);
}
/// <summary>
/// Delete all targets for the specified seer
/// </summary>
@@ -75,7 +87,10 @@ static class LocateArrow
{
LocateArrows.Remove(arrowInfo);
}
Utils.SendRPC(CustomRPC.Arrow, false, 3, seer);
}
/// <summary>
/// Get all visible target arrows
/// </summary>
@@ -85,6 +100,7 @@ static class LocateArrow
{
return LocateArrows.Keys.Where(ai => ai.From == seer.PlayerId).Aggregate(string.Empty, (current, arrowInfo) => current + LocateArrows[arrowInfo]);
}
/// <summary>
/// Check target arrow every FixedUpdate
/// Issue NotifyRoles when there are updates
@@ -110,6 +126,7 @@ static class LocateArrow
update = true;
continue;
}
// Take the direction vector of the target
var dir = loc - seer.transform.position;
int index;
@@ -127,6 +144,7 @@ static class LocateArrow
var angle = Vector3.SignedAngle(Vector3.down, dir, Vector3.back) + 180 + 22.5;
index = ((int)(angle / 45)) % 8;
}
var arrow = Arrows[index];
if (LocateArrows[arrowInfo] != arrow)
{
@@ -134,9 +152,26 @@ static class LocateArrow
update = true;
}
}
if (update)
{
Utils.NotifyRoles(SpecifySeer: seer, ForceLoop: false, SpecifyTarget: seer);
}
}
}
class ArrowInfo(byte from, Vector3 to)
{
public byte From = from;
public Vector3 To = to;
public bool Equals(ArrowInfo obj)
{
return From == obj.From && To == obj.To;
}
public override string ToString()
{
return $"(From:{From} To:{To})";
}
}
}
+1 -3
View File
@@ -132,9 +132,7 @@ public static class NameColorManager
CustomRoles.HeadHunter when ((HeadHunter)Main.PlayerStates[seer.PlayerId].Role).Targets.Contains(target.PlayerId) => "000000",
CustomRoles.BountyHunter when (Main.PlayerStates[seer.PlayerId].Role as BountyHunter)?.GetTarget(seer) == target.PlayerId => "000000",
CustomRoles.Pyromaniac when ((Pyromaniac)Main.PlayerStates[seer.PlayerId].Role).DousedList.Contains(target.PlayerId) => "#BA4A00",
CustomRoles.Glitch when Glitch.hackedIdList.ContainsKey(target.PlayerId) => Main.RoleColors[CustomRoles.Glitch],
CustomRoles.Escort when Glitch.hackedIdList.ContainsKey(target.PlayerId) => Main.RoleColors[CustomRoles.Escort],
CustomRoles.Consort when Glitch.hackedIdList.ContainsKey(target.PlayerId) => Main.RoleColors[CustomRoles.Glitch],
CustomRoles.Glitch when target.IsRoleBlocked() => Main.RoleColors[seerRole],
CustomRoles.Aid when Aid.ShieldedPlayers.ContainsKey(target.PlayerId) => Main.RoleColors[CustomRoles.Aid],
CustomRoles.Spy when Spy.SpyRedNameList.ContainsKey(target.PlayerId) => "#BA4A00",
CustomRoles.Mastermind when Mastermind.ManipulateDelays.ContainsKey(target.PlayerId) => "#00ffa5",
+5 -22
View File
@@ -51,6 +51,7 @@ public enum CustomRPC
KillFlash,
SyncAbilityUseLimit,
RemoveSubRole,
Arrow,
// Roles
SetDrawPlayer,
@@ -97,8 +98,6 @@ public enum CustomRPC
SetMarkedPlayer,
SetMedicalerProtectList,
SyncPsychicRedList,
SetMorticianArrow,
SetTracefinderArrow,
SetCleanserCleanLimit,
SetJailorTarget,
SetDoppelgangerStealLimit,
@@ -118,8 +117,6 @@ public enum CustomRPC
SyncVengefulRomanticTarget,
SetRevealedPlayer,
SetCurrentRevealTarget,
SetBloodhoundArrow,
SetVultureArrow,
SetDoomsayerProgress,
SetTrackerTarget,
RpcPassBomb,
@@ -340,6 +337,10 @@ internal class RPCHandlerPatch
case CustomRPC.RemoveSubRole:
Main.PlayerStates[reader.ReadByte()].RemoveSubRole((CustomRoles)reader.ReadPackedInt32());
break;
case CustomRPC.Arrow:
if (reader.ReadBoolean()) TargetArrow.ReceiveRPC(reader);
else LocateArrow.ReceiveRPC(reader);
break;
case CustomRPC.SyncPostman:
{
byte id = reader.ReadByte();
@@ -613,12 +614,6 @@ internal class RPCHandlerPatch
(Main.PlayerStates[id].Role as Mafioso)?.ReceiveRPCSyncPistolCD(reader);
}
break;
case CustomRPC.SetMorticianArrow:
Mortician.ReceiveRPC(reader);
break;
case CustomRPC.SetTracefinderArrow:
Tracefinder.ReceiveRPC(reader);
break;
case CustomRPC.SyncNameNotify:
NameNotifyManager.ReceiveRPC(reader);
break;
@@ -634,9 +629,6 @@ internal class RPCHandlerPatch
case CustomRPC.MafiaRevenge:
Mafia.ReceiveRPC(reader, __instance);
break;
//case CustomRPC.RetributionistRevenge:
// RetributionistRevengeManager.ReceiveRPC(reader, __instance);
// break;
case CustomRPC.SetSwooperTimer:
{
byte id = reader.ReadByte();
@@ -687,15 +679,6 @@ internal class RPCHandlerPatch
Utils.FlashColor(new(1f, 0f, 0f, 0.3f));
if (Constants.ShouldPlaySfx()) RPC.PlaySound(PlayerControl.LocalPlayer.PlayerId, Sounds.KillSound);
break;
case CustomRPC.SetBloodhoundArrow:
Bloodhound.ReceiveRPC(reader);
break;
case CustomRPC.SetVultureArrow:
Vulture.ReceiveRPC(reader);
break;
//case CustomRPC.DoPoison:
// Baker.ReceiveRPC(reader);
// break;
case CustomRPC.SetCleanserCleanLimit:
Cleanser.ReceiveRPC(reader);
break;
+53
View File
@@ -0,0 +1,53 @@
using System.Collections.Generic;
using UnityEngine;
namespace EHR.Modules
{
public static class RoleBlockManager
{
public static Dictionary<byte, (long StartTimeStamp, float Duration)> RoleBlockedPlayers = [];
public static void Reset() => RoleBlockedPlayers = [];
public static void AddRoleBlock(PlayerControl pc, float duration)
{
long now = Utils.TimeStamp;
if (RoleBlockedPlayers.TryGetValue(pc.PlayerId, out var data) && (data.Duration - (now - data.StartTimeStamp) + 1) > duration)
{
Logger.Info($"{pc.GetNameWithRole()} got role blocked, but the duration is less than the previous one", "RoleBlockManager");
return;
}
RoleBlockedPlayers[pc.PlayerId] = (now, duration);
Logger.Info($"{pc.GetNameWithRole()} is now role blocked for {duration} seconds", "RoleBlockManager");
}
public static void OnFixedUpdate(PlayerControl pc)
{
if (RoleBlockedPlayers.TryGetValue(pc.PlayerId, out var data))
{
long now = Utils.TimeStamp;
if (now - data.StartTimeStamp >= data.Duration)
{
RoleBlockedPlayers.Remove(pc.PlayerId);
Logger.Info($"{pc.GetNameWithRole()} is no longer role blocked", "RoleBlockManager");
}
}
}
public static string GetBlockNotify(this BlockedAction blockedAction)
{
string blockedActionString = Translator.GetString($"{blockedAction}");
string notify = string.Format(Translator.GetString("RoleBlockNotify"), blockedActionString);
return Utils.ColorString(Color.yellow, notify);
}
}
public enum BlockedAction
{
Kill,
Report,
Sabotage,
Vent
}
}
+48 -17
View File
@@ -1,28 +1,17 @@
using System.Collections.Generic;
using System.Linq;
using EHR.Modules;
using Hazel;
using UnityEngine;
namespace EHR;
static class TargetArrow
{
class ArrowInfo(byte from, byte to)
{
public readonly byte From = from;
public readonly byte To = to;
public bool Equals(ArrowInfo obj)
{
return From == obj.From && To == obj.To;
}
public override string ToString()
{
return $"(From:{From} To:{To})";
}
}
static readonly Dictionary<ArrowInfo, string> TargetArrows = [];
static readonly string[] Arrows = [
static readonly string[] Arrows =
[
"↑",
"↗",
"→",
@@ -39,6 +28,22 @@ static class TargetArrow
TargetArrows.Clear();
}
public static void ReceiveRPC(MessageReader reader)
{
switch (reader.ReadPackedInt32())
{
case 1:
Add(reader.ReadByte(), reader.ReadByte());
break;
case 2:
Remove(reader.ReadByte(), reader.ReadByte());
break;
case 3:
RemoveAllTarget(reader.ReadByte());
break;
}
}
/// <summary>
/// Register a new target arrow object
/// </summary>
@@ -50,8 +55,10 @@ static class TargetArrow
if (!TargetArrows.Any(a => a.Key.Equals(arrowInfo)))
{
TargetArrows[arrowInfo] = "・";
Utils.SendRPC(CustomRPC.Arrow, true, 1, seer, target);
}
}
/// <summary>
/// Delete target
/// </summary>
@@ -65,7 +72,10 @@ static class TargetArrow
{
TargetArrows.Remove(a);
}
Utils.SendRPC(CustomRPC.Arrow, true, 2, seer, target);
}
/// <summary>
/// Delete all targets for the specified seer
/// </summary>
@@ -77,6 +87,8 @@ static class TargetArrow
{
TargetArrows.Remove(arrowInfo);
}
Utils.SendRPC(CustomRPC.Arrow, true, 3, seer);
}
/// <summary>
@@ -115,6 +127,7 @@ static class TargetArrow
update = true;
continue;
}
// Take the direction vector of the target
var dir = target.transform.position - seer.transform.position;
int index;
@@ -132,6 +145,7 @@ static class TargetArrow
var angle = Vector3.SignedAngle(Vector3.down, dir, Vector3.back) + 180 + 22.5;
index = ((int)(angle / 45)) % 8;
}
var arrow = Arrows[index];
if (TargetArrows[arrowInfo] != arrow)
{
@@ -139,9 +153,26 @@ static class TargetArrow
update = true;
}
}
if (update)
{
Utils.NotifyRoles(SpecifySeer: seer, ForceLoop: false, SpecifyTarget: seer);
}
}
}
class ArrowInfo(byte from, byte to)
{
public readonly byte From = from;
public readonly byte To = to;
public bool Equals(ArrowInfo obj)
{
return From == obj.From && To == obj.To;
}
public override string ToString()
{
return $"(From:{From} To:{To})";
}
}
}
+16
View File
@@ -448,6 +448,8 @@ public static class Utils
public static void SendRPC(CustomRPC rpc, params object[] data)
{
if (!AmongUsClient.Instance.AmHost) return;
var w = CreateRPC(rpc);
foreach (var o in data)
{
@@ -471,12 +473,25 @@ public static class Utils
case Vector2 v:
NetHelpers.WriteVector2(v, w);
break;
case Vector3 v:
w.Write(v.x);
w.Write(v.y);
w.Write(v.z);
break;
}
}
EndRPC(w);
}
public static Vector3 ReadVector3(MessageReader reader)
{
float x = reader.ReadSingle();
float y = reader.ReadSingle();
float z = reader.ReadSingle();
return new(x, y, z);
}
public static void IncreaseAbilityUseLimitOnKill(PlayerControl killer)
{
if (Main.PlayerStates[killer.PlayerId].Role is Mafioso { IsEnable: true } mo) mo.OnMurder(killer, null);
@@ -2422,6 +2437,7 @@ public static class Utils
Main.DontCancelVoteList.Clear();
DoorsReset.ResetDoors();
RoleBlockManager.Reset();
if ((MapNames)Main.NormalOptions.MapId == MapNames.Airship && AmongUsClient.Instance.AmHost && PlayerControl.LocalPlayer.Is(CustomRoles.GM))
{
+26 -12
View File
@@ -96,17 +96,31 @@ internal class TitleLogoPatch
//private static readonly Color themeColor10 = new(0.18f, 0.2f, 0.59f);
//private static readonly Color themeColor11 = new(0.96f, 0.88f, 0.86f);
private static readonly Color ThemeColor1 = new(0.98f, 0.7f, 0.44f);
private static readonly Color ThemeColor2 = new(0.98f, 0.61f, 0.42f);
private static readonly Color ThemeColor3 = new(0.04f, 0.41f, 0.75f);
private static readonly Color ThemeColor4 = new(0.12f, 0.17f, 0.47f);
private static readonly Color ThemeColor5 = new(0.38f, 0.44f, 0.66f);
private static readonly Color ThemeColor6 = new(0.72f, 0.68f, 0.79f);
private static readonly Color ThemeColor7 = ThemeColor1.ShadeColor(0.1f);
private static readonly Color ThemeColor8 = new(0.19f, 0.24f, 0.37f);
private static readonly Color ThemeColor9 = ThemeColor5.ShadeColor(0.1f);
private static readonly Color ThemeColor10 = ThemeColor4.ShadeColor(0.1f);
private static readonly Color ThemeColor11 = ThemeColor6.ShadeColor(0.1f);
// Winter BG
// private static readonly Color ThemeColor1 = new(0.98f, 0.7f, 0.44f);
// private static readonly Color ThemeColor2 = new(0.98f, 0.61f, 0.42f);
// private static readonly Color ThemeColor3 = new(0.04f, 0.41f, 0.75f);
// private static readonly Color ThemeColor4 = new(0.12f, 0.17f, 0.47f);
// private static readonly Color ThemeColor5 = new(0.38f, 0.44f, 0.66f);
// private static readonly Color ThemeColor6 = new(0.72f, 0.68f, 0.79f);
// private static readonly Color ThemeColor7 = ThemeColor1.ShadeColor(0.1f);
// private static readonly Color ThemeColor8 = new(0.19f, 0.24f, 0.37f);
// private static readonly Color ThemeColor9 = ThemeColor5.ShadeColor(0.1f);
// private static readonly Color ThemeColor10 = ThemeColor4.ShadeColor(0.1f);
// private static readonly Color ThemeColor11 = ThemeColor6.ShadeColor(0.1f);
// Summer BG
private static readonly Color ThemeColor1 = new(0.706f, 0.588f, 0.455f);
private static readonly Color ThemeColor2 = new(0.827f, 0.827f, 0.643f);
private static readonly Color ThemeColor3 = new(0.196f, 0.196f, 0.067f);
private static readonly Color ThemeColor4 = new(0.145f, 0.655f, 0.859f);
private static readonly Color ThemeColor5 = new(0.580f, 0.780f, 0.820f);
private static readonly Color ThemeColor6 = new(0.435f, 0.776f, 0.925f);
private static readonly Color ThemeColor7 = new(0.161f, 0.439f, 0.588f);
private static readonly Color ThemeColor8 = new(0.388f, 0.565f, 0.537f);
private static readonly Color ThemeColor9 = new(0.463f, 0.471f, 0.188f);
private static readonly Color ThemeColor10 = Color.black;
private static readonly Color ThemeColor11 = ThemeColor4.ShadeColor(0.1f);
private static void Postfix(MainMenuManager __instance)
{
@@ -199,7 +213,7 @@ internal class TitleLogoPatch
}
};
var bgRenderer = customBg.AddComponent<SpriteRenderer>();
bgRenderer.sprite = Utils.LoadSprite("EHR.Resources.Images.WinterBG.jpg", 180f);
bgRenderer.sprite = Utils.LoadSprite("EHR.Resources.Images.SummerBG.jpg", 180f);
if (__instance.screenTint != null)
{
+9 -6
View File
@@ -159,7 +159,6 @@ class ExileControllerWrapUpPatch
static void WrapUpFinalizer(GameData.PlayerInfo exiled)
{
// Even if an exception occurs in WrapUpPostfix, this part will be executed reliably.
bool overrideExiledPlayer = false;
if (AmongUsClient.Instance.AmHost)
{
_ = new LateTask(() =>
@@ -171,7 +170,6 @@ class ExileControllerWrapUpPatch
exiled.Object != null)
{
exiled.Object.RpcExileV2();
overrideExiledPlayer = true;
}
}, 0.8f, "Restore IsDead Task");
_ = new LateTask(() =>
@@ -199,11 +197,14 @@ class ExileControllerWrapUpPatch
SoundManager.Instance.ChangeAmbienceVolume(DataManager.Settings.Audio.AmbienceVolume);
Logger.Info("Start task phase", "Phase");
if (Options.EnableKillerLeftCommand.GetBool() && Options.CurrentGameMode == CustomGameMode.Standard && Options.ShowImpRemainOnEject.GetBool())
bool showRemainingKillers = Options.EnableKillerLeftCommand.GetBool() && Options.ShowImpRemainOnEject.GetBool();
bool appendEjectionNotify = CheckForEndVotingPatch.EjectionText != string.Empty;
Logger.Warn($"Ejection Text: {CheckForEndVotingPatch.EjectionText}", "debug");
if ((showRemainingKillers || appendEjectionNotify) && Options.CurrentGameMode == CustomGameMode.Standard)
{
_ = new LateTask(() =>
{
var text = Utils.GetRemainingKillers(notify: true);
var text = showRemainingKillers ? Utils.GetRemainingKillers(notify: true) : string.Empty;
text = $"<#ffffff>{text}</color>";
var r = IRandom.Instance;
foreach (var pc in Main.AllAlivePlayerControls)
@@ -214,11 +215,13 @@ class ExileControllerWrapUpPatch
finalText = $"\n{notify.TEXT}\n{finalText}";
}
if (overrideExiledPlayer && CheckForEndVotingPatch.EjectionText != string.Empty)
if (appendEjectionNotify)
{
finalText = $"\n{CheckForEndVotingPatch.EjectionText}\n{finalText}";
finalText = $"\n<#ffffff>{CheckForEndVotingPatch.EjectionText}</color>\n{finalText}";
}
if (!showRemainingKillers) finalText = finalText.TrimStart();
pc.Notify(finalText, r.Next(7, 13));
}
}, 0.5f, log: false);
+60 -25
View File
@@ -75,15 +75,14 @@ class HudManagerPatch
{
if (OverriddenRolesText == null)
{
OverriddenRolesText = Object.Instantiate(__instance.KillButton.cooldownTimerText);
OverriddenRolesText = Object.Instantiate(__instance.KillButton.cooldownTimerText, __instance.transform, true);
OverriddenRolesText.alignment = TextAlignmentOptions.Right;
OverriddenRolesText.verticalAlignment = VerticalAlignmentOptions.Top;
OverriddenRolesText.transform.parent = __instance.transform;
OverriddenRolesText.transform.localPosition = new(4.9f, 0.8f, 0);
OverriddenRolesText.overflowMode = TextOverflowModes.Overflow;
OverriddenRolesText.enableWordWrapping = false;
OverriddenRolesText.color = Color.white;
OverriddenRolesText.fontSize = OverriddenRolesText.fontSizeMax = OverriddenRolesText.fontSizeMin = 2f;
OverriddenRolesText.fontSize = OverriddenRolesText.fontSizeMax = OverriddenRolesText.fontSizeMin = 2.5f;
}
if (Main.SetRoles.Count > 0 || Main.SetAddOns.Count > 0)
@@ -120,24 +119,17 @@ class HudManagerPatch
}
}
bool stop = false;
foreach (var roles in Main.SetRoles)
foreach (var role in Main.SetRoles)
{
if (!Main.SetAddOns.ContainsKey(roles.Key)) continue;
foreach (var addons in Main.SetAddOns)
{
if (!Main.SetRoles.ContainsKey(addons.Key)) continue;
foreach (var addon in addons.Value)
{
if (!CustomRolesHelper.CheckAddonConflictV2(addon, roles.Value))
{
resultText[roles.Key] += " <#ff0000>(!)</color>";
stop = true;
break;
}
}
if (!Main.SetAddOns.TryGetValue(role.Key, out var addons)) continue;
if (stop) break;
foreach (var addon in addons)
{
if (!CustomRolesHelper.CheckAddonConflictV2(addon, role.Value))
{
resultText[role.Key] += " <#ff0000>(!)</color>";
break;
}
}
}
@@ -359,14 +351,13 @@ class HudManagerPatch
if (LowerInfoText == null)
{
LowerInfoText = Object.Instantiate(__instance.KillButton.cooldownTimerText);
LowerInfoText = Object.Instantiate(__instance.KillButton.cooldownTimerText, __instance.transform, true);
LowerInfoText.alignment = TextAlignmentOptions.Center;
LowerInfoText.transform.parent = __instance.transform;
LowerInfoText.transform.localPosition = new(0, -2f, 0);
LowerInfoText.overflowMode = TextOverflowModes.Overflow;
LowerInfoText.enableWordWrapping = false;
LowerInfoText.color = Color.white;
LowerInfoText.fontSize = LowerInfoText.fontSizeMax = LowerInfoText.fontSizeMin = 2f;
LowerInfoText.fontSize = LowerInfoText.fontSizeMax = LowerInfoText.fontSizeMin = 2.7f;
}
var state = Main.PlayerStates[player.PlayerId];
@@ -476,6 +467,8 @@ class HudManagerPatch
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.ToggleHighlight))]
class ToggleHighlightPatch
{
private static readonly int OutlineColor = Shader.PropertyToID("_OutlineColor");
public static void Postfix(PlayerControl __instance /*[HarmonyArgument(0)] bool active,*/ /*[HarmonyArgument(1)] RoleTeamTypes team*/)
{
if (!GameStates.IsInTask) return;
@@ -483,7 +476,7 @@ class ToggleHighlightPatch
if (player.CanUseKillButton())
{
__instance.cosmetics.currentBodySprite.BodySprite.material.SetColor("_OutlineColor", Utils.GetRoleColor(player.GetCustomRole()));
__instance.cosmetics.currentBodySprite.BodySprite.material.SetColor(OutlineColor, Utils.GetRoleColor(player.GetCustomRole()));
}
}
}
@@ -491,11 +484,14 @@ class ToggleHighlightPatch
[HarmonyPatch(typeof(Vent), nameof(Vent.SetOutline))]
class SetVentOutlinePatch
{
private static readonly int OutlineColor = Shader.PropertyToID("_OutlineColor");
private static readonly int AddColor = Shader.PropertyToID("_AddColor");
public static void Postfix(Vent __instance, [HarmonyArgument(1)] ref bool mainTarget)
{
Color color = PlayerControl.LocalPlayer.GetRoleColor();
__instance.myRend.material.SetColor("_OutlineColor", color);
__instance.myRend.material.SetColor("_AddColor", mainTarget ? color : Color.clear);
__instance.myRend.material.SetColor(OutlineColor, color);
__instance.myRend.material.SetColor(AddColor, mainTarget ? color : Color.clear);
}
}
@@ -623,10 +619,49 @@ class MapBehaviourShowPatch
opts.Mode = MapOptions.Modes.Normal;
}
if (Main.GodMode.Value) opts.ShowLivePlayerPosition = true;
return true;
}
}
[HarmonyPatch(typeof(InfectedOverlay), nameof(InfectedOverlay.Update))]
class SabotageMapPatch
{
public static Dictionary<SystemTypes, TextMeshPro> TimerTexts = [];
public static void Postfix(InfectedOverlay __instance)
{
float perc = __instance.sabSystem.PercentCool;
int total = __instance.sabSystem.initialCooldown ? 10 : 30;
if (SabotageSystemTypeRepairDamagePatch.IsCooldownModificationEnabled) total = (int)SabotageSystemTypeRepairDamagePatch.ModifiedCooldownSec;
int remaining = Math.Clamp(total - (int)Math.Ceiling((1f - perc) * total) + 1, 0, total);
foreach (var mr in __instance.rooms)
{
if (mr.special == null || mr.special.transform == null) continue;
var room = mr.room;
if (!TimerTexts.ContainsKey(room))
{
TimerTexts[room] = Object.Instantiate(HudManager.Instance.KillButton.cooldownTimerText, mr.special.transform, true);
TimerTexts[room].alignment = TextAlignmentOptions.Center;
TimerTexts[room].transform.localPosition = mr.special.transform.localPosition;
TimerTexts[room].transform.localPosition = new(0, -0.4f, 0f);
TimerTexts[room].overflowMode = TextOverflowModes.Overflow;
TimerTexts[room].enableWordWrapping = false;
TimerTexts[room].color = Color.white;
TimerTexts[room].fontSize = TimerTexts[room].fontSizeMax = TimerTexts[room].fontSizeMin = 2.5f;
TimerTexts[room].sortingOrder = 100;
}
bool isActive = Utils.IsActive(room);
bool isOtherActive = TimerTexts.Keys.Any(Utils.IsActive);
TimerTexts[room].text = $"<b><#ff{(isActive || isOtherActive ? "00" : "ff")}00>{(isActive ? remaining : GetString(isOtherActive ? "SabotageDisabledIndicator" : "SabotageActiveIndicator"))}</color></b>";
TimerTexts[room].enabled = remaining > 0 || isActive;
}
}
}
[HarmonyPatch(typeof(TaskPanelBehaviour), nameof(TaskPanelBehaviour.SetTaskText))]
class TaskPanelBehaviourPatch
{
+23 -77
View File
@@ -880,20 +880,28 @@ class MeetingHudStartPatch
var seerRole = seer.GetCustomRole();
// Guesser Mode //
if (Options.GuesserMode.GetBool())
if (((Options.GuesserMode.GetBool() && !seer.Data.IsDead && !target.Data.IsDead &&
((Options.CrewmatesCanGuess.GetBool() && seer.IsCrewmate() && !seer.Is(CustomRoles.Judge) && !seer.Is(CustomRoles.NiceSwapper) && !seer.Is(CustomRoles.Lookout) && !seer.Is(CustomRoles.ParityCop)) ||
(Options.ImpostorsCanGuess.GetBool() && seerRole.IsImpostor() && !seer.Is(CustomRoles.Councillor)) ||
(Options.NeutralKillersCanGuess.GetBool() && seer.IsNeutralKiller()) ||
(Options.PassiveNeutralsCanGuess.GetBool() && seerRole.IsNonNK() && !seer.Is(CustomRoles.Doomsayer)))) ||
// Other Roles and Add-ons that can see player IDs //
(seer.Data.IsDead && !target.Data.IsDead && seerRole is CustomRoles.Mafia) ||
(!seer.Data.IsDead && !target.Data.IsDead &&
(seer.Is(CustomRoles.Guesser) ||
seerRole is
CustomRoles.Judge or
CustomRoles.NiceSwapper or
CustomRoles.Lookout or
CustomRoles.ParityCop or
CustomRoles.Councillor or
CustomRoles.Doomsayer or
CustomRoles.EvilGuesser or
CustomRoles.NiceGuesser
))))
{
if (Options.CrewmatesCanGuess.GetBool() && seer.IsCrewmate() && !seer.Is(CustomRoles.Judge) && !seer.Is(CustomRoles.NiceSwapper) && !seer.Is(CustomRoles.Lookout) && !seer.Is(CustomRoles.ParityCop))
if (!seer.Data.IsDead && !target.Data.IsDead)
pva.NameText.text = Utils.ColorString(Utils.GetRoleColor(seerRole), target.PlayerId.ToString()) + " " + pva.NameText.text;
if (Options.ImpostorsCanGuess.GetBool() && seerRole.IsImpostor() && !seer.Is(CustomRoles.Councillor))
if (!seer.Data.IsDead && !target.Data.IsDead)
pva.NameText.text = Utils.ColorString(Utils.GetRoleColor(seerRole), target.PlayerId.ToString()) + " " + pva.NameText.text;
if (Options.NeutralKillersCanGuess.GetBool() && seer.IsNeutralKiller())
if (!seer.Data.IsDead && !target.Data.IsDead)
pva.NameText.text = Utils.ColorString(Utils.GetRoleColor(seerRole), target.PlayerId.ToString()) + " " + pva.NameText.text;
if (Options.PassiveNeutralsCanGuess.GetBool() && seerRole.IsNonNK() && !seer.Is(CustomRoles.Doomsayer))
if (!seer.Data.IsDead && !target.Data.IsDead)
pva.NameText.text = Utils.ColorString(Utils.GetRoleColor(seerRole), target.PlayerId.ToString()) + " " + pva.NameText.text;
pva.NameText.text = $"{Utils.ColorString(Utils.GetRoleColor(seerRole), target.PlayerId.ToString())} {pva.NameText.text}";
}
if (seer.KnowDeathReason(target))
@@ -940,46 +948,6 @@ class MeetingHudStartPatch
if (Psychic.IsRedForPsy(target, seer) && !seer.Data.IsDead)
pva.NameText.text = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Impostor), pva.NameText.text);
break;
case CustomRoles.Mafia:
if (seer.Data.IsDead && !target.Data.IsDead)
pva.NameText.text = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Mafia), target.PlayerId.ToString()) + " " + pva.NameText.text;
break;
case CustomRoles.NiceGuesser:
case CustomRoles.EvilGuesser:
if (!seer.Data.IsDead && !target.Data.IsDead)
pva.NameText.text = Utils.ColorString(Utils.GetRoleColor(seer.Is(CustomRoles.NiceGuesser) ? CustomRoles.NiceGuesser : CustomRoles.EvilGuesser), target.PlayerId.ToString()) + " " + pva.NameText.text;
break;
case CustomRoles.Guesser:
if (!seer.Data.IsDead && !target.Data.IsDead)
pva.NameText.text = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Guesser), target.PlayerId.ToString()) + " " + pva.NameText.text;
break;
case CustomRoles.Judge:
if (!seer.Data.IsDead && !target.Data.IsDead)
pva.NameText.text = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Judge), target.PlayerId.ToString()) + " " + pva.NameText.text;
break;
case CustomRoles.NiceSwapper:
if (!seer.Data.IsDead && !target.Data.IsDead)
pva.NameText.text = Utils.ColorString(Utils.GetRoleColor(CustomRoles.NiceSwapper), target.PlayerId.ToString()) + " " + pva.NameText.text;
break;
case CustomRoles.Lookout:
if (!seer.Data.IsDead && !target.Data.IsDead)
pva.NameText.text = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Lookout), target.PlayerId.ToString()) + " " + pva.NameText.text;
break;
case CustomRoles.Doomsayer:
if (!seer.Data.IsDead && !target.Data.IsDead)
pva.NameText.text = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Doomsayer), target.PlayerId.ToString()) + " " + pva.NameText.text;
break;
case CustomRoles.ParityCop:
if (!seer.Data.IsDead && !target.Data.IsDead)
pva.NameText.text = Utils.ColorString(Utils.GetRoleColor(CustomRoles.ParityCop), target.PlayerId.ToString()) + " " + pva.NameText.text;
break;
case CustomRoles.Councillor:
if (!seer.Data.IsDead && !target.Data.IsDead)
pva.NameText.text = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Councillor), target.PlayerId.ToString()) + " " + pva.NameText.text;
break;
case CustomRoles.Gamer:
sb.Append(Gamer.TargetMark(seer, target));
sb.Append(Snitch.GetWarningMark(seer, target));
@@ -992,31 +960,9 @@ class MeetingHudStartPatch
if (Silencer.ForSilencer.Contains(target.PlayerId))
sb.Append(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Silencer), "╳"));
List<CustomRoles> list = seer.GetCustomSubRoles();
foreach (var SeerSubRole in list)
if (target.GetCustomSubRoles().Contains(CustomRoles.Lovers) && (seer.Is(CustomRoles.Lovers) || seer.Data.IsDead))
{
switch (SeerSubRole)
{
case CustomRoles.Guesser:
if (!seer.Data.IsDead && !target.Data.IsDead)
pva.NameText.text = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Guesser), target.PlayerId.ToString()) + " " + pva.NameText.text;
break;
}
}
List<CustomRoles> list1 = target.GetCustomSubRoles();
foreach (var subRole in list1)
{
switch (subRole)
{
case CustomRoles.Lovers:
if (seer.Is(CustomRoles.Lovers) || seer.Data.IsDead)
{
sb.Append(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Lovers), "♥"));
}
break;
}
sb.Append(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Lovers), "♥"));
}
sb.Append(Witch.GetSpelledMark(target.PlayerId, true));
+35 -34
View File
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using AmongUs.GameOptions;
using EHR.Modules;
using EHR.Patches;
using EHR.Roles.AddOns.Common;
using EHR.Roles.AddOns.Crewmate;
using EHR.Roles.AddOns.Impostor;
@@ -50,6 +51,37 @@ internal class ChangeRoleSettings
Main.AllPlayerKillCooldown = [];
Main.AllPlayerSpeed = [];
Main.KillTimers = [];
Main.SleuthMsgs = [];
Main.CyberStarDead = [];
Main.KilledDiseased = [];
Main.KilledAntidote = [];
Main.BaitAlive = [];
Main.DontCancelVoteList = [];
Main.LastEnteredVent = [];
Main.LastEnteredVentLocation = [];
Main.AfterMeetingDeathPlayers = [];
Main.ResetCamPlayerList = [];
Main.ClientIdList = [];
Main.CheckShapeshift = [];
Main.ShapeshiftTarget = [];
Main.ShieldPlayer = Options.ShieldPersonDiedFirst.GetBool() ? Main.FirstDied : byte.MaxValue;
Main.FirstDied = byte.MaxValue;
Main.MadmateNum = 0;
Mayor.MayorUsedButtonCount = [];
Paranoia.ParaUsedButtonCount = [];
Mario.MarioVentCount = [];
Cleaner.CleanerBodies = [];
Virus.InfectedBodies = [];
Workaholic.WorkaholicAlive = [];
Virus.VirusNotify = [];
Veteran.VeteranInProtect = [];
Witness.AllKillers = [];
Grenadier.GrenadierBlinding = [];
SecurityGuard.BlockSabo = [];
Ventguard.BlockedVents = [];
Grenadier.MadGrenadierBlinding = [];
OverKiller.OverDeadPlayerList = [];
Warlock.WarlockTimer = [];
Arsonist.IsDoused = [];
Revolutionist.IsDraw = [];
@@ -67,45 +99,13 @@ internal class ChangeRoleSettings
Warlock.IsCurseAndKill = [];
Warlock.IsCursed = false;
Detective.DetectiveNotify = [];
Main.SleuthMsgs = [];
Crusader.ForCrusade = [];
Main.CyberStarDead = [];
Main.KilledDiseased = [];
Main.KilledAntidote = [];
Workaholic.WorkaholicAlive = [];
Main.BaitAlive = [];
Cleaner.CleanerBodies = [];
Virus.InfectedBodies = [];
Virus.VirusNotify = [];
Main.DontCancelVoteList = [];
Main.LastEnteredVent = [];
Main.LastEnteredVentLocation = [];
Main.AfterMeetingDeathPlayers = [];
Main.ResetCamPlayerList = [];
Main.ClientIdList = [];
Main.CheckShapeshift = [];
Main.ShapeshiftTarget = [];
Mayor.MayorUsedButtonCount = [];
Paranoia.ParaUsedButtonCount = [];
Mario.MarioVentCount = [];
Veteran.VeteranInProtect = [];
Witness.AllKillers = [];
Grenadier.GrenadierBlinding = [];
SecurityGuard.BlockSabo = [];
Ventguard.BlockedVents = [];
Grenadier.MadGrenadierBlinding = [];
OverKiller.OverDeadPlayerList = [];
Provocateur.Provoked = [];
Main.ShieldPlayer = Options.ShieldPersonDiedFirst.GetBool() ? Main.FirstDied : byte.MaxValue;
Main.FirstDied = byte.MaxValue;
Main.MadmateNum = 0;
Crusader.ForCrusade = [];
Godfather.GodfatherTarget = byte.MaxValue;
ChatManager.ResetHistory();
ReportDeadBodyPatch.CanReport = [];
SabotageMapPatch.TimerTexts = [];
Options.UsedButtonCount = 0;
@@ -213,6 +213,7 @@ internal class ChangeRoleSettings
DoorsReset.Initialize();
GhostRolesManager.Initialize();
CustomTeamManager.LoadCustomTeams();
RoleBlockManager.Reset();
IRandom.SetInstanceById(Options.RoleAssigningAlgorithm.GetValue());
+13 -11
View File
@@ -238,9 +238,9 @@ class CheckMurderPatch
if (Pelican.IsEaten(target.PlayerId))
return false;
if (Glitch.hackedIdList.ContainsKey(killer.PlayerId))
if (killer.IsRoleBlocked())
{
killer.Notify(string.Format(GetString("HackedByGlitch"), "Kill"));
killer.Notify(BlockedAction.Kill.GetBlockNotify());
return false;
}
@@ -341,9 +341,9 @@ class CheckMurderPatch
return false;
}
if (Glitch.hackedIdList.ContainsKey(killer.PlayerId))
if (killer.IsRoleBlocked())
{
killer.Notify(string.Format(GetString("HackedByGlitch"), "Kill"));
killer.Notify(BlockedAction.Kill.GetBlockNotify());
return false;
}
@@ -1030,9 +1030,9 @@ class FixedUpdatePatch
byte id = __instance.PlayerId;
if (AmongUsClient.Instance.AmHost && GameStates.IsInTask && ReportDeadBodyPatch.CanReport[id] && ReportDeadBodyPatch.WaitReport[id].Count > 0)
{
if (Glitch.hackedIdList.ContainsKey(id))
if (id.IsPlayerRoleBlocked())
{
__instance.Notify(string.Format(GetString("HackedByGlitch"), "Report"));
__instance.Notify(BlockedAction.Report.GetBlockNotify());
Logger.Info("Dead Body Report Blocked (player is hacked by Glitch)", "FixedUpdate.ReportDeadBody");
ReportDeadBodyPatch.WaitReport[id].Clear();
}
@@ -1222,6 +1222,8 @@ class FixedUpdatePatch
}
if (!lowLoad) Randomizer.OnFixedUpdateForPlayers(player);
RoleBlockManager.OnFixedUpdate(player);
}
if (!lowLoad)
@@ -1294,7 +1296,7 @@ class FixedUpdatePatch
RoleText.text = RoleTextData.Item1;
RoleText.color = RoleTextData.Item2;
if (Options.CurrentGameMode != CustomGameMode.Standard) RoleText.text = string.Empty;
if (Options.CurrentGameMode is not CustomGameMode.Standard and not CustomGameMode.HideAndSeek) RoleText.text = string.Empty;
RoleText.enabled = IsRoleTextEnabled(__instance);
@@ -1623,7 +1625,7 @@ class PlayerStartPatch
{
var roleText = Object.Instantiate(__instance.cosmetics.nameText, __instance.cosmetics.nameText.transform, true);
roleText.transform.localPosition = new(0f, 0.2f, 0f);
roleText.fontSize -= 0.2f;
roleText.fontSize -= 0.9f;
roleText.text = "RoleText";
roleText.gameObject.name = "RoleText";
roleText.enabled = false;
@@ -1756,14 +1758,14 @@ class CoEnterVentPatch
return true;
case CustomGameMode.HideAndSeek:
CustomHideAndSeekManager.OnCoEnterVent(__instance, id);
return true;
break;
}
if (Glitch.hackedIdList.ContainsKey(__instance.myPlayer.PlayerId))
if (__instance.myPlayer.IsRoleBlocked())
{
_ = new LateTask(() =>
{
__instance.myPlayer?.Notify(string.Format(GetString("HackedByGlitch"), "Vent"));
__instance.myPlayer?.Notify(BlockedAction.Vent.GetBlockNotify());
__instance.myPlayer?.MyPhysics?.RpcBootFromVent(id);
}, 0.5f);
return true;
+9 -10
View File
@@ -1,4 +1,4 @@
using System.Linq;
using EHR.Modules;
using EHR.Roles.Crewmate;
using EHR.Roles.Neutral;
using HarmonyLib;
@@ -244,27 +244,26 @@ public static class ElectricTaskCompletePatch
[HarmonyPatch(typeof(SabotageSystemType), nameof(SabotageSystemType.UpdateSystem))]
public static class SabotageSystemTypeRepairDamagePatch
{
private static bool isCooldownModificationEnabled;
private static float modifiedCooldownSec;
public static bool IsCooldownModificationEnabled;
public static float ModifiedCooldownSec;
public static void Initialize()
{
isCooldownModificationEnabled = Options.SabotageCooldownControl.GetBool();
modifiedCooldownSec = Options.SabotageCooldown.GetFloat();
IsCooldownModificationEnabled = Options.SabotageCooldownControl.GetBool();
ModifiedCooldownSec = Options.SabotageCooldown.GetFloat();
}
public static bool Prefix([HarmonyArgument(0)] PlayerControl player)
{
if (Options.DisableSabotage.GetBool() || Options.CurrentGameMode != CustomGameMode.Standard) return false;
if (SecurityGuard.BlockSabo.Count > 0) return false;
if (Glitch.hackedIdList.ContainsKey(player.PlayerId))
if (player.IsRoleBlocked())
{
player.Notify(string.Format(Translator.GetString("HackedByGlitch"), "Sabotage"));
player.Notify(BlockedAction.Sabotage.GetBlockNotify());
return false;
}
if (player.Is(CustomRoleTypes.Impostor) && !player.IsAlive() && Options.DeadImpCantSabotage.GetBool()) return false;
if (player.Is(CustomRoleTypes.Impostor) && (player.IsAlive() || !Options.DeadImpCantSabotage.GetBool()) && player.GetCustomRole() is not CustomRoles.Minimalism and not CustomRoles.Mafioso and not CustomRoles.Generator) return true;
bool allow = player.GetCustomRole() switch
{
CustomRoles.Jackal when Jackal.CanSabotage.GetBool() => true,
@@ -282,12 +281,12 @@ public static class SabotageSystemTypeRepairDamagePatch
public static void Postfix(SabotageSystemType __instance)
{
if (!isCooldownModificationEnabled || !AmongUsClient.Instance.AmHost)
if (!IsCooldownModificationEnabled || !AmongUsClient.Instance.AmHost)
{
return;
}
__instance.Timer = modifiedCooldownSec;
__instance.Timer = ModifiedCooldownSec;
__instance.IsDirty = true;
}
}
+9 -5
View File
@@ -1,6 +1,7 @@
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;
@@ -34,15 +35,19 @@ class ShipFixedUpdatePatch
[HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.UpdateSystem), typeof(SystemTypes), typeof(PlayerControl), typeof(MessageReader))]
public static class MessageReaderUpdateSystemPatch
{
public static void Prefix(ShipStatus __instance, [HarmonyArgument(0)] SystemTypes systemType, [HarmonyArgument(1)] PlayerControl player, [HarmonyArgument(2)] MessageReader reader)
public static bool Prefix(ShipStatus __instance, [HarmonyArgument(0)] SystemTypes systemType, [HarmonyArgument(1)] PlayerControl player, [HarmonyArgument(2)] MessageReader reader)
{
try
{
RepairSystemPatch.Prefix(__instance, systemType, player, MessageReader.Get(reader).ReadByte());
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)
@@ -115,14 +120,13 @@ class RepairSystemPatch
case SystemTypes.Sabotage when AmongUsClient.Instance.NetworkMode != NetworkModes.FreePlay:
if (Options.CurrentGameMode != CustomGameMode.Standard) return false;
if (SecurityGuard.BlockSabo.Count > 0) return false;
if (Glitch.hackedIdList.ContainsKey(player.PlayerId))
if (player.IsRoleBlocked())
{
player.Notify(string.Format(Translator.GetString("HackedByGlitch"), "Sabotage"));
player.Notify(BlockedAction.Sabotage.GetBlockNotify());
return false;
}
if (player.Is(CustomRoleTypes.Impostor) && !player.IsAlive() && Options.DeadImpCantSabotage.GetBool()) return false;
if (player.Is(CustomRoleTypes.Impostor) && (player.IsAlive() || !Options.DeadImpCantSabotage.GetBool()) && !player.Is(CustomRoles.Minimalism) && !player.Is(CustomRoles.Mafioso)) return true;
return player.GetCustomRole() switch
{
CustomRoles.Jackal when Jackal.CanSabotage.GetBool() => true,
Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 749 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 696 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 MiB

+10 -3
View File
@@ -1047,6 +1047,11 @@
"TieMode.Default": "No ejects",
"TieMode.All": "Eject All",
"TieMode.Random": "Eject Random",
"Kill": "Kill",
"Report": "Report",
"Sabotage": "Sabotage",
"Vent": "Vent",
"Dead": "DEAD",
"DisableDevices": "Disable Devices",
"DisableSkeldDevices": "Disable Skeld Devices",
"DisableMiraHQDevices": "Disable MiraHQ Devices",
@@ -1573,7 +1578,9 @@
"HackDuration": "Hack Duration",
"MimicCooldown": "Mimic Cooldown",
"MimicDuration": "Mimic Duration",
"HackedByGlitch": "<color=#ffff00>You are hacked, you can't {0}.</color>",
"RoleBlockNotify": "You are role blocked, you can't {0}",
"RoleBlockDuration": "Role Block Duration",
"RoleBlockCooldown": "Role Block Cooldown",
"BKProtectDuration": "Protection Duration",
"TotocalcioMaxBetTimes": "Maximum Number of Follows",
"TotocalcioBetCooldown": "Follow Cooldown",
@@ -2124,7 +2131,6 @@
"TabGroup.Addons": "Add-Ons",
"TabGroup.OtherRoles": "Ghost Roles",
"TabGroup.TaskSettings": "Game Modifiers",
"TabGroup.CovenRoles": "Coven Roles",
"OtherRoles.CrewmateRoles": "★ Crewmate Roles",
"OtherRoles.NeutralRoles": "★ Neutral Roles",
"OtherRoles.ImpostorRoles": "★ Impostor Roles",
@@ -2309,6 +2315,8 @@
"FarseerKillButtonText": "Reveal",
"PoisonerKillButtonText": "Poison",
"SentryPetButtonText": "Monitor",
"SabotageActiveIndicator": "▶",
"SabotageDisabledIndicator": "⊘",
"DisabledBySettings": "Disabled by Settings",
"Disabled": "Disabled",
"FailToTrack": "Failed To Track",
@@ -2797,7 +2805,6 @@
"Escort": "Escort",
"EscortInfo": "Role-Block Players to Help the Crew!",
"EscortInfoLong": "(Crewmates):\\nAs the Escort, you can role-block a player for a specified time using your kill button. A role-blocked player cannot kill, vent, sabotage or report.\\n(Role-Block duration is the same as the hack duration for The Glitch)",
"EscortCD": "Role-Block Cooldown",
"EscortBlockDuration": "Role-Block Duration",
"EscortTargetHacked": "Target successfully role-blocked",
"EscortKillButtonText": "Role-Block",
+1 -1
View File
@@ -2308,7 +2308,7 @@
"MonarchKillButtonText": "Посвятить",
"FarseerKillButtonText": "Раскрыть",
"SentryPetButtonText": "Сенсор",
"PoisonerKillButtonText": "Отравить"
"PoisonerKillButtonText": "Отравить",
"DisabledBySettings": "Выключено настройками",
"Disabled": "Выключено",
"FailToTrack": "Не удалось отследить",
+1 -1
View File
@@ -1,6 +1,6 @@
namespace EHR.Roles.AddOns.Common
{
internal class Flash : IAddon
internal class Flashman : IAddon
{
public AddonTypes Type => AddonTypes.Helpful;
-5
View File
@@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using EHR.Modules;
using Hazel;
using UnityEngine;
@@ -88,7 +87,6 @@ namespace EHR.Roles.Crewmate
{
TargetArrow.RemoveAllTarget(id);
LocateArrow.RemoveAllTarget(id);
Utils.SendRPC(CustomRPC.SetBloodhoundArrow, id, 1);
}
BloodhoundTargets.Clear();
@@ -105,7 +103,6 @@ namespace EHR.Roles.Crewmate
var pos = target.Pos();
LocateArrow.Add(id, pos);
Utils.SendRPC(CustomRPC.SetBloodhoundArrow, id, 2, pos);
}
}
@@ -120,13 +117,11 @@ namespace EHR.Roles.Crewmate
var pos = target.Object.Pos();
LocateArrow.Remove(pc.PlayerId, pos);
Utils.SendRPC(CustomRPC.SetBloodhoundArrow, pc.PlayerId, 3, pos);
if (pc.GetAbilityUseLimit() >= 1)
{
BloodhoundTargets.Add(killer.PlayerId);
TargetArrow.Add(pc.PlayerId, killer.PlayerId);
Utils.SendRPC(CustomRPC.SetBloodhoundArrow, pc.PlayerId, 4, killer.PlayerId);
pc.Notify(GetString("BloodhoundTrackRecorded"));
pc.RpcRemoveAbilityUse();
+8 -5
View File
@@ -1,6 +1,5 @@
using System.Collections.Generic;
using AmongUs.GameOptions;
using EHR.Roles.Neutral;
using static EHR.Translator;
namespace EHR.Roles.Crewmate
@@ -12,18 +11,24 @@ namespace EHR.Roles.Crewmate
private static OptionItem CD;
private static OptionItem UseLimit;
private static OptionItem Duration;
public static OptionItem UsePet;
public override bool IsEnable => playerIdList.Count > 0;
public static void SetupCustomOption()
{
Options.SetupSingleRoleOptions(Id, TabGroup.CrewmateRoles, CustomRoles.Escort);
CD = FloatOptionItem.Create(Id + 10, "EscortCD", new(2.5f, 60f, 2.5f), 30f, TabGroup.CrewmateRoles)
CD = FloatOptionItem.Create(Id + 10, "RoleBlockCooldown", new(2.5f, 60f, 2.5f), 30f, TabGroup.CrewmateRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Escort])
.SetValueFormat(OptionFormat.Seconds);
UseLimit = IntegerOptionItem.Create(Id + 11, "AbilityUseLimit", new(1, 20, 1), 3, TabGroup.CrewmateRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Escort])
.SetValueFormat(OptionFormat.Times);
UsePet = Options.CreatePetUseSetting(Id + 12, CustomRoles.Escort);
Duration = FloatOptionItem.Create(Id + 13, "RoleBlockDuration", new(1f, 60f, 1f), 15f, TabGroup.CrewmateRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Escort])
.SetValueFormat(OptionFormat.Seconds);
}
public override void Init()
@@ -42,8 +47,6 @@ namespace EHR.Roles.Crewmate
Main.ResetCamPlayerList.Add(playerId);
}
public override bool IsEnable => playerIdList.Count > 0;
public override void SetKillCooldown(byte playerId)
{
Main.AllPlayerKillCooldown[playerId] = playerId.GetAbilityUseLimit() > 0 ? CD.GetFloat() : 300f;
@@ -58,7 +61,7 @@ namespace EHR.Roles.Crewmate
killer.RpcRemoveAbilityUse();
killer.SetKillCooldown();
Glitch.hackedIdList.TryAdd(target.PlayerId, Utils.TimeStamp);
target.BlockRole(Duration.GetFloat());
killer.Notify(GetString("EscortTargetHacked"));
return false;
-30
View File
@@ -1,6 +1,4 @@
using System.Collections.Generic;
using EHR.Modules;
using Hazel;
using UnityEngine;
using static EHR.Options;
@@ -36,32 +34,6 @@ public class Mortician : RoleBase
playerIdList.Add(playerId);
}
private static void SendRPC(byte playerId, bool add, Vector3 loc = new())
{
if (!Utils.DoRPC) return;
MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SetMorticianArrow, SendOption.Reliable);
writer.Write(playerId);
writer.Write(add);
if (add)
{
writer.Write(loc.x);
writer.Write(loc.y);
writer.Write(loc.z);
}
AmongUsClient.Instance.FinishRpcImmediately(writer);
}
public static void ReceiveRPC(MessageReader reader)
{
byte playerId = reader.ReadByte();
bool add = reader.ReadBoolean();
if (add)
LocateArrow.Add(playerId, new(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()));
else
LocateArrow.RemoveAllTarget(playerId);
}
public static void OnPlayerDead(PlayerControl target)
{
var pos = target.Pos();
@@ -84,7 +56,6 @@ public class Mortician : RoleBase
var player = Utils.GetPlayerById(pc);
if (player == null || !player.IsAlive()) continue;
LocateArrow.Add(pc, target.transform.position);
SendRPC(pc, true, target.transform.position);
}
}
@@ -93,7 +64,6 @@ public class Mortician : RoleBase
foreach (byte apc in playerIdList)
{
LocateArrow.RemoveAllTarget(apc);
SendRPC(apc, false);
}
if (!pc.Is(CustomRoles.Mortician) || target == null || pc.PlayerId == target.PlayerId) return;
+2 -2
View File
@@ -271,7 +271,7 @@ namespace EHR.Roles.Crewmate
{
var pc = PickRandomPlayer();
AddEffectForPlayer(pc, effect);
Glitch.hackedIdList.TryAdd(pc.PlayerId, Utils.TimeStamp);
pc.BlockRole(IRandom.Instance.Next(MinimumEffectDuration, MaximumEffectDuration));
NotifyAboutRNG(pc);
}
break;
@@ -281,7 +281,7 @@ namespace EHR.Roles.Crewmate
foreach (var pc in Main.AllAlivePlayerControls)
{
AddEffectForPlayer(pc, effect);
Glitch.hackedIdList.TryAdd(pc.PlayerId, now);
pc.BlockRole(IRandom.Instance.Next(MinimumEffectDuration, MaximumEffectDuration));
NotifyAboutRNG(pc);
}
}
-30
View File
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using AmongUs.GameOptions;
using EHR.Modules;
using Hazel;
using UnityEngine;
using static EHR.Options;
@@ -50,44 +48,17 @@ public class Tracefinder : RoleBase
On = true;
}
private static void SendRPC(byte playerId, bool add, Vector3 loc = new())
{
if (!Utils.DoRPC) return;
MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SetTracefinderArrow, SendOption.Reliable);
writer.Write(playerId);
writer.Write(add);
if (add)
{
writer.Write(loc.x);
writer.Write(loc.y);
writer.Write(loc.z);
}
AmongUsClient.Instance.FinishRpcImmediately(writer);
}
public override void ApplyGameOptions(IGameOptions opt, byte id)
{
AURoleOptions.ScientistCooldown = VitalsCooldown.GetFloat();
AURoleOptions.ScientistBatteryCharge = VitalsDuration.GetFloat();
}
public static void ReceiveRPC(MessageReader reader)
{
byte playerId = reader.ReadByte();
bool add = reader.ReadBoolean();
if (add)
LocateArrow.Add(playerId, new(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()));
else
LocateArrow.RemoveAllTarget(playerId);
}
public override void OnReportDeadBody()
{
foreach (byte apc in playerIdList)
{
LocateArrow.RemoveAllTarget(apc);
SendRPC(apc, false);
}
}
@@ -109,7 +80,6 @@ public class Tracefinder : RoleBase
PlayerControl pc = Utils.GetPlayerById(id);
if (pc == null || !pc.IsAlive()) continue;
LocateArrow.Add(id, target.transform.position);
SendRPC(id, true, target.transform.position);
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
}
}
-1
View File
@@ -77,7 +77,6 @@ namespace EHR.Roles.Crewmate
Utils.GetPlayerById(trackerId).RpcRemoveAbilityUse();
TrackerTarget[trackerId].Add(targetId);
TargetArrow.Add(trackerId, targetId);
}
public static string GetTargetMark(PlayerControl seer, PlayerControl target) => !(seer == null || target == null) && TrackerTarget.ContainsKey(seer.PlayerId) && TrackerTarget[seer.PlayerId].Contains(target.PlayerId) ? Utils.ColorString(seer.GetRoleColor(), "◀") : string.Empty;
-1
View File
@@ -82,7 +82,6 @@ public class BountyHunter : RoleBase
public void ReceiveRPC(byte bountyId, byte targetId)
{
Target = targetId;
if (ShowTargetArrow) TargetArrow.Add(bountyId, targetId);
}
public override bool OnCheckMurder(PlayerControl killer, PlayerControl target)
+8 -5
View File
@@ -1,5 +1,4 @@
using System.Collections.Generic;
using EHR.Roles.Neutral;
using static EHR.Translator;
namespace EHR.Roles.Impostor
@@ -11,16 +10,22 @@ namespace EHR.Roles.Impostor
private static OptionItem CD;
private static OptionItem UseLimit;
private static OptionItem Duration;
public override bool IsEnable => playerIdList.Count > 0;
public static void SetupCustomOption()
{
Options.SetupRoleOptions(Id, TabGroup.ImpostorRoles, CustomRoles.Consort);
CD = FloatOptionItem.Create(Id + 10, "EscortCD", new(2.5f, 60f, 2.5f), 30f, TabGroup.ImpostorRoles)
CD = FloatOptionItem.Create(Id + 10, "RoleBlockCooldown", new(2.5f, 60f, 2.5f), 30f, TabGroup.ImpostorRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Consort])
.SetValueFormat(OptionFormat.Seconds);
UseLimit = IntegerOptionItem.Create(Id + 11, "AbilityUseLimit", new(1, 20, 1), 3, TabGroup.ImpostorRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Consort])
.SetValueFormat(OptionFormat.Times);
Duration = FloatOptionItem.Create(Id + 12, "RoleBlockDuration", new(1f, 60f, 1f), 15f, TabGroup.ImpostorRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Consort])
.SetValueFormat(OptionFormat.Seconds);
}
public override void Init()
@@ -34,8 +39,6 @@ namespace EHR.Roles.Impostor
playerId.SetAbilityUseLimit(UseLimit.GetInt());
}
public override bool IsEnable => playerIdList.Count > 0;
public override bool OnCheckMurder(PlayerControl killer, PlayerControl target)
{
if (!IsEnable || killer == null || target == null) return false;
@@ -44,7 +47,7 @@ namespace EHR.Roles.Impostor
return killer.CheckDoubleTrigger(target, () =>
{
killer.RpcRemoveAbilityUse();
Glitch.hackedIdList.TryAdd(target.PlayerId, Utils.TimeStamp);
target.BlockRole(Duration.GetFloat());
killer.Notify(GetString("EscortTargetHacked"));
killer.SetKillCooldown(CD.GetFloat());
});
+1 -1
View File
@@ -237,7 +237,7 @@ namespace EHR.Roles.Impostor
SendRPCSyncPistolCD();
}
public override string GetProgressText(byte id, bool comms) => string.Format(GetString("MafiosoProgressText"), Tier, XP);
public override string GetProgressText(byte id, bool comms) => id.IsPlayerModClient() ? string.Empty : string.Format(GetString("MafiosoProgressText"), Tier, XP);
public override string GetSuffix(PlayerControl pc, PlayerControl _, bool hud = false, bool m = false)
{
+1
View File
@@ -136,6 +136,7 @@ namespace EHR.Roles.Impostor
public override string GetSuffix(PlayerControl seer, PlayerControl target, bool hud = false, bool m = false)
{
if (seer.IsModClient() && !hud) return string.Empty;
if (Main.PlayerStates[seer.PlayerId].Role is YinYanger { IsEnable: true } yy && seer.PlayerId == target.PlayerId)
{
return yy.YinYangedPlayers.Count == 2 ? $"<color=#00ffa5>{Translator.GetString("Mode")}:</color> {Translator.GetString("YinYangModeNormal")}" : $"<color=#00ffa5>{Translator.GetString("Mode")}:</color> {Translator.GetString("YinYangMode")} ({yy.YinYangedPlayers.Count}/2)";
+1 -19
View File
@@ -14,8 +14,6 @@ public class Glitch : RoleBase
private const int Id = 18125;
public static List<byte> playerIdList = [];
public static Dictionary<byte, long> hackedIdList = [];
public static OptionItem KillCooldown;
public static OptionItem HackCooldown;
public static OptionItem HackDuration;
@@ -62,7 +60,6 @@ public class Glitch : RoleBase
public override void Init()
{
playerIdList = [];
hackedIdList = [];
GlitchId = byte.MaxValue;
}
@@ -168,7 +165,7 @@ public class Glitch : RoleBase
{
Utils.NotifyRoles(SpecifySeer: killer, SpecifyTarget: target);
HackCDTimer = HackCooldown.GetInt();
hackedIdList.TryAdd(target.PlayerId, Utils.TimeStamp);
target.BlockRole(HackDuration.GetFloat());
LastHack = Utils.TimeStamp;
SendRPCSyncTimers();
}
@@ -195,23 +192,8 @@ public class Glitch : RoleBase
if (MimicCDTimer is > 180 or < 0) MimicCDTimer = 0;
if (MimicDurTimer is > 180 or < 0) MimicDurTimer = 0;
bool change = false;
foreach (var pc in hackedIdList)
{
if (pc.Value + HackDuration.GetInt() < now)
{
hackedIdList.Remove(pc.Key);
change = true;
}
}
if (player == null) return;
if (change)
{
Utils.NotifyRoles(SpecifySeer: player);
}
if (!player.IsAlive())
{
HackCDTimer = 0;
-32
View File
@@ -1,8 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using AmongUs.GameOptions;
using EHR.Modules;
using Hazel;
using UnityEngine;
using static EHR.Options;
using static EHR.Translator;
@@ -91,38 +89,11 @@ public class Vulture : RoleBase
AURoleOptions.EngineerInVentMaxTime = 0f;
}
private static void SendRPC(byte playerId, bool add, Vector3 loc = new())
{
if (!Utils.DoRPC) return;
MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SetVultureArrow, SendOption.Reliable);
writer.Write(playerId);
writer.Write(add);
if (add)
{
writer.Write(loc.x);
writer.Write(loc.y);
writer.Write(loc.z);
}
AmongUsClient.Instance.FinishRpcImmediately(writer);
}
public static void ReceiveRPC(MessageReader reader)
{
byte playerId = reader.ReadByte();
bool add = reader.ReadBoolean();
if (add)
LocateArrow.Add(playerId, new(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()));
else
LocateArrow.RemoveAllTarget(playerId);
}
public static void Clear()
{
foreach (byte apc in playerIdList)
{
LocateArrow.RemoveAllTarget(apc);
SendRPC(apc, false);
}
}
@@ -144,7 +115,6 @@ public class Vulture : RoleBase
Utils.GetPlayerById(apc).Notify(GetString("VultureCooldownUp"));
}
}, VultureReportCD.GetFloat(), "Vulture CD");
SendRPC(apc, false);
Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: player);
}
}
@@ -159,7 +129,6 @@ public class Vulture : RoleBase
var player = Utils.GetPlayerById(pc);
if (player == null || !player.IsAlive()) continue;
LocateArrow.Add(pc, target.transform.position);
SendRPC(pc, true, target.transform.position);
Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: player);
}
}
@@ -177,7 +146,6 @@ public class Vulture : RoleBase
foreach (byte apc in playerIdList)
{
LocateArrow.Remove(apc, target.Object.transform.position);
SendRPC(apc, false);
}
}
+2 -2
View File
@@ -28,8 +28,8 @@ public class Main : BasePlugin
public const string DebugKeyHash = "c0fd562955ba56af3ae20d7ec9e64c664f0facecef4b3e366e109306adeae29d";
public const string DebugKeySalt = "59687b";
public const string PluginGuid = "com.gurge44.endlesshostroles";
public const string PluginVersion = "3.3.0";
public const string PluginDisplayVersion = "3.3.0";
public const string PluginVersion = "3.4.0";
public const string PluginDisplayVersion = "3.4.0";
public const string NeutralColor = "#ffab1b";
public const string ImpostorColor = "#ff1919";
public const string CrewmateColor = "#8cffff";