Add Shifter, Fix bugs

This commit is contained in:
Gurge44 committed 2024-05-18 13:13:43 +02:00
1 parent f1b05d35b0
commit 20de8bd597
19 files changed
+212 -60

No files matched your search

+1
View File
@@ -280,6 +280,7 @@ public enum CustomRoles
Samurai,
SchrodingersCat,
NSerialKiller, // Serial Killer
Shifter,
Sidekick,
Simon,
SoulHunter,
+28 -11
View File
@@ -122,7 +122,7 @@ namespace EHR
};
memberNum[Team.Crewmate] = allPlayers.Count - memberNum.Values.Sum();
Logger.Warn($"Number of impostors: {memberNum[Team.Impostor]}", "debug");
Logger.Warn($"Number of impostors: {memberNum[Team.Impostor]}", "HnsRoleAssigner");
foreach (var item in Main.SetRoles)
{
@@ -136,7 +136,7 @@ namespace EHR
role.Value[item.Value]--;
memberNum[role.Key]--;
Logger.Warn($"Pre-Set Role Assigned: {pc.GetRealName()} => {item.Value}", "CustomRoleSelector");
Logger.Warn($"Pre-Set Role Assigned: {pc.GetRealName()} => {item.Value}", "HnsRoleAssigner");
}
var playerTeams = Enum.GetValues<Team>()[1..]
@@ -186,14 +186,14 @@ namespace EHR
foreach (PlayerControl pc in allPlayers.Except(result.Keys).ToArray())
{
Logger.Warn($"Unassigned, force Hider: {pc.GetRealName()} => {CustomRoles.Hider}", "debug");
Logger.Warn($"Unassigned, force Hider: {pc.GetRealName()} => {CustomRoles.Hider}", "HnsRoleAssigner");
result[pc] = CustomRoles.Hider;
memberNum[Team.Crewmate]--;
allPlayers.Remove(pc);
}
if (allPlayers.Count > 0) Logger.Error($"Some players were not assigned a role: {allPlayers.Join(x => x.GetRealName())}", "CustomRoleSelector");
Logger.Msg($"Roles: {result.Join(x => $"{x.Key.GetRealName()} => {x.Value}")}", "HideAndSeekRoleSelector");
if (allPlayers.Count > 0) Logger.Error($"Some players were not assigned a role: {allPlayers.Join(x => x.GetRealName())}", "HnsRoleAssigner");
Logger.Msg($"Roles: {result.Join(x => $"{x.Key.GetRealName()} => {x.Value}")}", "HnsRoleAssigner");
var roleInterfaces = Assembly.GetExecutingAssembly().GetTypes()
.Where(x => typeof(IHideAndSeekRole).IsAssignableFrom(x) && !x.IsInterface)
@@ -203,6 +203,14 @@ namespace EHR
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));
// ==================================================================================================================
if (result.ContainsValue(CustomRoles.Agent))
{
var agent = result.GetKeyByValue(CustomRoles.Agent).PlayerId;
PlayerRoles.DoIf(x => x.Value.Interface.Team == Team.Impostor, x => TargetArrow.Add(x.Key, agent));
}
}
public static void ApplyGameOptions(IGameOptions opt, PlayerControl pc)
@@ -248,6 +256,12 @@ namespace EHR
string dangerMeter = GetDangerMeter(seer);
if (PlayerRoles[seer.PlayerId].Interface.Team == Team.Impostor && PlayerRoles.Values.Any(x => x.Role == CustomRoles.Agent))
{
var agent = PlayerRoles.First(x => x.Value.Role == CustomRoles.Agent).Key;
dangerMeter += TargetArrow.GetArrows(seer, agent);
}
if (!isHUD && seer.IsModClient()) return string.Empty;
if (TimeLeft <= 60)
{
@@ -304,9 +318,7 @@ namespace EHR
// If there are no crew roles left, the game is over and only impostors win
if (alivePlayers.All(x => PlayerRoles[x.PlayerId].Interface.Team != Team.Crewmate))
{
CustomWinnerHolder.ResetAndSetWinner(CustomWinner.Seeker);
CustomWinnerHolder.WinnerIds.UnionWith(PlayerRoles.Where(x => x.Value.Interface.Team == Team.Impostor).Select(x => x.Key));
AddFoxesToWinners();
SetWinners(CustomWinner.Seeker, Team.Impostor);
return true;
}
@@ -314,13 +326,18 @@ namespace EHR
if (TimeLeft <= 0)
{
reason = GameOverReason.HumansByTask;
CustomWinnerHolder.ResetAndSetWinner(CustomWinner.Hider);
CustomWinnerHolder.WinnerIds.UnionWith(PlayerRoles.Where(x => x.Value.Interface.Team == Team.Crewmate).Select(x => x.Key));
AddFoxesToWinners();
SetWinners(CustomWinner.Hider, Team.Crewmate);
return true;
}
return false;
static void SetWinners(CustomWinner winner, Team team)
{
CustomWinnerHolder.ResetAndSetWinner(winner);
CustomWinnerHolder.WinnerIds.UnionWith(PlayerRoles.Where(x => x.Value.Interface.Team == team).Select(x => x.Key));
AddFoxesToWinners();
}
}
public static void AddFoxesToWinners()
+6 -2
View File
@@ -362,6 +362,7 @@ internal static class CustomRolesHelper
CustomRoles.PlagueDoctor => RoleTypes.Impostor,
CustomRoles.Postman => RoleTypes.Impostor,
CustomRoles.SchrodingersCat => RoleTypes.Impostor,
CustomRoles.Shifter => RoleTypes.Impostor,
CustomRoles.Impartial => RoleTypes.Impostor,
CustomRoles.Predator => RoleTypes.Impostor,
CustomRoles.Reckless => RoleTypes.Impostor,
@@ -400,6 +401,7 @@ internal static class CustomRolesHelper
public static bool IsNonNK(this CustomRoles role, bool check = false) => (!check && role == CustomRoles.Arsonist && CanCheck && Options.IsLoaded && Options.ArsonistCanIgniteAnytime != null && !Options.ArsonistCanIgniteAnytime.GetBool()) || role is
CustomRoles.Jester or
CustomRoles.Postman or
CustomRoles.Shifter or
CustomRoles.SchrodingersCat or
CustomRoles.Impartial or
CustomRoles.Predator or
@@ -515,6 +517,7 @@ internal static class CustomRolesHelper
public static bool IsNC(this CustomRoles role) => role is
CustomRoles.Mario or
CustomRoles.Shifter or
CustomRoles.Terrorist or
CustomRoles.Revolutionist or
CustomRoles.Impartial or
@@ -1021,9 +1024,10 @@ internal static class CustomRolesHelper
CustomRoles.Parasite => CountTypes.Impostor,
CustomRoles.Crewpostor => CountTypes.Impostor,
CustomRoles.Refugee => CountTypes.Impostor,
CustomRoles.DarkHide => DarkHide.SnatchesWin.GetBool() ? CountTypes.Crew : CountTypes.DarkHide,
CustomRoles.Arsonist => !Options.ArsonistKeepsGameGoing.GetBool() ? CountTypes.Crew : CountTypes.Arsonist,
CustomRoles.DarkHide when DarkHide.SnatchesWin.GetBool() => CountTypes.Crew,
CustomRoles.Arsonist when !Options.ArsonistKeepsGameGoing.GetBool() => CountTypes.Crew,
CustomRoles.SchrodingersCat => SchrodingersCat.WinsWithCrewIfNotAttacked.GetBool() ? CountTypes.Crew : CountTypes.OutOfGame,
CustomRoles.Shifter => CountTypes.OutOfGame,
_ => Enum.TryParse(role.ToString(), true, out CountTypes type)
? type
+5 -5
View File
@@ -76,7 +76,7 @@ namespace EHR.Modules
foreach ((CustomTeam team, HashSet<byte> players) in CustomTeamPlayerIds)
{
if (!GetSettingForTeam(team, "Arrows")) continue;
if (!IsSettingEnabledForTeam(team, "Arrows")) continue;
foreach (byte player in players)
{
@@ -91,7 +91,7 @@ namespace EHR.Modules
public static string GetSuffix(PlayerControl seer)
{
if (seer == null || EnabledCustomTeams.Count == 0 || !GetSettingForPlayerTeam(seer.PlayerId, "Arrows")) return string.Empty;
if (seer == null || EnabledCustomTeams.Count == 0 || !IsSettingEnabledForPlayerTeam(seer.PlayerId, "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)));
}
@@ -143,13 +143,13 @@ namespace EHR.Modules
return team1 != null && team2 != null && team1.Equals(team2);
}
public static bool GetSettingForPlayerTeam(byte id, string settingName)
public static bool IsSettingEnabledForPlayerTeam(byte id, string settingName)
{
var team = GetCustomTeam(id);
return team != null && GetSettingForTeam(team, settingName);
return team != null && IsSettingEnabledForTeam(team, settingName);
}
public static bool GetSettingForTeam(CustomTeam team, string settingName)
public static bool IsSettingEnabledForTeam(CustomTeam team, string settingName)
{
var optionsGroup = CustomTeamOptions.First(x => x.Team.Equals(team));
var setting = optionsGroup.GetType().GetFields().FirstOrDefault(x => x.Name.Contains(settingName));
+5 -2
View File
@@ -24,7 +24,7 @@ static class ExtendedPlayerControl
{
public const MurderResultFlags ResultFlags = MurderResultFlags.Succeeded;
public static void RpcSetCustomRole(this PlayerControl player, CustomRoles role, bool isRoleForced = false)
public static void RpcSetCustomRole(this PlayerControl player, CustomRoles role, bool isRoleForced = false, bool replaceAllAddons = false)
{
if (role < CustomRoles.NotAssigned || isRoleForced)
{
@@ -33,7 +33,7 @@ static class ExtendedPlayerControl
else
{
if (!Cleanser.CleansedCanGetAddon.GetBool() && player.Is(CustomRoles.Cleansed)) return;
Main.PlayerStates[player.PlayerId].SetSubRole(role);
Main.PlayerStates[player.PlayerId].SetSubRole(role, replaceAllAddons);
}
if (AmongUsClient.Instance.AmHost)
@@ -41,6 +41,7 @@ static class ExtendedPlayerControl
MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SetCustomRole, SendOption.Reliable);
writer.Write(player.PlayerId);
writer.WritePacked((int)role);
writer.Write(replaceAllAddons);
AmongUsClient.Instance.FinishRpcImmediately(writer);
}
}
@@ -869,6 +870,8 @@ static class ExtendedPlayerControl
if (Options.CurrentGameMode == CustomGameMode.SoloKombat) return;
if (target == null) target = killer;
CheckAndSpawnAdditionalRefugee(target.Data);
if (target.GetTeam() is Team.Impostor or Team.Neutral) Stressed.OnNonCrewmateDead();
if (killer.Is(CustomRoles.Damocles)) Damocles.OnMurder(killer.PlayerId);
+6 -2
View File
@@ -132,7 +132,11 @@ public class PlayerState(byte playerId)
{
if (role == CustomRoles.Cleansed)
AllReplace = true;
if (AllReplace) SubRoles.Clear();
if (AllReplace)
{
SubRoles.Clear();
Utils.SendRPC(CustomRPC.RemoveSubRole, PlayerId, 2);
}
if (!SubRoles.Contains(role))
SubRoles.Add(role);
@@ -229,7 +233,7 @@ public class PlayerState(byte playerId)
if (SubRoles.Contains(role))
SubRoles.Remove(role);
Utils.SendRPC(CustomRPC.RemoveSubRole, PlayerId, (int)role);
Utils.SendRPC(CustomRPC.RemoveSubRole, PlayerId, 1, (int)role);
}
public void SetDead()
+6 -9
View File
@@ -35,6 +35,8 @@ namespace EHR.Modules
IGhostRole instance = CreateGhostRoleInstance(suitableRole);
instance.OnAssign(pc);
AssignedGhostRoles[pc.PlayerId] = (suitableRole, instance);
if (suitableRole == CustomRoles.Haunter) GhostRoles.Remove(suitableRole);
}
public static void SpecificAssignGhostRole(byte id, CustomRoles role, bool set)
@@ -57,16 +59,11 @@ namespace EHR.Modules
if (pc.IsAlive() || pc.GetCountTypes() is CountTypes.None or CountTypes.OutOfGame || pc.Is(CustomRoles.EvilSpirit)) return false;
var suitableRole = GetSuitableGhostRole(pc);
switch (suitableRole)
return suitableRole switch
{
case CustomRoles.Specter when IsPartnerPickedRole():
return false;
case CustomRoles.Haunter:
GhostRoles.Remove(CustomRoles.Haunter);
break;
}
return suitableRole.IsGhostRole() && !AssignedGhostRoles.Any(x => x.Key == pc.PlayerId || x.Value.Role == suitableRole);
CustomRoles.Specter when IsPartnerPickedRole() => false,
_ => suitableRole.IsGhostRole() && !AssignedGhostRoles.Any(x => x.Key == pc.PlayerId || x.Value.Role == suitableRole)
};
bool IsPartnerPickedRole() => Main.PlayerStates[pc.PlayerId].Role switch
{
+1 -1
View File
@@ -182,7 +182,7 @@ public static class GuessManager
return true;
}
if (CustomTeamManager.AreInSameCustomTeam(pc.PlayerId, targetId) && !CustomTeamManager.GetSettingForPlayerTeam(targetId, "GuessEachOther"))
if (CustomTeamManager.AreInSameCustomTeam(pc.PlayerId, targetId) && !CustomTeamManager.IsSettingEnabledForPlayerTeam(targetId, "GuessEachOther"))
{
if (!isUI) Utils.SendMessage(GetString("GuessSameCTAPlayer"), pc.PlayerId);
else pc.ShowPopUp(GetString("GuessSameCTAPlayer"));
+1 -1
View File
@@ -71,7 +71,7 @@ public static class NameColorManager
}
// Custom Teams
if (CustomTeamManager.AreInSameCustomTeam(seer.PlayerId, target.PlayerId) && CustomTeamManager.GetSettingForPlayerTeam(seer.PlayerId, "KnowRoles")) color = Main.RoleColors[target.GetCustomRole()];
if (CustomTeamManager.AreInSameCustomTeam(seer.PlayerId, target.PlayerId) && CustomTeamManager.IsSettingEnabledForPlayerTeam(seer.PlayerId, "KnowRoles")) color = Main.RoleColors[target.GetCustomRole()];
// Add-ons
if (target.Is(CustomRoles.Glow) && Utils.IsActive(SystemTypes.Electrical)) color = Main.RoleColors[CustomRoles.Glow];
+14 -5
View File
@@ -51,6 +51,7 @@ public enum CustomRPC
ShowPopUp,
KillFlash,
SyncAbilityUseLimit,
RemoveAbilityUseLimit,
RemoveSubRole,
Arrow,
@@ -338,15 +339,23 @@ internal class RPCHandlerPatch
case CustomRPC.SetCustomRole:
byte CustomRoleTargetId = reader.ReadByte();
CustomRoles role = (CustomRoles)reader.ReadPackedInt32();
RPC.SetCustomRole(CustomRoleTargetId, role);
bool replaceAllAddons = reader.ReadBoolean();
RPC.SetCustomRole(CustomRoleTargetId, role, replaceAllAddons);
break;
case CustomRPC.SyncAbilityUseLimit:
var pc = Utils.GetPlayerById(reader.ReadByte());
pc.SetAbilityUseLimit(reader.ReadSingle(), rpc: false);
break;
case CustomRPC.RemoveSubRole:
Main.PlayerStates[reader.ReadByte()].RemoveSubRole((CustomRoles)reader.ReadPackedInt32());
case CustomRPC.RemoveAbilityUseLimit:
Main.AbilityUseLimit.Remove(reader.ReadByte());
break;
case CustomRPC.RemoveSubRole:
{
byte id = reader.ReadByte();
if (reader.ReadPackedInt32() == 2) Main.PlayerStates[id].SubRoles.Clear();
else Main.PlayerStates[id].RemoveSubRole((CustomRoles)reader.ReadPackedInt32());
break;
}
case CustomRPC.Arrow:
if (reader.ReadBoolean()) TargetArrow.ReceiveRPC(reader);
else LocateArrow.ReceiveRPC(reader);
@@ -989,7 +998,7 @@ internal static class RPC
}
}
public static void SetCustomRole(byte targetId, CustomRoles role)
public static void SetCustomRole(byte targetId, CustomRoles role, bool replaceAllAddons = false)
{
if (role < CustomRoles.NotAssigned)
{
@@ -997,7 +1006,7 @@ internal static class RPC
}
else
{
Main.PlayerStates[targetId].SetSubRole(role);
Main.PlayerStates[targetId].SetSubRole(role, replaceAllAddons);
}
HudManager.Instance.SetHudActive(true);
+23 -4
View File
@@ -600,6 +600,7 @@ public static class Utils
case CustomRoles.PlagueDoctor:
case CustomRoles.Postman:
case CustomRoles.SchrodingersCat:
case CustomRoles.Shifter:
case CustomRoles.Impartial:
case CustomRoles.Predator:
case CustomRoles.Reckless:
@@ -773,7 +774,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.GetSettingForPlayerTeam(__instance.PlayerId, "KnowRoles") ||
CustomTeamManager.AreInSameCustomTeam(__instance.PlayerId, PlayerControl.LocalPlayer.PlayerId) && CustomTeamManager.IsSettingEnabledForPlayerTeam(__instance.PlayerId, "KnowRoles") ||
Main.PlayerStates.Values.Any(x => x.Role.KnowRole(PlayerControl.LocalPlayer, __instance)) ||
PlayerControl.LocalPlayer.IsRevealedPlayer(__instance) ||
PlayerControl.LocalPlayer.Is(CustomRoles.God) ||
@@ -1635,6 +1636,23 @@ public static class Utils
}
}
public static void CheckAndSpawnAdditionalRefugee(GameData.PlayerInfo deadPlayer)
{
if (deadPlayer != null && Options.SpawnAdditionalRefugeeOnImpsDead.GetBool() && Main.AllAlivePlayerControls.Length >= Options.SpawnAdditionalRefugeeMinAlivePlayers.GetInt() && !CustomRoles.Refugee.RoleExist(countDead: true) && !Main.AllAlivePlayerControls.Any(x => x.PlayerId != deadPlayer.PlayerId && (x.Is(CustomRoleTypes.Impostor) || (x.IsNeutralKiller() && Options.SpawnAdditionalRefugeeWhenNKAlive.GetBool()))))
{
PlayerControl[] ListToChooseFrom = Options.UsePets.GetBool() ? Main.AllAlivePlayerControls.Where(x => x.PlayerId != deadPlayer.PlayerId && x.Is(CustomRoleTypes.Crewmate)).ToArray() : Main.AllAlivePlayerControls.Where(x => x.PlayerId != deadPlayer.PlayerId && x.Is(CustomRoleTypes.Crewmate) && x.GetCustomRole().GetRoleTypes() == RoleTypes.Impostor).ToArray();
if (ListToChooseFrom.Length > 0)
{
var pc = ListToChooseFrom.RandomElement();
pc.RpcSetCustomRole(CustomRoles.Refugee);
pc.SetKillCooldown();
Logger.Warn($"{pc.GetRealName()} is now a Refugee since all Impostors are dead", "Add Refugee");
}
else Logger.Msg("No Player to change to Refugee.", "Add Refugee");
}
}
public static void SendMessage(string text, byte sendTo = byte.MaxValue, string title = "")
{
if (!AmongUsClient.Instance.AmHost) return;
@@ -1982,7 +2000,6 @@ public static class Utils
if (Pelican.IsEaten(seer.PlayerId)) SelfName = $"{ColorString(GetRoleColor(CustomRoles.Pelican), GetString("EatenByPelican"))}";
if (Deathpact.IsInActiveDeathpact(seer)) SelfName = Deathpact.GetDeathpactString(seer);
if (NameNotifyManager.GetNameNotify(seer, out var name)) SelfName = name;
// Devourer
if (Devourer.HideNameOfConsumedPlayer.GetBool() && Devourer.playerIdList.Any(x => Main.PlayerStates[x].Role is Devourer { IsEnable: true } dv && dv.PlayerSkinsCosumed.Contains(seer.PlayerId)) && !CamouflageIsForMeeting)
@@ -1993,6 +2010,8 @@ public static class Utils
GameMode2:
if (NameNotifyManager.GetNameNotify(seer, out var name)) SelfName = name;
switch (Options.CurrentGameMode)
{
case CustomGameMode.SoloKombat:
@@ -2008,7 +2027,7 @@ public static class Utils
break;
}
SelfName += SelfSuffix.ToString() == string.Empty ? string.Empty : $"\r\n {SelfSuffix}";
SelfName += SelfSuffix.ToString() == string.Empty ? string.Empty : $"\r\n{SelfSuffix}";
if (!isForMeeting) SelfName += "\r\n";
seer.RpcSetNamePrivate(SelfName, true, force: NoCache);
@@ -2128,7 +2147,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.GetSettingForPlayerTeam(seer.PlayerId, "KnowRoles") ||
CustomTeamManager.AreInSameCustomTeam(seer.PlayerId, target.PlayerId) && CustomTeamManager.IsSettingEnabledForPlayerTeam(seer.PlayerId, "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 ||
+3 -1
View File
@@ -235,7 +235,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.GetSettingForTeam(x.Key, "WinWithOriginalTeam"), x => WinnerIds.ExceptWith(x.Value));
.DoIf(x => !CustomTeamManager.IsSettingEnabledForTeam(x.Key, "WinWithOriginalTeam"), x => WinnerIds.ExceptWith(x.Value));
}
if ((WinnerTeam == CustomWinner.Lovers || WinnerIds.Any(x => Main.PlayerStates[x].SubRoles.Contains(CustomRoles.Lovers))) && Main.LoversPlayers.All(x => x.IsAlive()))
@@ -267,6 +267,8 @@ class GameEndChecker
}
}
}
WinnerIds.RemoveWhere(x => Main.PlayerStates[x].MainRole == CustomRoles.Shifter);
}
Camouflage.BlockCamouflage = true;
+1 -15
View File
@@ -1,6 +1,5 @@
using System.Linq;
using AmongUs.Data;
using AmongUs.GameOptions;
using EHR.Roles.AddOns.Crewmate;
using EHR.Roles.AddOns.Impostor;
using EHR.Roles.Crewmate;
@@ -134,20 +133,7 @@ class ExileControllerWrapUpPatch
if (map != null) Main.AllAlivePlayerControls.Do(map.RandomTeleport);
}
if (exiled != null && Options.SpawnAdditionalRefugeeOnImpsDead.GetBool() && Main.AllAlivePlayerControls.Length >= Options.SpawnAdditionalRefugeeMinAlivePlayers.GetInt() && !CustomRoles.Refugee.RoleExist(countDead: true) && !Main.AllAlivePlayerControls.Any(x => x.PlayerId != exiled.PlayerId && (x.Is(CustomRoleTypes.Impostor) || (x.IsNeutralKiller() && Options.SpawnAdditionalRefugeeWhenNKAlive.GetBool()))))
{
PlayerControl[] ListToChooseFrom = Options.UsePets.GetBool() ? Main.AllAlivePlayerControls.Where(x => x.PlayerId != exiled.PlayerId && x.Is(CustomRoleTypes.Crewmate)).ToArray() : Main.AllAlivePlayerControls.Where(x => x.PlayerId != exiled.PlayerId && x.Is(CustomRoleTypes.Crewmate) && x.GetCustomRole().GetRoleTypes() == RoleTypes.Impostor).ToArray();
if (ListToChooseFrom.Length > 0)
{
var index = IRandom.Instance.Next(0, ListToChooseFrom.Length);
var pc = ListToChooseFrom[index];
pc.RpcSetCustomRole(CustomRoles.Refugee);
pc.SetKillCooldown();
Logger.Warn($"{pc.GetRealName()} is now a Refugee since all Impostors are dead", "Add Refugee");
}
else Logger.Msg("No Player to change to Refugee.", "Add Refugee");
}
Utils.CheckAndSpawnAdditionalRefugee(exiled);
FallFromLadder.Reset();
Utils.CountAlivePlayers(true);
+3
View File
@@ -58,6 +58,9 @@ public static class HudSpritePatch
switch (player.GetCustomRole())
{
case CustomRoles.Shifter:
newKillButton = CustomButton.Get("Swap");
break;
case CustomRoles.Changeling:
newAbilityButton = CustomButton.Get("GlitchMimic");
break;
+1 -1
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.GetSettingForPlayerTeam(pc.PlayerId, "KnowRoles") ||
CustomTeamManager.AreInSameCustomTeam(pc.PlayerId, PlayerControl.LocalPlayer.PlayerId) && CustomTeamManager.IsSettingEnabledForPlayerTeam(pc.PlayerId, "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) ||
+1 -1
View File
@@ -299,7 +299,7 @@ class CheckMurderPatch
if (!AmongUsClient.Instance.AmHost) return false;
if (target == null) target = killer;
if (CustomTeamManager.AreInSameCustomTeam(killer.PlayerId, target.PlayerId) && !CustomTeamManager.GetSettingForPlayerTeam(killer.PlayerId, "KillEachOther")) return false;
if (CustomTeamManager.AreInSameCustomTeam(killer.PlayerId, target.PlayerId) && !CustomTeamManager.IsSettingEnabledForPlayerTeam(killer.PlayerId, "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;
+5
View File
@@ -3410,6 +3410,11 @@
"BenefactorTargetGotShieldNotify": "You got a temporary shield as the task\\nyou completed was marked by the Benefactor!",
"BenefactorTaskMarked": "Task marked",
"TaskMarkPerRound": "Maximum Number of Tasks Marked Each Round",
"Shifter": "Shifter",
"ShifterInfo": "Steal Someone's Role",
"ShifterInfoLong": "(Neutrals):\\nAs the Shifter, you must steal someone's role by using your kill button on them. Depending on the settings, you may also steal their progress in their role and ability uses, and their add-ons.\\nIf you have this role when the game ends, you lose!",
"Shifter.StealAddons": "Steal Add-ons",
"Shifter.StealProgress": "Steal Progress",
"Rogue": "Rogue",
"RogueInfo": "Complete Objectives, Get Rewards",
"RogueInfoLong": "(Neutral):\\nAs the Rogue, you get an objective with a reward each round. You can optionally complete the objective to get the reward.",
+101
View File
@@ -0,0 +1,101 @@
using System.Linq;
using AmongUs.GameOptions;
using EHR.Modules;
using HarmonyLib;
namespace EHR.Neutral
{
public class Shifter : RoleBase
{
private const int Id = 644400;
public static bool On;
private static OptionItem KillCooldown;
private static OptionItem CanVent;
private static OptionItem HasImpostorVision;
private static OptionItem StealAddons;
private static OptionItem StealProgress;
public override bool IsEnable => On;
public static void SetupCustomOption()
{
Options.SetupRoleOptions(Id, TabGroup.NeutralRoles, CustomRoles.Shifter);
KillCooldown = FloatOptionItem.Create(Id + 2, "AbilityCooldown", new(0f, 180f, 0.5f), 15f, TabGroup.NeutralRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Shifter])
.SetValueFormat(OptionFormat.Seconds);
CanVent = BooleanOptionItem.Create(Id + 3, "CanVent", true, TabGroup.NeutralRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Shifter]);
HasImpostorVision = BooleanOptionItem.Create(Id + 4, "ImpostorVision", true, TabGroup.NeutralRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Shifter]);
StealAddons = BooleanOptionItem.Create(Id + 5, "Shifter.StealAddons", true, TabGroup.NeutralRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Shifter]);
StealProgress = BooleanOptionItem.Create(Id + 6, "Shifter.StealProgress", true, TabGroup.NeutralRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Shifter]);
}
public override void Init()
{
On = false;
}
public override void Add(byte playerId)
{
On = true;
if (!AmongUsClient.Instance.AmHost) return;
if (!Main.ResetCamPlayerList.Contains(playerId))
Main.ResetCamPlayerList.Add(playerId);
}
public override void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat();
public override void ApplyGameOptions(IGameOptions opt, byte id) => opt.SetVision(HasImpostorVision.GetBool());
public override bool CanUseImpostorVentButton(PlayerControl pc) => CanVent.GetBool();
public override bool CanUseKillButton(PlayerControl pc) => true;
public override bool OnCheckMurder(PlayerControl killer, PlayerControl target)
{
if (!base.OnCheckMurder(killer, target)) return false;
killer.RpcSetCustomRole(target.GetCustomRole());
if (StealProgress.GetBool())
{
Main.PlayerStates[killer.PlayerId].Role = Main.PlayerStates[target.PlayerId].Role;
killer.SetAbilityUseLimit(target.GetAbilityUseLimit());
}
if (StealAddons.GetBool())
{
var killerSubRoles = killer.GetCustomSubRoles();
var targetSubRoles = target.GetCustomSubRoles();
if (targetSubRoles.Count > 0)
{
killer.RpcSetCustomRole(targetSubRoles[0], replaceAllAddons: true);
targetSubRoles.Skip(1).Do(x => killer.RpcSetCustomRole(x));
}
if (killerSubRoles.Count > 0)
{
target.RpcSetCustomRole(killerSubRoles[0], replaceAllAddons: true);
killerSubRoles.Skip(1).Do(x => target.RpcSetCustomRole(x));
}
}
// ------------------------------------------------------------------------------------------
target.RpcSetCustomRole(CustomRoles.Shifter);
Main.AbilityUseLimit.Remove(target.PlayerId);
Utils.SendRPC(CustomRPC.RemoveAbilityUseLimit, target.PlayerId);
target.SyncSettings();
target.SetKillCooldown();
// ------------------------------------------------------------------------------------------
Utils.NotifyRoles(SpecifyTarget: killer);
Utils.NotifyRoles(SpecifyTarget: target);
return false;
}
}
}
+1
View File
@@ -445,6 +445,7 @@ public class Main : BasePlugin
{ CustomRoles.PlagueDoctor, "#ff6633" },
{ CustomRoles.Postman, "#00b893" },
{ CustomRoles.SchrodingersCat, "#616161" },
{ CustomRoles.Shifter, "#777777" },
{ CustomRoles.Impartial, "#4287f5" },
{ CustomRoles.Predator, "#c73906" },
{ CustomRoles.Reckless, "#6e000d" },