mirror of
https://github.com/Gurge44/EndlessHostRoles.git
synced 2026-10-20 01:46:25 +00:00
Save & Load Combo Data + Fix Bugs
This commit is contained in:
1 parent
6908056940
commit
405c0e9c93
29 files changed
+262
-122
No files matched your search
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -55,9 +55,8 @@ public static class Zoom
|
||||
Flag.Run(() => { SetZoomSize(reset: true); }, "Zoom");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
catch
|
||||
{
|
||||
Utils.ThrowException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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()))
|
||||
|
||||
@@ -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))]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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.",
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in new issue
Block a user