Save & Load Combo Data + Fix Bugs

This commit is contained in:
Gurge44 committed 2024-06-09 18:27:25 +02:00
1 parent 6908056940
commit 405c0e9c93
29 files changed
+262 -122

No files matched your search

+1 -1
View File
@@ -223,7 +223,7 @@ namespace EHR
if (result.ContainsValue(CustomRoles.Agent))
{
var agent = result.GetKeyByValue(CustomRoles.Agent).PlayerId;
PlayerRoles.DoIf(x => x.Value.Role != CustomRoles.Agent && x.Value.Interface.Team == Team.Impostor, x => TargetArrow.Add(x.Key, agent));
PlayerRoles.DoIf(x => x.Value.Role != CustomRoles.Agent && x.Value.Interface.Team == Team.Impostor, x => TargetArrow.Add(x.Key, agent), fast: true);
}
}
+17 -8
View File
@@ -75,7 +75,7 @@ namespace EHR.Modules
foreach ((CustomTeam team, HashSet<byte> players) in CustomTeamPlayerIds)
{
if (!IsSettingEnabledForTeam(team, "Arrows")) continue;
if (!IsSettingEnabledForTeam(team, CTAOption.Arrows)) continue;
foreach (byte player in players)
{
@@ -90,7 +90,7 @@ namespace EHR.Modules
public static string GetSuffix(PlayerControl seer)
{
if (seer == null || EnabledCustomTeams.Count == 0 || !IsSettingEnabledForPlayerTeam(seer.PlayerId, "Arrows")) return string.Empty;
if (seer == null || EnabledCustomTeams.Count == 0 || !IsSettingEnabledForPlayerTeam(seer.PlayerId, CTAOption.Arrows)) return string.Empty;
return CustomTeamPlayerIds[GetCustomTeam(seer.PlayerId)].Aggregate(string.Empty, (s, id) => s + Utils.ColorString(Main.PlayerColors.GetValueOrDefault(id, Color.white), TargetArrow.GetArrows(seer, id)));
}
@@ -142,18 +142,17 @@ namespace EHR.Modules
return team1 != null && team2 != null && team1.Equals(team2);
}
public static bool IsSettingEnabledForPlayerTeam(byte id, string settingName)
public static bool IsSettingEnabledForPlayerTeam(byte id, CTAOption setting)
{
var team = GetCustomTeam(id);
return team != null && IsSettingEnabledForTeam(team, settingName);
return team != null && IsSettingEnabledForTeam(team, setting);
}
public static bool IsSettingEnabledForTeam(CustomTeam team, string settingName)
public static bool IsSettingEnabledForTeam(CustomTeam team, CTAOption setting)
{
var optionsGroup = CustomTeamOptions.First(x => x.Team.Equals(team));
var setting = optionsGroup.GetType().GetFields().FirstOrDefault(x => x.Name.Contains(settingName));
if (setting == null) return false;
return setting.GetValue(optionsGroup) as bool? ?? false;
var values = optionsGroup.AllOptions.ConvertAll(x => x.GetBool());
return values[(int)setting];
}
internal class CustomTeam
@@ -210,4 +209,14 @@ namespace EHR.Modules
public BooleanOptionItem Arrows { get; set; } = arrows;
}
}
public enum CTAOption
{
Enabled,
KnowRoles,
WinWithOriginalTeam,
KillEachOther,
GuessEachOther,
Arrows
}
}
+1 -1
View File
@@ -79,7 +79,7 @@ class Logger
string memberName = stack.GetMethod()?.Name;
log_text = $"[{t}][{className}.{memberName}({Path.GetFileName(fileName)}:{lineNumber})][{tag}]{text}";
NowDetailedErrorLog.Add(tag);
LateTask.New(() => NowDetailedErrorLog.Remove(tag), 5f, log: false);
LateTask.New(() => NowDetailedErrorLog.Remove(tag), 3f, log: false);
}
else
{
+8 -8
View File
@@ -178,21 +178,21 @@ public class RemoveDisableDevicesPatch
if (Options.DisableSkeldAdmin.GetBool() || rogueForce)
admins[0].gameObject.GetComponent<CircleCollider2D>().enabled = ignore;
if (Options.DisableSkeldCamera.GetBool() || rogueForce)
consoles.DoIf(x => x.name == "SurvConsole", x => x.gameObject.GetComponent<PolygonCollider2D>().enabled = ignore);
consoles.DoIf(x => x.name == "SurvConsole", x => x.gameObject.GetComponent<PolygonCollider2D>().enabled = ignore, fast: true);
break;
case 1:
if (Options.DisableMiraHQAdmin.GetBool() || rogueForce)
admins[0].gameObject.GetComponent<CircleCollider2D>().enabled = ignore;
if (Options.DisableMiraHQDoorLog.GetBool() || rogueForce)
consoles.DoIf(x => x.name == "SurvLogConsole", x => x.gameObject.GetComponent<BoxCollider2D>().enabled = ignore);
consoles.DoIf(x => x.name == "SurvLogConsole", x => x.gameObject.GetComponent<BoxCollider2D>().enabled = ignore, fast: true);
break;
case 2:
if (Options.DisablePolusAdmin.GetBool() || rogueForce)
admins.Do(x => x.gameObject.GetComponent<BoxCollider2D>().enabled = ignore);
if (Options.DisablePolusCamera.GetBool() || rogueForce)
consoles.DoIf(x => x.name == "Surv_Panel", x => x.gameObject.GetComponent<BoxCollider2D>().enabled = ignore);
consoles.DoIf(x => x.name == "Surv_Panel", x => x.gameObject.GetComponent<BoxCollider2D>().enabled = ignore, fast: true);
if (Options.DisablePolusVital.GetBool() || rogueForce)
consoles.DoIf(x => x.name == "panel_vitals", x => x.gameObject.GetComponent<BoxCollider2D>().enabled = ignore);
consoles.DoIf(x => x.name == "panel_vitals", x => x.gameObject.GetComponent<BoxCollider2D>().enabled = ignore, fast: true);
break;
case 4:
admins.Do(x =>
@@ -202,15 +202,15 @@ public class RemoveDisableDevicesPatch
x.gameObject.GetComponent<BoxCollider2D>().enabled = ignore;
});
if (Options.DisableAirshipCamera.GetBool() || rogueForce)
consoles.DoIf(x => x.name == "task_cams", x => x.gameObject.GetComponent<BoxCollider2D>().enabled = ignore);
consoles.DoIf(x => x.name == "task_cams", x => x.gameObject.GetComponent<BoxCollider2D>().enabled = ignore, fast: true);
if (Options.DisableAirshipVital.GetBool() || rogueForce)
consoles.DoIf(x => x.name == "panel_vitals", x => x.gameObject.GetComponent<CircleCollider2D>().enabled = ignore);
consoles.DoIf(x => x.name == "panel_vitals", x => x.gameObject.GetComponent<CircleCollider2D>().enabled = ignore, fast: true);
break;
case 5:
if (Options.DisableFungleCamera.GetBool() || rogueForce)
consoles.DoIf(x => x.name == "BinocularsSecurityConsole", x => x.gameObject.GetComponent<PolygonCollider2D>().enabled = ignore);
consoles.DoIf(x => x.name == "BinocularsSecurityConsole", x => x.gameObject.GetComponent<PolygonCollider2D>().enabled = ignore, fast: true);
if (Options.DisableFungleCamera.GetBool() || rogueForce)
consoles.DoIf(x => x.name == "VitalsConsole", x => x.gameObject.GetComponent<BoxCollider2D>().enabled = ignore);
consoles.DoIf(x => x.name == "VitalsConsole", x => x.gameObject.GetComponent<BoxCollider2D>().enabled = ignore, fast: true);
break;
}
}
+15 -1
View File
@@ -83,11 +83,25 @@ namespace EHR
/// Executes an action for each element in a collection if the predicate is true
/// </summary>
/// <param name="collection">The collection to iterate over</param>
/// <param name="fast">Whether to use a fast loop or linq</param>
/// <param name="predicate">The predicate to check for each element</param>
/// <param name="action">The action to execute for each element that satisfies the predicate</param>
/// <typeparam name="T">The type of the elements in the collection</typeparam>
public static void DoIf<T>(this IEnumerable<T> collection, Func<T, bool> predicate, Action<T> action)
public static void DoIf<T>(this IEnumerable<T> collection, Func<T, bool> predicate, Action<T> action, bool fast = false)
{
if (fast)
{
foreach (T element in collection)
{
if (predicate(element))
{
action(element);
}
}
return;
}
var partitioner = Partitioner.Create(collection.Where(predicate));
partitioner.GetDynamicPartitions().Do(action);
}
@@ -1,6 +1,7 @@
using System;
using System.Linq;
using AmongUs.GameOptions;
using EHR.Neutral;
using EHR.Roles.AddOns.GhostRoles;
using EHR.Roles.Crewmate;
using EHR.Roles.Impostor;
@@ -195,6 +196,8 @@ public class PlayerGameOptionsSender(PlayerControl player) : GameOptionsSender
break;
}
if (Shifter.WasShifter.Contains(player.PlayerId) && role.IsImpostor()) opt.SetVision(true);
Main.PlayerStates[player.PlayerId].Role.ApplyGameOptions(opt, player.PlayerId);
if (Main.AllPlayerControls.Any(x => x.Is(CustomRoles.Bewilder) && !x.IsAlive() && x.GetRealKiller()?.PlayerId == player.PlayerId && !x.Is(CustomRoles.Hangman)))
+1 -2
View File
@@ -250,8 +250,7 @@ public class PlayerState(byte playerId)
public void RemoveSubRole(CustomRoles role)
{
if (SubRoles.Contains(role))
SubRoles.Remove(role);
SubRoles.Remove(role);
if (role is CustomRoles.Flashman or CustomRoles.Dynamo)
{
+7 -7
View File
@@ -186,7 +186,7 @@ public static class GuessManager
return true;
}
if (CustomTeamManager.AreInSameCustomTeam(pc.PlayerId, targetId) && !CustomTeamManager.IsSettingEnabledForPlayerTeam(targetId, "GuessEachOther"))
if (CustomTeamManager.AreInSameCustomTeam(pc.PlayerId, targetId) && !CustomTeamManager.IsSettingEnabledForPlayerTeam(targetId, CTAOption.GuessEachOther))
{
if (!isUI) Utils.SendMessage(GetString("GuessSameCTAPlayer"), pc.PlayerId);
else pc.ShowPopUp(GetString("GuessSameCTAPlayer"));
@@ -237,8 +237,8 @@ public static class GuessManager
case CustomRoles.Doomsayer:
if (Doomsayer.CantGuess)
{
if (!isUI) Utils.SendMessage(GetString("DommsayerCantGuess"), pc.PlayerId);
else pc.ShowPopUp(GetString("DommsayerCantGuess"));
if (!isUI) Utils.SendMessage(GetString("DoomsayerCantGuess"), pc.PlayerId);
else pc.ShowPopUp(GetString("DoomsayerCantGuess"));
return true;
}
@@ -357,8 +357,8 @@ public static class GuessManager
if (Jailor.playerIdList.Any(x => Main.PlayerStates[x].Role is Jailor { IsEnable: true } jl && jl.JailorTarget == target.PlayerId))
{
if (!isUI) Utils.SendMessage(GetString("Can'tGuessJailed"), pc.PlayerId, title: Utils.ColorString(Utils.GetRoleColor(CustomRoles.Jailor), GetString("JailorTitle")));
else pc.ShowPopUp(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Jailor), GetString("JailorTitle")) + "\n" + GetString("Can'tGuessJailed"));
if (!isUI) Utils.SendMessage(GetString("CantGuessJailed"), pc.PlayerId, title: Utils.ColorString(Utils.GetRoleColor(CustomRoles.Jailor), GetString("JailorTitle")));
else pc.ShowPopUp(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Jailor), GetString("JailorTitle")) + "\n" + GetString("CantGuessJailed"));
return true;
}
@@ -482,8 +482,8 @@ public static class GuessManager
{
if (Doomsayer.GuessesCountPerMeeting >= Doomsayer.MaxNumberOfGuessesPerMeeting.GetInt() && pc.PlayerId != dp.PlayerId)
{
if (!isUI) Utils.SendMessage(GetString("DommsayerCantGuess"), pc.PlayerId);
else pc.ShowPopUp(GetString("DommsayerCantGuess"));
if (!isUI) Utils.SendMessage(GetString("DoomsayerCantGuess"), pc.PlayerId);
else pc.ShowPopUp(GetString("DoomsayerCantGuess"));
return true;
}
+2 -2
View File
@@ -71,7 +71,7 @@ public static class NameColorManager
}
// Custom Teams
if (CustomTeamManager.AreInSameCustomTeam(seer.PlayerId, target.PlayerId) && CustomTeamManager.IsSettingEnabledForPlayerTeam(seer.PlayerId, "KnowRoles")) color = Main.RoleColors[target.GetCustomRole()];
if (CustomTeamManager.AreInSameCustomTeam(seer.PlayerId, target.PlayerId) && CustomTeamManager.IsSettingEnabledForPlayerTeam(seer.PlayerId, CTAOption.KnowRoles)) color = Main.RoleColors[target.GetCustomRole()];
// Add-ons
if (target.Is(CustomRoles.Glow) && Utils.IsActive(SystemTypes.Electrical)) color = Main.RoleColors[CustomRoles.Glow];
@@ -199,7 +199,7 @@ public static class NameColorManager
|| seer.Is(CustomRoles.GM)
|| seer.Is(CustomRoles.God)
|| (seer.Is(CustomRoleTypes.Impostor) && target.Is(CustomRoleTypes.Impostor))
|| (seer.Is(CustomRoles.Traitor) && target.Is(CustomRoleTypes.Impostor))
|| (seer.Is(CustomRoles.Traitor) && target.Is(Team.Impostor))
|| (seer.Is(CustomRoles.Jackal) && target.Is(CustomRoles.Sidekick))
|| (seer.Is(CustomRoles.Sidekick) && target.Is(CustomRoles.Sidekick))
|| (seer.Is(CustomRoles.Sidekick) && target.Is(CustomRoles.Jackal))
+21 -12
View File
@@ -313,17 +313,21 @@ public static class Utils
public static void SaveComboInfo()
{
SaveFile("./EHR_Data/AlwaysCombos.json");
SaveFile("./EHR_Data/NeverCombos.json");
SaveFile("./EHR_DATA/AlwaysCombos.json");
SaveFile("./EHR_DATA/NeverCombos.json");
return;
void SaveFile(string path)
{
try
{
var data = new Il2CppSystem.Collections.Generic.Dictionary<string, List<int>>();
var data = new Il2CppSystem.Collections.Generic.Dictionary<string, Il2CppSystem.Collections.Generic.List<int>>();
var dict = path.Contains("Always") ? Main.AlwaysSpawnTogetherCombos : Main.NeverSpawnTogetherCombos;
dict.Do(pair => data[pair.Key.ToString()] = pair.Value.ConvertAll(x => (int)x));
dict.Do(pair =>
{
data[pair.Key.ToString()] = new();
pair.Value.Do(x => data[pair.Key.ToString()].Add((int)x));
});
File.WriteAllText(path, JsonConvert.SerializeObject(data, Formatting.Indented));
}
catch (Exception e)
@@ -336,8 +340,8 @@ public static class Utils
public static void LoadComboInfo()
{
LoadFile("./EHR_Data/AlwaysCombos.json");
LoadFile("./EHR_Data/NeverCombos.json");
LoadFile("./EHR_DATA/AlwaysCombos.json");
LoadFile("./EHR_DATA/NeverCombos.json");
return;
void LoadFile(string path)
@@ -345,13 +349,17 @@ public static class Utils
try
{
if (!File.Exists(path)) return;
var data = JsonConvert.DeserializeObject<Il2CppSystem.Collections.Generic.Dictionary<string, List<int>>>(File.ReadAllText(path));
var data = JsonConvert.DeserializeObject<Il2CppSystem.Collections.Generic.Dictionary<string, Il2CppSystem.Collections.Generic.List<int>>>(File.ReadAllText(path));
var dict = path.Contains("Always") ? Main.AlwaysSpawnTogetherCombos : Main.NeverSpawnTogetherCombos;
dict.Clear();
foreach (var pair in data)
{
var key = Enum.Parse<CustomRoles>(pair.Key);
dict[key] = pair.Value.ConvertAll(x => (CustomRoles)x);
dict[key] = [];
foreach (var n in pair.Value)
{
dict[key].Add((CustomRoles)n);
}
}
}
catch (Exception e)
@@ -423,12 +431,12 @@ public static class Utils
var self = seerId == targetId || Main.PlayerStates[seerId].IsDead;
bool isHnsAgentOverride = Options.CurrentGameMode == CustomGameMode.HideAndSeek && targetMainRole == CustomRoles.Agent && HnSManager.PlayerRoles[seerId].Interface.Team != Team.Impostor;
if (targetMainRole == CustomRoles.LovingImpostor)
if (!GameStates.IsEnded && targetMainRole == CustomRoles.LovingImpostor && !self && seerMainRole != CustomRoles.LovingCrewmate && !seerSubRoles.Contains(CustomRoles.Lovers))
{
targetMainRole = Lovers.LovingImpostorRoleForOtherImps.GetValue() switch
{
0 => CustomRoles.ImpostorEHR,
1 => Enum.GetValues<CustomRoles>().Where(x => x.IsEnable() && x.IsImpostor() && x != CustomRoles.LovingImpostor && !HnSManager.AllHnSRoles.Contains(x)).Shuffle()[0],
1 => Lovers.LovingImpostorRole,
_ => CustomRoles.LovingImpostor
};
}
@@ -826,7 +834,7 @@ public static class Utils
__instance.Is(CustomRoleTypes.Impostor) && PlayerControl.LocalPlayer.Is(CustomRoles.Crewpostor) && Options.AlliesKnowCrewpostor.GetBool() ||
__instance.Is(CustomRoleTypes.Impostor) && PlayerControl.LocalPlayer.Is(CustomRoleTypes.Impostor) && Options.ImpKnowAlliesRole.GetBool() ||
__instance.Is(CustomRoleTypes.Impostor) && PlayerControl.LocalPlayer.Is(CustomRoles.Madmate) && Options.MadmateKnowWhosImp.GetBool() ||
CustomTeamManager.AreInSameCustomTeam(__instance.PlayerId, PlayerControl.LocalPlayer.PlayerId) && CustomTeamManager.IsSettingEnabledForPlayerTeam(__instance.PlayerId, "KnowRoles") ||
CustomTeamManager.AreInSameCustomTeam(__instance.PlayerId, PlayerControl.LocalPlayer.PlayerId) && CustomTeamManager.IsSettingEnabledForPlayerTeam(__instance.PlayerId, CTAOption.KnowRoles) ||
Main.PlayerStates.Values.Any(x => x.Role.KnowRole(PlayerControl.LocalPlayer, __instance)) ||
PlayerControl.LocalPlayer.IsRevealedPlayer(__instance) ||
PlayerControl.LocalPlayer.Is(CustomRoles.God) ||
@@ -1984,6 +1992,7 @@ public static class Utils
if (seer.Is(CustomRoles.Sonar)) SelfSuffix.Append(Sonar.GetSuffix(seer, isForMeeting));
SelfSuffix.Append(Bloodmoon.GetSuffix(seer));
SelfSuffix.Append(Haunter.GetSuffix(seer));
switch (seer.GetCustomRole())
{
@@ -2230,7 +2239,7 @@ public static class Utils
(target.Is(CustomRoles.Mayor) && Mayor.MayorRevealWhenDoneTasks.GetBool() && target.GetTaskState().IsTaskFinished) ||
(seer.Is(CustomRoleTypes.Crewmate) && target.Is(CustomRoles.Marshall) && target.GetTaskState().IsTaskFinished) ||
(Main.PlayerStates[target.PlayerId].deathReason == PlayerState.DeathReason.Vote && Options.SeeEjectedRolesInMeeting.GetBool()) ||
CustomTeamManager.AreInSameCustomTeam(seer.PlayerId, target.PlayerId) && CustomTeamManager.IsSettingEnabledForPlayerTeam(seer.PlayerId, "KnowRoles") ||
CustomTeamManager.AreInSameCustomTeam(seer.PlayerId, target.PlayerId) && CustomTeamManager.IsSettingEnabledForPlayerTeam(seer.PlayerId, CTAOption.KnowRoles) ||
Main.PlayerStates.Values.Any(x => x.Role.KnowRole(seer, target)) ||
Markseeker.PlayerIdList.Any(x => Main.PlayerStates[x].Role is Markseeker { IsEnable: true, TargetRevealed: true } ms && ms.MarkedId == target.PlayerId) ||
Options.CurrentGameMode is CustomGameMode.FFA or CustomGameMode.MoveAndStop or CustomGameMode.HotPotato ||
+1 -2
View File
@@ -55,9 +55,8 @@ public static class Zoom
Flag.Run(() => { SetZoomSize(reset: true); }, "Zoom");
}
}
catch (Exception e)
catch
{
Utils.ThrowException(e);
}
}
+25 -4
View File
@@ -755,7 +755,20 @@ internal class ChatCommands
goto Canceled;
}
if ((PlayerControl.LocalPlayer.IsAlive() || ExileController.Instance) && Lovers.PrivateChat.GetBool() && (ExileController.Instance || !GameStates.IsMeeting)) goto Canceled;
if (GameStates.IsInGame && ((PlayerControl.LocalPlayer.IsAlive() || ExileController.Instance) && Lovers.PrivateChat.GetBool() && (ExileController.Instance || !GameStates.IsMeeting)))
{
if (PlayerControl.LocalPlayer.Is(CustomRoles.Lovers) || PlayerControl.LocalPlayer.GetCustomRole() is CustomRoles.LovingCrewmate or CustomRoles.LovingImpostor)
{
var otherLover = Main.LoversPlayers.First(x => x.PlayerId != PlayerControl.LocalPlayer.PlayerId);
var title = PlayerControl.LocalPlayer.GetRealName();
ChatUpdatePatch.LoversMessage = true;
Utils.SendMessage(text, otherLover.PlayerId, title);
Utils.SendMessage(text, PlayerControl.LocalPlayer.PlayerId, title);
LateTask.New(() => ChatUpdatePatch.LoversMessage = false, 1f, log: false);
}
goto Canceled;
}
goto Skip;
Canceled:
@@ -1382,14 +1395,21 @@ internal class ChatCommands
return;
}
if (GameStates.IsInGame && ((player.IsAlive() || ExileController.Instance) && Lovers.PrivateChat.GetBool() && (ExileController.Instance || !GameStates.IsMeeting)))
if (GameStates.IsInGame && !ChatUpdatePatch.LoversMessage && ((player.IsAlive() || ExileController.Instance) && Lovers.PrivateChat.GetBool() && (ExileController.Instance || !GameStates.IsMeeting)))
{
ChatManager.SendPreviousMessagesToAll();
ChatManager.SendPreviousMessagesToAll(clear: true);
canceled = true;
if (player.Is(CustomRoles.Lovers) || player.GetCustomRole() is CustomRoles.LovingCrewmate or CustomRoles.LovingImpostor)
{
var otherLover = Main.LoversPlayers.First(x => x.PlayerId != player.PlayerId);
LateTask.New(() => Utils.SendMessage(text, otherLover.PlayerId, player.GetRealName()), 0.5f, log: false);
LateTask.New(() =>
{
var title = player.GetRealName();
ChatUpdatePatch.LoversMessage = true;
Utils.SendMessage(text, otherLover.PlayerId, title);
Utils.SendMessage(text, player.PlayerId, title);
LateTask.New(() => ChatUpdatePatch.LoversMessage = false, 1f, log: false);
}, 0.5f, log: false);
}
}
@@ -1402,6 +1422,7 @@ internal class ChatCommands
internal class ChatUpdatePatch
{
public static bool DoBlockChat;
public static bool LoversMessage;
public static void Postfix(ChatController __instance)
{
+20 -25
View File
@@ -198,7 +198,7 @@ public static class ChatManager
}
}
public static void SendPreviousMessagesToAll(bool realMessagesOnly = false)
public static void SendPreviousMessagesToAll(bool clear = false)
{
if (!AmongUsClient.Instance.AmHost || !GameStates.IsModHost) return;
ChatUpdatePatch.DoBlockChat = true;
@@ -209,36 +209,31 @@ public static class ChatManager
var filtered = ChatHistory.Where(a => Utils.GetPlayerById(Convert.ToByte(a.Split(':')[0].Trim())).IsAlive()).ToArray();
switch (realMessagesOnly)
for (int i = clear ? 0 : filtered.Length; i < 20; i++)
{
case true when filtered.Length < 5:
return;
case false:
for (int i = filtered.Length; i < 20; i++)
{
var player = x[r.Next(0, totalAlive)];
DestroyableSingleton<HudManager>.Instance.Chat.AddChat(player, msg);
SendRPC(player, msg);
}
break;
var player = x[r.Next(0, totalAlive)];
DestroyableSingleton<HudManager>.Instance.Chat.AddChat(player, msg);
SendRPC(player, msg);
}
foreach (string str in filtered)
if (!clear)
{
var entryParts = str.Split(':');
var senderId = entryParts[0].Trim();
var senderMessage = entryParts[1].Trim();
for (int j = 2; j < entryParts.Length; j++)
foreach (string str in filtered)
{
senderMessage += ':' + entryParts[j].Trim();
var entryParts = str.Split(':');
var senderId = entryParts[0].Trim();
var senderMessage = entryParts[1].Trim();
for (int j = 2; j < entryParts.Length; j++)
{
senderMessage += ':' + entryParts[j].Trim();
}
var senderPlayer = Utils.GetPlayerById(Convert.ToByte(senderId));
if (senderPlayer == null) continue;
DestroyableSingleton<HudManager>.Instance.Chat.AddChat(senderPlayer, senderMessage);
SendRPC(senderPlayer, senderMessage);
}
var senderPlayer = Utils.GetPlayerById(Convert.ToByte(senderId));
if (senderPlayer == null) continue;
DestroyableSingleton<HudManager>.Instance.Chat.AddChat(senderPlayer, senderMessage);
SendRPC(senderPlayer, senderMessage);
}
ChatUpdatePatch.DoBlockChat = false;
+1 -1
View File
@@ -237,7 +237,7 @@ class GameEndChecker
.Where(x => x.Team != null)
.GroupBy(x => x.Team)
.ToDictionary(x => x.Key, x => x.Select(y => y.Player.PlayerId))
.DoIf(x => !CustomTeamManager.IsSettingEnabledForTeam(x.Key, "WinWithOriginalTeam"), x => WinnerIds.ExceptWith(x.Value));
.DoIf(x => !CustomTeamManager.IsSettingEnabledForTeam(x.Key, CTAOption.WinWithOriginalTeam), x => WinnerIds.ExceptWith(x.Value), fast: true);
}
if ((WinnerTeam == CustomWinner.Lovers || WinnerIds.Any(x => Main.PlayerStates[x].SubRoles.Contains(CustomRoles.Lovers))) && Main.LoversPlayers.All(x => x.IsAlive()))
+4 -1
View File
@@ -1,6 +1,7 @@
using System;
using System.Linq;
using AmongUs.Data;
using EHR.Roles.AddOns.Common;
using EHR.Roles.AddOns.Crewmate;
using EHR.Roles.AddOns.Impostor;
using EHR.Roles.Crewmate;
@@ -184,6 +185,8 @@ class ExileControllerWrapUpPatch
SoundManager.Instance.ChangeAmbienceVolume(DataManager.Settings.Audio.AmbienceVolume);
Logger.Info("Start task phase", "Phase");
if (!Lovers.IsChatActivated && Lovers.PrivateChat.GetBool()) return;
bool showRemainingKillers = Options.EnableKillerLeftCommand.GetBool() && Options.ShowImpRemainOnEject.GetBool();
bool appendEjectionNotify = CheckForEndVotingPatch.EjectionText != string.Empty;
Logger.Warn($"Ejection Text: {CheckForEndVotingPatch.EjectionText}", "ExilePatch");
@@ -214,7 +217,7 @@ class ExileControllerWrapUpPatch
}, 0.5f, log: false);
}
LateTask.New(() => { ChatManager.SendPreviousMessagesToAll(); }, 3f, log: false);
LateTask.New(() => ChatManager.SendPreviousMessagesToAll(), 3f, log: false);
}
[HarmonyPatch(typeof(ExileController), nameof(ExileController.WrapUp))]
+4
View File
@@ -45,20 +45,24 @@ public static class GameOptionsMenuPatch
{
case StringNames.GameVotingTime:
ob.Cast<NumberOption>().ValidRange = new(0, 600);
ob.Cast<NumberOption>().Value = (float)Math.Round(ob.Cast<NumberOption>().Value, 2);
break;
case StringNames.GameShortTasks:
case StringNames.GameLongTasks:
case StringNames.GameCommonTasks:
ob.Cast<NumberOption>().ValidRange = new(0, 90);
ob.Cast<NumberOption>().Value = (float)Math.Round(ob.Cast<NumberOption>().Value, 2);
break;
case StringNames.GameKillCooldown:
ob.Cast<NumberOption>().ValidRange = new(0, 180);
ob.Cast<NumberOption>().Increment = 0.5f;
ob.Cast<NumberOption>().Value = (float)Math.Round(ob.Cast<NumberOption>().Value, 2);
break;
case StringNames.GamePlayerSpeed:
case StringNames.GameCrewLight:
case StringNames.GameImpostorLight:
ob.Cast<NumberOption>().Increment = 0.05f;
ob.Cast<NumberOption>().Value = (float)Math.Round(ob.Cast<NumberOption>().Value, 2);
break;
}
}
+2 -2
View File
@@ -810,7 +810,7 @@ class MeetingHudStartPatch
(pc.Is(CustomRoles.Mayor) && Mayor.MayorRevealWhenDoneTasks.GetBool() && pc.GetTaskState().IsTaskFinished) ||
(pc.Is(CustomRoles.Marshall) && PlayerControl.LocalPlayer.Is(CustomRoleTypes.Crewmate) && pc.GetTaskState().IsTaskFinished) ||
(Main.PlayerStates[pc.PlayerId].deathReason == PlayerState.DeathReason.Vote && Options.SeeEjectedRolesInMeeting.GetBool()) ||
CustomTeamManager.AreInSameCustomTeam(pc.PlayerId, PlayerControl.LocalPlayer.PlayerId) && CustomTeamManager.IsSettingEnabledForPlayerTeam(pc.PlayerId, "KnowRoles") ||
CustomTeamManager.AreInSameCustomTeam(pc.PlayerId, PlayerControl.LocalPlayer.PlayerId) && CustomTeamManager.IsSettingEnabledForPlayerTeam(pc.PlayerId, CTAOption.KnowRoles) ||
Main.PlayerStates.Values.Any(x => x.Role.KnowRole(PlayerControl.LocalPlayer, pc)) ||
Markseeker.PlayerIdList.Any(x => Main.PlayerStates[x].Role is Markseeker { IsEnable: true, TargetRevealed: true } ms && ms.MarkedId == pc.PlayerId) ||
PlayerControl.LocalPlayer.IsRevealedPlayer(pc) ||
@@ -1034,7 +1034,7 @@ class MeetingHudUpdatePatch
Logger.Info($"{player.GetNameWithRole().RemoveHtmlTags()}を処刑しました", "Execution");
__instance.CheckForEndVoting();
}
});
}, fast: true);
}
if (!GameStates.IsVoting && __instance.lastSecond < 1)
+12 -1
View File
@@ -300,6 +300,7 @@ internal class ChangeRoleSettings
Asthmatic.Init();
DoubleShot.Init();
Circumvent.Init();
Lovers.Init();
}
catch (Exception ex)
{
@@ -603,13 +604,23 @@ internal class SelectRolesPatch
if (!overrideLovers && CustomRoles.Lovers.IsEnable() && (CustomRoles.FFF.IsEnable() ? -1 : rd.Next(1, 100)) <= Lovers.LoverSpawnChances.GetInt()) AssignLoversRolesFromList();
// Add-on assignment
var aapc = Main.AllAlivePlayerControls;
var addonNum = aapc.ToDictionary(x => x, _ => 0);
AddonRolesList
.Where(x => x.IsEnable())
.SelectMany(x => Enumerable.Repeat(x, Math.Clamp(x.GetCount(), 0, aapc.Length)))
.Shuffle()
.Chunk(aapc.Length)
.Do(c => c.Zip(aapc).DoIf(x => CustomRolesHelper.CheckAddonConflict(x.First, x.Second) && IRandom.Instance.Next(1, 100) <= (Options.CustomAdtRoleSpawnRate.TryGetValue(x.First, out var sc) ? sc.GetFloat() : 0), x => Main.PlayerStates[x.Second.PlayerId].SetSubRole(x.First)));
.SelectMany(a => a.Select(x =>
{
var suitablePlayer = aapc
.OrderBy(p => addonNum[p])
.FirstOrDefault(p => CustomRolesHelper.CheckAddonConflict(x, p));
if (suitablePlayer != null) addonNum[suitablePlayer]++;
return (Role: x, SuitablePlayer: suitablePlayer);
}))
.DoIf(x => x.SuitablePlayer != null && IRandom.Instance.Next(1, 100) <= (Options.CustomAdtRoleSpawnRate.TryGetValue(x.Role, out var sc) ? sc.GetFloat() : 0), x => Main.PlayerStates[x.SuitablePlayer.PlayerId].SetSubRole(x.Role), fast: true);
foreach (var state in Main.PlayerStates.Values)
+38 -22
View File
@@ -302,7 +302,7 @@ class CheckMurderPatch
if (!AmongUsClient.Instance.AmHost) return false;
if (target == null) target = killer;
if (CustomTeamManager.AreInSameCustomTeam(killer.PlayerId, target.PlayerId) && !CustomTeamManager.IsSettingEnabledForPlayerTeam(killer.PlayerId, "KillEachOther")) return false;
if (CustomTeamManager.AreInSameCustomTeam(killer.PlayerId, target.PlayerId) && !CustomTeamManager.IsSettingEnabledForPlayerTeam(killer.PlayerId, CTAOption.KillEachOther)) return false;
if (killer.Is(CustomRoles.Jackal) && target.Is(CustomRoles.Sidekick) && !Options.JackalCanKillSidekick.GetBool()) return false;
if (killer.Is(CustomRoles.Sidekick) && target.Is(CustomRoles.Jackal) && !Options.SidekickCanKillJackal.GetBool()) return false;
@@ -328,7 +328,19 @@ class CheckMurderPatch
if (killer.Is(CustomRoles.Refugee) && target.Is(CustomRoleTypes.Impostor)) return false;
if (GhostRolesManager.AssignedGhostRoles.TryGetValue(target.PlayerId, out var ghostRole) && ghostRole.Instance is GA ga && ga.ProtectionList.Contains(target.PlayerId)) return false;
if (Echo.On)
{
foreach (Echo echo in Echo.Instances)
{
if (echo.EchoPC.shapeshiftTargetPlayerId == target.PlayerId)
{
echo.OnTargetCheckMurder(killer, target);
return false;
}
}
}
if (GhostRolesManager.AssignedGhostRoles.Values.Any(x => x.Instance is GA ga && ga.ProtectionList.Contains(target.PlayerId))) return false;
if (SoulHunter.IsSoulHunterTarget(killer.PlayerId) && target.Is(CustomRoles.SoulHunter))
{
@@ -1002,7 +1014,7 @@ class FixedUpdatePatch
if (id.IsPlayerRoleBlocked())
{
__instance.Notify(BlockedAction.Report.GetBlockNotify());
Logger.Info("Dead Body Report Blocked (player is hacked by Glitch)", "FixedUpdate.ReportDeadBody");
Logger.Info("Dead Body Report Blocked (player role blocked)", "FixedUpdate.ReportDeadBody");
ReportDeadBodyPatch.WaitReport[id].Clear();
}
else
@@ -1014,12 +1026,32 @@ class FixedUpdatePatch
}
}
if (AmongUsClient.Instance.AmHost)
{
if (GhostRolesManager.AssignedGhostRoles.TryGetValue(__instance.PlayerId, out var ghostRole))
{
switch (ghostRole.Instance)
{
case Haunter haunter:
haunter.Update(__instance);
break;
case Bloodmoon:
Bloodmoon.Update(__instance);
break;
}
}
else if (!Main.HasJustStarted && GameStates.IsInTask && GhostRolesManager.ShouldHaveGhostRole(__instance))
{
GhostRolesManager.AssignGhostRole(__instance);
}
}
if (Options.DontUpdateDeadPlayers.GetBool() && !__instance.IsAlive())
{
DeadBufferTime.TryAdd(id, IRandom.Instance.Next(50, 70));
DeadBufferTime.TryAdd(id, IRandom.Instance.Next(20, 40));
DeadBufferTime[id]--;
if (DeadBufferTime[id] > 0) return;
DeadBufferTime[id] = IRandom.Instance.Next(50, 70);
DeadBufferTime[id] = IRandom.Instance.Next(20, 40);
}
if (Options.LowLoadMode.GetBool())
@@ -1155,23 +1187,6 @@ class FixedUpdatePatch
}
}
if (GhostRolesManager.AssignedGhostRoles.TryGetValue(player.PlayerId, out var ghostRole))
{
switch (ghostRole.Instance)
{
case Haunter haunter:
haunter.Update(player);
break;
case Bloodmoon when !lowLoad:
Bloodmoon.Update(player);
break;
}
}
else if (!lowLoad && !Main.HasJustStarted && GameStates.IsInTask && GhostRolesManager.ShouldHaveGhostRole(player))
{
GhostRolesManager.AssignGhostRole(player);
}
long now = TimeStamp;
if (!lowLoad && Options.UsePets.GetBool() && GameStates.IsInTask && (!LastUpdate.TryGetValue(playerId, out var lastPetNotify) || lastPetNotify < now))
{
@@ -1486,6 +1501,7 @@ class FixedUpdatePatch
if (self)
{
Suffix.Append(Bloodmoon.GetSuffix(seer));
Suffix.Append(Haunter.GetSuffix(seer));
if (seer.Is(CustomRoles.Asthmatic)) Suffix.Append(Asthmatic.GetSuffixText(seer.PlayerId));
if (seer.Is(CustomRoles.Sonar)) Suffix.Append(Sonar.GetSuffix(seer, GameStates.IsMeeting));
}
+2 -1
View File
@@ -3100,7 +3100,7 @@
"LobbyCloseTimer": "Lobby Closing Timer: {0}",
"HorseMode": "Horse Mode",
"LongMode": "Long Mode",
"CustomTeamHelp": "You are in the {0}!{1}\\nWork with your team members to win together!",
"CustomTeamHelp": "You are in the {0}! ({1})\\nWork with your team members to win together!",
"NoPetActionMsg1": "You just ate a cookie",
"NoPetActionMsg2": "You look around",
"NoPetActionMsg3": "You start wondering whether you are sus or not",
@@ -3809,6 +3809,7 @@
"GA": "Guardian Angel",
"GAInfo": "Protect Crewmates",
"GAInfoLong": "(Crewmates):\\nAs the Guardian Angel, you can protect someone to save them from being killed. This is the vanilla Guardian Angel role, but as an add-on.",
"Prefix.GA": "Guardian Angel",
"Haunter": "Haunter",
"HaunterInfo": "You're the Impostors' Worst Nightmare",
"HaunterInfoLong": "(Neutrals):\\nAs the Haunter, when you complete all of your tasks, a random living impostor's name will show in red to everyone in meetings. When you have 1 task left, all impostors will get an arrow pointing towards you, and if any of them come close to you, you lose this role.",
+10 -1
View File
@@ -1,4 +1,6 @@
using static EHR.Options;
using System;
using System.Linq;
using static EHR.Options;
namespace EHR.Roles.AddOns.Common
{
@@ -32,6 +34,8 @@ namespace EHR.Roles.AddOns.Common
"LovingImpostor"
];
public static CustomRoles LovingImpostorRole;
public AddonTypes Type => AddonTypes.Mixed;
public void SetupCustomOption()
@@ -103,5 +107,10 @@ namespace EHR.Roles.AddOns.Common
CustomAdtRoleSpawnRate.Add(role, rateOption);
}
public static void Init()
{
LovingImpostorRole = Enum.GetValues<CustomRoles>().Where(x => x.IsEnable() && x.IsImpostor() && x != CustomRoles.LovingImpostor && !x.RoleExist(countDead: true) && !HnSManager.AllHnSRoles.Contains(x)).Shuffle()[0];
}
}
}
+1 -1
View File
@@ -2,7 +2,7 @@
namespace EHR.Roles.AddOns.GhostRoles
{
public class GA : IGhostRole, ISettingHolder
internal class GA : IGhostRole, ISettingHolder
{
private static OptionItem ProtectDuration;
private static OptionItem CD;
+14
View File
@@ -14,6 +14,7 @@ namespace EHR.Roles.AddOns.GhostRoles
private static OptionItem RevealNeutralKillers;
private static OptionItem RevealMadmates;
private static OptionItem NumberOfReveals;
private byte HaunterId;
private List<byte> WarnedImps = [];
@@ -27,6 +28,7 @@ namespace EHR.Roles.AddOns.GhostRoles
public void OnAssign(PlayerControl pc)
{
HaunterId = pc.PlayerId;
LateTask.New(() =>
{
var taskState = pc.GetTaskState();
@@ -123,5 +125,17 @@ namespace EHR.Roles.AddOns.GhostRoles
pc.Notify(Translator.GetString("HaunterStoppedSelf"), 7f);
}
}
public static string GetSuffix(PlayerControl seer)
{
foreach (var role in GhostRolesManager.AssignedGhostRoles.Values)
{
if (role.Instance is not Haunter haunter) continue;
if (!haunter.WarnedImps.Contains(seer.PlayerId)) continue;
return TargetArrow.GetArrows(seer, haunter.HaunterId);
}
return string.Empty;
}
}
}
+2 -2
View File
@@ -175,14 +175,14 @@ public class NiceSwapper : RoleBase
if (x.TargetPlayerId.IsHost()) MeetingHud.Instance.CmdCastVote(x.TargetPlayerId, SwapTargets.Item2);
else MeetingHud.Instance.CastVote(x.TargetPlayerId, SwapTargets.Item2);
x.VotedFor = SwapTargets.Item2;
});
}, fast: true);
playerStates.DoIf(votedFor2.Contains, x =>
{
x.UnsetVote();
if (x.TargetPlayerId.IsHost()) MeetingHud.Instance.CmdCastVote(x.TargetPlayerId, SwapTargets.Item1);
else MeetingHud.Instance.CastVote(x.TargetPlayerId, SwapTargets.Item1);
x.VotedFor = SwapTargets.Item1;
});
}, fast: true);
PlayerControl Target1 = Utils.GetPlayerById(SwapTargets.Item1);
PlayerControl Target2 = Utils.GetPlayerById(SwapTargets.Item2);
+2 -2
View File
@@ -141,11 +141,11 @@ namespace EHR.Crewmate
break;
case Poop.Red:
var defaultSpeed = Main.RealOptionsData.GetFloat(FloatOptionNames.PlayerSpeedMod);
((List<PlayerControl>)activePoop.Data).DoIf(x => x, x =>
((List<PlayerControl>)activePoop.Data).DoIf(x => x != null, x =>
{
Main.AllPlayerSpeed[x.PlayerId] = defaultSpeed;
x.MarkDirtySettings();
});
}, fast: true);
break;
}
}
+1 -1
View File
@@ -53,7 +53,7 @@ namespace EHR.Roles.Impostor
if (x.TargetPlayerId.IsHost()) MeetingHud.Instance.CmdCastVote(x.TargetPlayerId, bmVotedFor);
else MeetingHud.Instance.CastVote(x.TargetPlayerId, bmVotedFor);
x.VotedFor = bmVotedFor;
});
}, fast: true);
}
}
}
+44 -10
View File
@@ -1,11 +1,16 @@
namespace EHR.Roles.Impostor
using System.Collections.Generic;
namespace EHR.Roles.Impostor
{
public class Echo : RoleBase
{
public static bool On;
public static List<Echo> Instances = [];
private static OptionItem ShapeshiftCooldown;
private static OptionItem ShapeshiftDuration;
public PlayerControl EchoPC;
public override bool IsEnable => On;
public static void SetupCustomOption()
@@ -23,14 +28,17 @@
.SetValueFormat(OptionFormat.Seconds);
}
public override void Init()
{
Instances = [];
On = false;
}
public override void Add(byte playerId)
{
On = true;
}
public override void Init()
{
On = false;
EchoPC = Utils.GetPlayerById(playerId);
Instances.Add(this);
}
public override void SetButtonTexts(HudManager hud, byte id)
@@ -57,14 +65,40 @@
{
target = Utils.GetPlayerById(shapeshifter.shapeshiftTargetPlayerId);
if (target == null) return true;
target.RpcShapeshift(target, false);
var pos = shapeshifter.Pos();
shapeshifter.TP(target);
target.TP(pos);
RevertSwap(shapeshifter, target);
LateTask.New(() => target.Suicide(PlayerState.DeathReason.Kill, shapeshifter), 0.2f, "Echo Unshift Kill");
}
return true;
}
private static void RevertSwap(PlayerControl echo, PlayerControl target)
{
target.RpcShapeshift(target, false);
var pos = echo.Pos();
echo.TP(target);
target.TP(pos);
}
public override bool OnCheckMurderAsTarget(PlayerControl killer, PlayerControl target)
{
if (!target.IsShifted()) return true;
var ssTarget = Utils.GetPlayerById(target.shapeshiftTargetPlayerId);
if (ssTarget == null || !killer.RpcCheckAndMurder(ssTarget, check: true)) return true;
RevertSwap(target, ssTarget);
LateTask.New(() => killer.Kill(ssTarget), 0.2f, log: false);
return false;
}
public void OnTargetCheckMurder(PlayerControl killer, PlayerControl target)
{
RevertSwap(EchoPC, target);
LateTask.New(() =>
{
killer.RpcCheckAndMurder(EchoPC);
target.Suicide(PlayerState.DeathReason.Kill, EchoPC);
}, 0.2f, log: false);
}
}
}
+1 -1
View File
@@ -231,7 +231,7 @@ public class Witch : RoleBase
public override string GetSuffix(PlayerControl witch, PlayerControl target, bool hud = false, bool isMeeting = false)
{
if (witch == null || isMeeting || witch.PlayerId != target.PlayerId) return string.Empty;
if (witch == null || isMeeting || witch.PlayerId != target.PlayerId || !witch.Is(CustomRoles.Witch)) return string.Empty;
var str = new StringBuilder();
if (hud)
+2 -3
View File
@@ -18,11 +18,10 @@ public class Tremor : RoleBase
private static OptionItem TimerStart;
private static OptionItem TimerDecrease;
private static OptionItem DoomTime;
int Count;
int DoomTimer;
long LastUpdate = Utils.TimeStamp;
int Timer;
public override bool IsEnable => On;
@@ -71,7 +70,7 @@ public class Tremor : RoleBase
public override void OnFixedUpdate(PlayerControl pc)
{
if (!GameStates.IsInTask || !pc.IsAlive()) return;
if (!GameStates.IsInTask || ExileController.Instance || !pc.IsAlive()) return;
bool wasDoom = IsDoom;