Merge remote-tracking branch 'origin/main'

This commit is contained in:
Gurge44 committed 2025-09-26 14:01:24 +02:00
commit 186f77f8b8
17 files changed
+85 -55

No files matched your search

+2 -2
View File
@@ -218,7 +218,7 @@ public enum CustomRoles
Marshall,
Mathematician,
Mayor,
SabotageMaster, // Mechanic
Mechanic,
Medic,
Mediumshiper,
Merchant,
@@ -372,7 +372,7 @@ public enum CustomRoles
Spirit,
Spiritcaller,
Sprayer,
DarkHide, // Stalker
Stalker, // Stalker
Starspawn,
Cultist,
Sunnyboy,
+1 -1
View File
@@ -8,7 +8,7 @@
<Description>EHR</Description>
<Authors>Gurge44</Authors>
<langVersion>preview</langVersion>
<AmongUs>C:\Program Files\Epic Games\AmongUs</AmongUs>
<AmongUs>D:\SteamLibrary\steamapps\common\Among Us</AmongUs>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>True</Optimize>
<AssemblyName>$(MSBuildProjectName)</AssemblyName>
+1
View File
@@ -81,6 +81,7 @@ public static class AFKDetector
{
Logger.SendInGame(Translator.GetString("AFKTooMany"));
PlayerData.Clear();
Utils.NotifyRoles(ForceLoop: true);
}
}
+37 -30
View File
@@ -2730,13 +2730,13 @@ public static class Utils
if (target.Is(CustomRoles.Car) && !forMeeting && !GameStates.IsEnded)
{
sender.RpcSetName(target, Car.Name, seer);
return true;
continue;
}
if (Main.PlayerStates.TryGetValue(target.PlayerId, out var targetState) && targetState.Role is Tree { TreeSpriteActive: true } && !forMeeting && !GameStates.IsEnded)
{
sender.RpcSetName(target, Tree.Sprite, seer);
return true;
continue;
}
TargetMark.Clear();
@@ -2797,33 +2797,7 @@ public static class Utils
bool shouldSeeTargetAddons = seer.PlayerId == target.PlayerId || new[] { seer, target }.All(x => x.Is(Team.Impostor));
string targetRoleText =
(!seer.IsAlive() && Options.GhostCanSeeOtherRoles.GetBool()) ||
(seer.Is(CustomRoles.Mimic) && !target.IsAlive() && Options.MimicCanSeeDeadRoles.GetBool()) ||
(target.Is(CustomRoles.Gravestone) && !target.IsAlive()) ||
(Main.LoversPlayers.TrueForAll(x => x.PlayerId == seer.PlayerId || x.PlayerId == target.PlayerId) && Main.LoversPlayers.Count == 2 && Lovers.LoverKnowRoles.GetBool()) ||
(seer.Is(CustomRoleTypes.Coven) && target.Is(CustomRoleTypes.Coven)) ||
(seer.Is(CustomRoleTypes.Impostor) && target.Is(CustomRoleTypes.Impostor) && Options.ImpKnowAlliesRole.GetBool() && CustomTeamManager.ArentInCustomTeam(seer.PlayerId, target.PlayerId)) ||
(seer.IsMadmate() && target.Is(CustomRoleTypes.Impostor) && Options.MadmateKnowWhosImp.GetBool()) ||
(seer.Is(CustomRoleTypes.Impostor) && target.IsMadmate() && Options.ImpKnowWhosMadmate.GetBool()) ||
(seer.Is(CustomRoles.Crewpostor) && target.Is(CustomRoleTypes.Impostor) && Options.CrewpostorKnowsAllies.GetBool()) ||
(seer.Is(CustomRoles.Hypocrite) && target.Is(CustomRoleTypes.Impostor) && Hypocrite.KnowsAllies.GetBool()) ||
(seer.Is(CustomRoleTypes.Impostor) && target.Is(CustomRoles.Hypocrite) && Hypocrite.AlliesKnowHypocrite.GetBool()) ||
(seer.Is(CustomRoleTypes.Impostor) && target.Is(CustomRoles.Crewpostor) && Options.AlliesKnowCrewpostor.GetBool()) ||
(seer.IsMadmate() && target.IsMadmate() && Options.MadmateKnowWhosMadmate.GetBool()) ||
((seer.Is(CustomRoles.Sidekick) || seer.Is(CustomRoles.Recruit) || seer.Is(CustomRoles.Jackal)) && (target.Is(CustomRoles.Sidekick) || target.Is(CustomRoles.Recruit) || target.Is(CustomRoles.Jackal))) ||
(target.Is(CustomRoles.Workaholic) && Workaholic.WorkaholicVisibleToEveryone.GetBool()) ||
(target.Is(CustomRoles.Doctor) && !target.HasEvilAddon() && Options.DoctorVisibleToEveryone.GetBool()) ||
(target.Is(CustomRoles.Mayor) && Mayor.MayorRevealWhenDoneTasks.GetBool() && target.GetTaskState().IsTaskFinished) ||
(Marshall.CanSeeMarshall(seer) && 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, 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 or CustomGameMode.Speedrun ||
(Options.CurrentGameMode == CustomGameMode.HideAndSeek && CustomHnS.IsRoleTextEnabled(seer, target)) ||
(seer.IsRevealedPlayer(target) && !target.Is(CustomRoles.Trickster)) ||
(seer.Is(CustomRoles.God) && God.KnowInfo.GetValue() == 2) ||
target.Is(CustomRoles.GM)
KnowsTargetRole(seer, target)
? $"<size={fontSize}>{target.GetDisplayRoleName(seeTargetBetrayalAddons: shouldSeeTargetAddons)}{GetProgressText(target)}</size>\r\n"
: string.Empty;
@@ -2942,7 +2916,7 @@ public static class Utils
additionalSuffixes.Add(AFKDetector.GetSuffix(seer, target));
if (!forMeeting && Options.CurrentGameMode == CustomGameMode.Standard && Main.Invisible.Contains(target.PlayerId))
additionalSuffixes.Add(ColorString(Palette.White_75Alpha, GetString("Invisible")));
additionalSuffixes.Add(ColorString(Palette.White_75Alpha, "\n" + GetString("Invisible")));
TargetSuffix.Append(BuildSuffix(seer, target, meeting: forMeeting));
@@ -3012,6 +2986,37 @@ public static class Utils
return hasValue;
}
public static bool KnowsTargetRole(PlayerControl seer, PlayerControl target)
{
return (!seer.IsAlive() && Options.GhostCanSeeOtherRoles.GetBool()) ||
(seer.Is(CustomRoles.Mimic) && !target.IsAlive() && Options.MimicCanSeeDeadRoles.GetBool()) ||
(target.Is(CustomRoles.Gravestone) && !target.IsAlive()) ||
(Main.LoversPlayers.TrueForAll(x => x.PlayerId == seer.PlayerId || x.PlayerId == target.PlayerId) && Main.LoversPlayers.Count == 2 && Lovers.LoverKnowRoles.GetBool()) ||
(seer.Is(CustomRoleTypes.Coven) && target.Is(CustomRoleTypes.Coven)) ||
(seer.Is(CustomRoleTypes.Impostor) && target.Is(CustomRoleTypes.Impostor) && Options.ImpKnowAlliesRole.GetBool() && CustomTeamManager.ArentInCustomTeam(seer.PlayerId, target.PlayerId)) ||
(seer.IsMadmate() && target.Is(CustomRoleTypes.Impostor) && Options.MadmateKnowWhosImp.GetBool()) ||
(seer.Is(CustomRoleTypes.Impostor) && target.IsMadmate() && Options.ImpKnowWhosMadmate.GetBool()) ||
(seer.Is(CustomRoles.Crewpostor) && target.Is(CustomRoleTypes.Impostor) && Options.CrewpostorKnowsAllies.GetBool()) ||
(seer.Is(CustomRoles.Hypocrite) && target.Is(CustomRoleTypes.Impostor) && Hypocrite.KnowsAllies.GetBool()) ||
(seer.Is(CustomRoleTypes.Impostor) && target.Is(CustomRoles.Hypocrite) && Hypocrite.AlliesKnowHypocrite.GetBool()) ||
(seer.Is(CustomRoleTypes.Impostor) && target.Is(CustomRoles.Crewpostor) && Options.AlliesKnowCrewpostor.GetBool()) ||
(seer.IsMadmate() && target.IsMadmate() && Options.MadmateKnowWhosMadmate.GetBool()) ||
((seer.Is(CustomRoles.Sidekick) || seer.Is(CustomRoles.Recruit) || seer.Is(CustomRoles.Jackal)) && (target.Is(CustomRoles.Sidekick) || target.Is(CustomRoles.Recruit) || target.Is(CustomRoles.Jackal))) ||
(target.Is(CustomRoles.Workaholic) && Workaholic.WorkaholicVisibleToEveryone.GetBool()) ||
(target.Is(CustomRoles.Doctor) && !target.HasEvilAddon() && Options.DoctorVisibleToEveryone.GetBool()) ||
(target.Is(CustomRoles.Mayor) && Mayor.MayorRevealWhenDoneTasks.GetBool() && target.GetTaskState().IsTaskFinished) ||
(Marshall.CanSeeMarshall(seer) && 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, 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 or CustomGameMode.Speedrun ||
(Options.CurrentGameMode == CustomGameMode.HideAndSeek && CustomHnS.IsRoleTextEnabled(seer, target)) ||
(seer.IsRevealedPlayer(target) && !target.Is(CustomRoles.Trickster)) ||
(seer.Is(CustomRoles.God) && God.KnowInfo.GetValue() == 2) ||
target.Is(CustomRoles.GM);
}
public static void MarkEveryoneDirtySettings()
{
PlayerGameOptionsSender.SetDirtyToAll();
@@ -3238,6 +3243,8 @@ public static class Utils
public static void AddAbilityCD(CustomRoles role, byte playerId, bool includeDuration = true)
{
if (Options.UsePhantomBasis.GetBool() && (!role.IsNK() || Options.UsePhantomBasisForNKs.GetBool()) && role.SimpleAbilityTrigger()) return;
if (role.UsesPetInsteadOfKill())
{
var kcd = (int)Math.Round(Main.AllPlayerKillCooldown.TryGetValue(playerId, out float killCd) ? killCd : Options.AdjustedDefaultKillCooldown);
+1
View File
@@ -220,6 +220,7 @@ internal static class ChatCommands
new(["imitate", "имитировать", "模仿"], "{id}", GetString("CommandDescription.Imitate"), Command.UsageLevels.Everyone, Command.UsageTimes.InMeeting, ImitateCommand, true, true, [GetString("CommandArgs.Imitate.Id")]),
new(["retribute", "воздать", "报复"], "{id}", GetString("CommandDescription.Retribute"), Command.UsageLevels.Everyone, Command.UsageTimes.InMeeting, RetributeCommand, true, true, [GetString("CommandArgs.Retribute.Id")]),
new(["revive", "воскрешение", "воскрешать", "复活", "reviver"], "{id}", GetString("CommandDescription.Revive"), Command.UsageLevels.Host, Command.UsageTimes.InGame, ReviveCommand, true, false, [GetString("CommandArgs.Revive.Id")]),
new(["select", "выбратьигрока", "选择玩家", "selecionar"], "{id} {role}", GetString("CommandDescription.Select"), Command.UsageLevels.Everyone, Command.UsageTimes.InMeeting, SelectCommand, true, true, [GetString("CommandArgs.Select.Id"), GetString("CommandArgs.Select.Role")]),
new(["confirmauth"], "{uuid}", GetString("CommandDescription.ConfirmAuth"), Command.UsageLevels.Everyone, Command.UsageTimes.Always, ConfirmAuthCommand, true, false, [GetString("CommandArgs.ConfirmAuth.UUID")]),
+5 -4
View File
@@ -54,9 +54,6 @@ internal static class ControllerManagerUpdatePatch
}
else
InGameRoleInfoMenu.Hide();
if (KeysDown(KeyCode.Return, KeyCode.C, KeyCode.LeftShift))
HudManager.Instance.Chat.SetVisible(true);
if (KeysDown(KeyCode.F11, KeyCode.LeftAlt))
{
@@ -89,10 +86,14 @@ internal static class ControllerManagerUpdatePatch
if (KeysDown(KeyCode.LeftAlt, KeyCode.C) && !Input.GetKey(KeyCode.LeftShift) && !GameStates.IsNotJoined)
Utils.CopyCurrentSettings();
bool admin = ChatCommands.IsPlayerAdmin(PlayerControl.LocalPlayer.FriendCode);
if (!AmongUsClient.Instance.AmHost && !admin) return;
if (KeysDown(KeyCode.Return, KeyCode.C, KeyCode.LeftShift))
HudManager.Instance.Chat.SetVisible(true);
if (KeysDown(KeyCode.Return, KeyCode.L, KeyCode.LeftShift) && GameStates.IsInGame)
{
CustomWinnerHolder.ResetAndSetWinner(CustomWinner.Draw);
+1
View File
@@ -144,6 +144,7 @@ internal static class ExileControllerWrapUpPatch
{
string text = showRemainingKillers ? Utils.GetRemainingKillers(true) : string.Empty;
string finalText = ejectionNotify ? "<#ffffff>" + CheckForEndVotingPatch.EjectionText.Trim() : text;
if (Options.EnableGameTimeLimit.GetBool()) finalText += $"\n<#888888>{Options.GameTimeLimit.GetInt() - Main.GameTimer:N0}s {Translator.GetString("RemainingText.Suffix")}";
if (!string.IsNullOrEmpty(finalText))
Main.AllAlivePlayerControls.NotifyPlayers(finalText, 13f);
+1 -1
View File
@@ -661,7 +661,7 @@ internal static class MeetingHudStartPatch
{
private static void NotifyRoleSkillOnMeetingStart()
{
if (!AmongUsClient.Instance.AmHost) return;
if (!AmongUsClient.Instance.AmHost || GameStates.IsEnded) return;
List<Message> msgToSend = [];
+2 -2
View File
@@ -1848,7 +1848,7 @@ internal static class FixedUpdatePatch
additionalSuffixes.Add(AFKDetector.GetSuffix(seer, target));
if (!GameStates.IsMeeting && Options.CurrentGameMode == CustomGameMode.Standard && Main.Invisible.Contains(target.PlayerId) && (self || (seer.IsImpostor() && target.IsImpostor())))
additionalSuffixes.Add(ColorString(Palette.White_75Alpha, GetString("Invisible")));
additionalSuffixes.Add(ColorString(Palette.White_75Alpha, "\n" + GetString("Invisible")));
switch (target.GetCustomRole())
{
@@ -2044,7 +2044,7 @@ internal static class FixedUpdatePatch
if (Suffix.ToString() != string.Empty)
{
offset += moveandstop ? 0.15f : 0.1f;
offset += moveandstop ? 0.15f : 0.2f;
offset += moveandstop ? 0f : Suffix.ToString().Count(x => x == '\n') * 0.15f;
}
-1
View File
@@ -81,7 +81,6 @@ levelposse#7723,virajwins // Hacking while also streaming it
gummytub#2962,0f6992415
dollepic#0847,17be4645c // DESTRUCT10
donehoof#2148
huesassy#4051 // Harassment
daytiddly#8682,f5f420927,Wardpatchy // Nuking lobbies
coachcalm#9343,354aa4ac3,Twinfabled // Hacking the game
+5
View File
@@ -2490,6 +2490,7 @@
"CommandDescription.Retribute": "Guess who killed the player you camped as the Retributionist",
"CommandDescription.ConfirmAuth": "Command required to register a new EHR account",
"CommandDescription.Revive": "Revives a dead player. Requires special access or No Game End enabled.",
"CommandDescription.Select": "Select your impostor partner and their role.",
"CommandArgs.ChangeSetting.Name": "The setting's name to change (leave blank to view all settings)",
"CommandArgs.ChangeSetting.UnknownValue": "(leave blank to view what to put here)",
"CommandArgs.Rename.Name": "Your new name",
@@ -2583,6 +2584,8 @@
"CommandArgs.Retribute.Id": "The potential killer's ID to guess",
"CommandArgs.ConfirmAuth.UUID": "The unique token provided by the server",
"CommandArgs.Revive.Id": "The dead player's ID to revive",
"CommandArgs.Select.Id": "The player's ID to select as your impostor partner",
"CommandArgs.Select.Role": "The role to select for your impostor partner",
"Commands.ChangeSettingHelp": "<b><u>Arguments:</u></b><size=70%>\\n- map (theskeld/mirahq/polus/dlekseht/airship/thefungle/custom)\\n- impostors (number)\\n- players (number)\\n- recommended (on/off)\\n- confirmejects (on/off)\\n- emergencymeetings (number)\\n- anonymousvotes (on/off)\\n- emergencycooldown (number)\\n- discussiontime (number)\\n- votingtime (number)\\n- playerspeed (float)\\n- crewmatevision (float)\\n- impostorvision (float)\\n- killcooldown (float)\\n- killdistance (short/medium/long/custom)\\n- taskbarupdates (always/meetings/never)\\n- visualtasks (on/off)\\n- commontasks (number)\\n- longtasks (number)\\n- shorttasks (number)\\n- scientistcount (number)\\n- scientistchance (number)\\n- vitalsdisplaycooldown (float)\\n- batteryduration (float)\\n- engineercount (number)\\n- engineerchance (number)\\n- ventusecooldown (float)\\n- maxtimeinvents (float)\\n- guardianangelcount (number)\\n- guardianangelchance (number)\\n- protectcooldown (float)\\n- protectduration (float)\\n- protectvisibletoimpostors (on/off)\\n- shapeshiftercount (number)\\n- shapeshifterchance (number)\\n- shapeshiftduration (float)\\n- shapeshiftcooldown (float)\\n- leaveshapeshiftevidence (on/off)\\n- phantomcount (number)\\n- phantomchance (number)\\n- inviscooldown (float)\\n- invisduration (float)\\n- noisemakercount (number)\\n- noisemakerchance (number)\\n- noisemakerimpostoralert (on/off)\\n- noisemakeralertduration (number)\\n- trackercount (number)\\n- trackerchance (number)\\n- trackduration (float)\\n- trackcooldown (float)\\n- trackdelay (float)\\n- ghostdotasks (on/off)\\n\\n<u><b>Notes:</b></u>\\n1. Upper and lowercase matters\\n2. Where it says custom, you obviously put a number argument after it\\n3. A float is a single precision floating number, like 1.7\\n4. \"ghostdotasks\" causes issues if you set it\\n5. Example uses:\\n - \"/cs map polus\"\\n - \"/cs killdistance custom 4\"\\n - \"/cs trackdelay 1,7\"\\n - \"/cs confirmejects on\"",
"AddTagSuccess": "<#00ffa5>✓</color> Suceessfully created the tag {0} for {1}. If you want to change it, just use this command again and it will override the current tag. To delete it, simply type <#00a5ff>/deletetag {2}</color>!",
"DeleteTagSuccess": "<#00ffa5>✓</color> Successfully deleted {0}'s tag.",
@@ -9007,6 +9010,7 @@
"Postponer": "Postponer",
"PostponerInfo": "Postpone Dead Body Spawning",
"PostponerInfoLong": "(Impostors):\\nAs the Postponer, when you kill, no dead body spawns instantly. Instead, it will spawn after a delay (in the same place as the murder).",
"Postponer.BodyDelay": "Body Spawn Delay",
"Tree": "Tree",
"TreeInfo": "You are a Tree",
"TreeInfoLong": "(Crewmates):\\nAs a Tree, you can pet to act like one (become anonymous and invisible). After a few seconds, you will fall down, killing or stunning everyone nearby, and making you visible again.",
@@ -9284,6 +9288,7 @@
"Ambusher.FragileDuration": "Fragile Effect Duration",
"Ambusher.Success": "<#00ff00>Ambush successful</color>",
"Ambusher.InProgress": "Ambushing {0}.... {1}s left",
"Ambusher.InvisTimeLeft": "Invisibility expires in {0}s",
"Psychopath": "Psychopath",
"PsychopathInfo": "You're Forced to Kill Off Cooldown",
"PsychopathInfoLong": "(Impostors):\\nAs the Psychopath, as soon as your kill cooldown is up, you'll kill instantly if someone is inside your kill-range.",
+3 -3
View File
@@ -63,7 +63,7 @@ public class Captain : RoleBase
var room = pc.GetPlainShipRoom();
if (room != null && (TargetRooms.Count == 0 || TargetRooms[^1] != room.RoomId))
if (room != null && room.RoomId != SystemTypes.Hallway && (TargetRooms.Count == 0 || TargetRooms[^1] != room.RoomId))
TargetRooms.Add(room.RoomId);
}
@@ -73,7 +73,7 @@ public class Captain : RoleBase
LateTask.New(() =>
{
string msg = string.Format(Translator.GetString("Captain.TargetInfo"), TargetId.ColoredPlayerName(), string.Join(" ➔ ", TargetRooms.ConvertAll(x => Translator.GetString(x.ToString()))));
string msg = string.Format(Translator.GetString("Captain.TargetInfo"), TargetId.ColoredPlayerName(), string.Join(" ➡ ", TargetRooms.ConvertAll(x => Translator.GetString(x.ToString()))));
Utils.SendMessage(msg, CaptainId, CustomRoles.Captain.ToColoredString());
TargetRooms = [];
}, 10f, "Captain Message");
@@ -110,6 +110,6 @@ public class Captain : RoleBase
public override string GetSuffix(PlayerControl seer, PlayerControl target, bool hud = false, bool meeting = false)
{
if (seer.PlayerId != CaptainId || seer.PlayerId != target.PlayerId || (seer.IsModdedClient() && !hud) || meeting) return string.Empty;
return string.Format(Translator.GetString("Captain.Suffix"), LastNotify);
return string.Format(Translator.GetString("Captain.Suffix"), string.IsNullOrEmpty(LastNotify) ? Translator.GetString("None") : LastNotify);
}
}
+1 -1
View File
@@ -43,7 +43,7 @@ public class Inquisitor : RoleBase
if (voter == null || target == null || voter.PlayerId == target.PlayerId || Main.DontCancelVoteList.Contains(voter.PlayerId)) return false;
PlayerControl[] players = ExcludeDeadPlayers.GetBool() ? Main.AllAlivePlayerControls : Main.AllPlayerControls;
List<(byte Id, CustomRoles Role)> knownRoles = Main.PlayerStates.Values.SelectMany(s => from pc in players where s.Role.KnowRole(target, pc) select (pc.PlayerId, pc.GetCustomRole())).DistinctBy(x => x.PlayerId).ToList();
List<(byte Id, CustomRoles Role)> knownRoles = [.. from pc in players where Utils.KnowsTargetRole(target, pc) select (pc.PlayerId, pc.GetCustomRole())];
string result;
+14 -4
View File
@@ -25,7 +25,7 @@ public class Tree : RoleBase
public override void SetupCustomOption()
{
StartSetup(655100)
.AutoSetupOption(ref TreeSpriteVisible, true)
.AutoSetupOption(ref TreeSpriteVisible, false)
.AutoSetupOption(ref FallDelay, 5, new IntegerValueRule(1, 60, 1), OptionFormat.Seconds)
.AutoSetupOption(ref AbilityUseLimit, 1f, new FloatValueRule(0, 20, 0.05f), OptionFormat.Times)
.AutoSetupOption(ref AbilityUseGainWithEachTaskCompleted, 0.5f, new FloatValueRule(0f, 5f, 0.05f), OptionFormat.Times)
@@ -56,8 +56,14 @@ public class Tree : RoleBase
pc.MarkDirtySettings();
bool treeSpriteVisible = TreeSpriteVisible.GetBool();
if (treeSpriteVisible) TreeSpriteActive = true;
else pc.RpcMakeInvisible();
if (treeSpriteVisible)
{
TreeSpriteActive = true;
Utils.NotifyRoles(SpecifyTarget: pc);
}
else
pc.RpcMakeInvisible();
LateTask.New(() =>
{
@@ -66,7 +72,11 @@ public class Tree : RoleBase
Main.AllPlayerSpeed[pc.PlayerId] = Main.RealOptionsData.GetFloat(FloatOptionNames.PlayerSpeedMod);
pc.MarkDirtySettings();
if (treeSpriteVisible) TreeSpriteActive = false;
if (treeSpriteVisible)
{
TreeSpriteActive = false;
Utils.NotifyRoles(SpecifyTarget: pc);
}
else pc.RpcMakeVisible();
int chance = FallKillChance.GetInt();
+7 -6
View File
@@ -117,9 +117,10 @@ public class Ambusher : RoleBase
if (!DontCheck)
{
var pos = pc.Pos();
var radius = FollowRadius.GetFloat();
var closestPlayer = Main.AllAlivePlayerControls.Without(pc).Select(x => (pc: x, distance: Vector2.Distance(x.Pos(), pos))).Where(x => x.distance <= radius).MinBy(x => x.distance).pc;
Vector2 pos = pc.Pos();
float radius = FollowRadius.GetFloat();
(PlayerControl pc, float distance)[] nearPlayers = Main.AllAlivePlayerControls.Without(pc).Select(x => (pc: x, distance: Vector2.Distance(x.Pos(), pos))).Where(x => x.distance <= radius).ToArray();
PlayerControl closestPlayer = nearPlayers.Length == 0 ? null : nearPlayers.MinBy(x => x.distance).pc;
if (closestPlayer == null)
{
@@ -174,7 +175,7 @@ public class Ambusher : RoleBase
public override void OnGlobalFixedUpdate(PlayerControl pc, bool lowLoad)
{
if (!lowLoad && FragilePlayers.TryGetValue(pc.PlayerId, out var endTS) && Utils.TimeStamp >= endTS)
if (!lowLoad && FragilePlayers.TryGetValue(pc.PlayerId, out long endTS) && Utils.TimeStamp >= endTS)
FragilePlayers.Remove(pc.PlayerId);
}
@@ -198,7 +199,7 @@ public class Ambusher : RoleBase
public override string GetSuffix(PlayerControl seer, PlayerControl target, bool hud = false, bool meeting = false)
{
if (seer.PlayerId != AmbusherId || seer.PlayerId != target.PlayerId || hud || meeting || !Main.Invisible.Contains(AmbusherId)) return string.Empty;
string str = DontCheck ? Translator.GetString("Ambusher.Success") : string.Format(Translator.GetString("Ambusher.InProgress"), TargetId.ColoredPlayerName(), Math.Round(TargetTimer, 1));
return $"{str}\n{string.Format(Translator.GetString("Ambusher.InvisTimeLeft"), (int)Math.Round(AbilityEndTimer))}";
string str = DontCheck ? Translator.GetString("Ambusher.Success") : TargetId != byte.MaxValue ? string.Format(Translator.GetString("Ambusher.InProgress"), TargetId.ColoredPlayerName(), Math.Round(TargetTimer, 1)) : string.Empty;
return $"{str}\n<size=80%>{string.Format(Translator.GetString("Ambusher.InvisTimeLeft"), (int)Math.Round(AbilityEndTimer))}</size>";
}
}
+1
View File
@@ -40,6 +40,7 @@ public class Loner : RoleBase
PickedPlayer = target.PlayerId;
PickedRole = Enum.GetValues<CustomRoles>().Where(x => x.IsImpostor() && !x.IsVanilla() && !CustomRoleSelector.RoleResult.ContainsValue(x) && x.GetMode() != 0).RandomElement();
if (PickedRole == CustomRoles.Crewmate) PickedRole = CustomRoles.ImpostorEHR;
Utils.SendMessage("\n", shapeshifter.PlayerId, string.Format(Translator.GetString("Loner.Picked"), PickedPlayer.ColoredPlayerName(), PickedRole.ToColoredString()));
}
+3
View File
@@ -204,18 +204,21 @@ public sealed class Stealth : RoleBase
public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting)
{
if (!shapeshifting || useLegacyVersion) return true;
DarkenPlayers(FindPlayersInRange());
return false;
}
public override bool OnVanish(PlayerControl pc)
{
if (useLegacyVersion) return true;
DarkenPlayers(FindPlayersInRange());
return false;
}
public override void OnPet(PlayerControl pc)
{
if (useLegacyVersion) return;
DarkenPlayers(FindPlayersInRange());
}