Unshift button trigger (it's amazing), Add Beehive, Add Oxyman, Add Rhapsode, Bug Fixes

This commit is contained in:
Gurge44 committed 2024-07-18 18:55:29 +02:00
1 parent cf44d2b106
commit 1e9079d5bc
56 files changed
+927 -118

No files matched your search

+3
View File
@@ -199,12 +199,14 @@ public enum CustomRoles
Nightmare,
Observer,
Oracle,
Oxyman,
Paranoia,
Perceiver,
Philantropist,
Psychic,
Rabbit,
Randomizer,
Rhapsode,
Ricochet,
Safeguard,
Scout,
@@ -244,6 +246,7 @@ public enum CustomRoles
Arsonist,
Bandit,
Bargainer,
Beehive,
BloodKnight,
Bubble,
Chemist,
+3
View File
@@ -199,12 +199,14 @@ public enum CustomRoles
Nightmare,
Observer,
Oracle,
Oxyman,
Paranoia,
Perceiver,
Philantropist,
Psychic,
Rabbit,
Randomizer,
Rhapsode,
Ricochet,
Safeguard,
Scout,
@@ -244,6 +246,7 @@ public enum CustomRoles
Arsonist,
Bandit,
Bargainer,
Beehive,
BloodKnight,
Bubble,
Chemist,
+1
View File
@@ -28,6 +28,7 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=PC/@EntryIndexedValue">PC</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RNG/@EntryIndexedValue">RNG</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RPC/@EntryIndexedValue">RPC</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SE/@EntryIndexedValue">SE</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SK/@EntryIndexedValue">SK</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SS/@EntryIndexedValue">SS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SSCD/@EntryIndexedValue">SSCD</s:String>
+15 -5
View File
@@ -86,7 +86,8 @@ internal static class CustomRolesHelper
if (role.IsGhostRole()) return CustomRoles.GuardianAngel;
if (role.IsVanilla()) return role;
if (checkDesyncRole && role.GetDYRole() == RoleTypes.Impostor) return CustomRoles.Impostor;
if (Options.UsePhantomBasis.GetBool() && role.InvisActivatedAbility()) return CustomRoles.Phantom;
if (Options.UsePhantomBasis.GetBool() && role.SimpleAbilityTrigger()) return CustomRoles.Phantom;
if (Options.UseUnshiftTrigger.GetBool() && role.SimpleAbilityTrigger()) return CustomRoles.Shapeshifter;
bool UsePets = Options.UsePets.GetBool();
return role switch
{
@@ -196,11 +197,13 @@ internal static class CustomRolesHelper
CustomRoles.GuessManagerRole => CustomRoles.Crewmate,
CustomRoles.Altruist => CustomRoles.Crewmate,
CustomRoles.Transmitter => CustomRoles.Crewmate,
CustomRoles.Oxyman => CustomRoles.Engineer,
CustomRoles.Chef => CustomRoles.Crewmate,
CustomRoles.Lyncher => CustomRoles.Crewmate,
CustomRoles.Adrenaline => CustomRoles.Crewmate,
CustomRoles.Safeguard => CustomRoles.Crewmate,
CustomRoles.Clairvoyant => UsePets ? CustomRoles.Crewmate : CustomRoles.Engineer,
CustomRoles.Rhapsode => UsePets ? CustomRoles.Crewmate : CustomRoles.Engineer,
CustomRoles.Telekinetic => CustomRoles.Engineer,
CustomRoles.Autocrat => CustomRoles.Crewmate,
CustomRoles.Inquirer => CustomRoles.Crewmate,
@@ -343,7 +346,8 @@ internal static class CustomRolesHelper
public static RoleTypes GetDYRole(this CustomRoles role, bool load = false)
{
if (!load && Options.UsePhantomBasis.GetBool() && Options.UsePhantomBasisForNKs.GetBool() && !role.IsImpostor() && role.InvisActivatedAbility()) return RoleTypes.Phantom;
if (!load && Options.UsePhantomBasis.GetBool() && Options.UsePhantomBasisForNKs.GetBool() && !role.IsImpostor() && role.SimpleAbilityTrigger()) return RoleTypes.Phantom;
if (!load && Options.UseUnshiftTrigger.GetBool() && Options.UseUnshiftTriggerForNKs.GetBool() && !role.IsImpostor() && role.SimpleAbilityTrigger()) return RoleTypes.Shapeshifter;
bool UsePets = !load && Options.UsePets.GetBool();
return role switch
{
@@ -398,6 +402,7 @@ internal static class CustomRolesHelper
CustomRoles.BloodKnight => RoleTypes.Impostor,
CustomRoles.Poisoner => RoleTypes.Impostor,
CustomRoles.NSerialKiller => RoleTypes.Impostor,
CustomRoles.Beehive => RoleTypes.Impostor,
CustomRoles.RouleteGrandeur => RoleTypes.Impostor,
CustomRoles.Nonplus => RoleTypes.Impostor,
CustomRoles.Tremor => RoleTypes.Impostor,
@@ -514,6 +519,7 @@ internal static class CustomRolesHelper
CustomRoles.Rogue or
CustomRoles.Parasite or
CustomRoles.NSerialKiller or
CustomRoles.Beehive or
CustomRoles.RouleteGrandeur or
CustomRoles.Nonplus or
CustomRoles.Tremor or
@@ -848,7 +854,7 @@ internal static class CustomRolesHelper
public static bool IsNoAnimationShifter(this CustomRoles role) => role is
CustomRoles.Echo;
public static bool InvisActivatedAbility(this CustomRoles role) => role is
public static bool SimpleAbilityTrigger(this CustomRoles role) => role is
CustomRoles.Warlock or
CustomRoles.Swiftclaw or
CustomRoles.Undertaker or
@@ -883,6 +889,7 @@ internal static class CustomRolesHelper
public static bool CheckAddonConflict(CustomRoles role, PlayerControl pc) => role.IsAdditionRole() && (!Main.NeverSpawnTogetherCombos.TryGetValue(OptionItem.CurrentPreset, out var neverList) || !neverList.TryGetValue(pc.GetCustomRole(), out var bannedAddonList) || !bannedAddonList.Contains(role)) && pc.GetCustomRole() is not CustomRoles.GuardianAngelEHR and not CustomRoles.God && !pc.Is(CustomRoles.Madmate) && !pc.Is(CustomRoles.GM) && role is not CustomRoles.Lovers && !pc.Is(CustomRoles.Needy) && (!pc.HasSubRole() || pc.GetCustomSubRoles().Count < Options.NoLimitAddonsNumMax.GetInt()) && (!Options.AddonCanBeSettings.TryGetValue(role, out var o) || ((o.Imp.GetBool() || !pc.GetCustomRole().IsImpostor()) && (o.Neutral.GetBool() || !pc.GetCustomRole().IsNeutral()) && (o.Crew.GetBool() || !pc.IsCrewmate()))) && (!role.IsImpOnlyAddon() || pc.IsImpostor()) && role switch
{
CustomRoles.Oblivious when pc.Is(CustomRoles.Amnesiac) && Amnesiac.RememberMode.GetValue() == 1 => false,
CustomRoles.Rookie when !pc.CanUseKillButton() => false,
CustomRoles.Energetic when !Options.UsePets.GetBool() => false,
CustomRoles.Madmate when pc.Is(CustomRoles.Sidekick) => false,
@@ -908,7 +915,7 @@ internal static class CustomRolesHelper
CustomRoles.Egoist when !pc.IsImpostor() => false,
CustomRoles.Damocles when pc.GetCustomRole() is CustomRoles.Bomber or CustomRoles.Nuker or CustomRoles.SerialKiller or CustomRoles.Cantankerous => false,
CustomRoles.Damocles when !pc.CanUseKillButton() => false,
CustomRoles.Flashman when pc.Is(CustomRoles.Swiftclaw) || pc.Is(CustomRoles.Giant) || pc.Is(CustomRoles.Spurt)=> false,
CustomRoles.Flashman when pc.Is(CustomRoles.Swiftclaw) || pc.Is(CustomRoles.Giant) || pc.Is(CustomRoles.Spurt) => false,
CustomRoles.Giant when pc.Is(CustomRoles.Flashman) || pc.Is(CustomRoles.Spurt) => false,
CustomRoles.Necroview when pc.Is(CustomRoles.Visionary) => false,
CustomRoles.Mimic when pc.Is(CustomRoles.Mafia) => false,
@@ -1124,6 +1131,7 @@ internal static class CustomRolesHelper
CustomRoles.SchrodingersCat => SchrodingersCat.WinsWithCrewIfNotAttacked.GetBool() ? CountTypes.Crew : CountTypes.OutOfGame,
CustomRoles.DarkHide => !DarkHide.SnatchesWin.GetBool() ? CountTypes.DarkHide : CountTypes.Crew,
CustomRoles.Arsonist => Options.ArsonistKeepsGameGoing.GetBool() ? CountTypes.Arsonist : CountTypes.Crew,
CustomRoles.Sheriff => Sheriff.KeepsGameGoing.GetBool() ? CountTypes.Sheriff : CountTypes.Crew,
CustomRoles.Shifter => CountTypes.OutOfGame,
_ => Enum.TryParse(role.ToString(), true, out CountTypes type)
@@ -1256,6 +1264,7 @@ public enum CountTypes
HexMaster,
Wraith,
NSerialKiller,
Beehive,
RouleteGrandeur,
Nonplus,
Tremor,
@@ -1299,5 +1308,6 @@ public enum CountTypes
PlagueBearer,
Glitch,
Arsonist,
Cherokious
Cherokious,
Sheriff
}
@@ -413,9 +413,12 @@ public class PlayerGameOptionsSender(PlayerControl player) : GameOptionsSender
AURoleOptions.ShapeshifterDuration = 1f;
}
if (Options.UsePhantomBasis.GetBool() && role.InvisActivatedAbility())
if (Options.UsePhantomBasis.GetBool() && role.SimpleAbilityTrigger())
AURoleOptions.PhantomDuration = 1f;
if (Options.UseUnshiftTrigger.GetBool() && role.SimpleAbilityTrigger())
AURoleOptions.ShapeshifterDuration = 0f;
// ===================================================================================================================
AURoleOptions.EngineerCooldown = Mathf.Max(0.01f, AURoleOptions.EngineerCooldown);
+1
View File
@@ -321,6 +321,7 @@ public static class GuessManager
if (!isUI) Utils.SendMessage(GetString("GuessSuperStar"), pc.PlayerId);
else pc.ShowPopUp(GetString("GuessSuperStar"));
return true;
case CustomRoles.DonutDelivery when DonutDelivery.IsUnguessable(pc, target):
case CustomRoles.Shifter:
case CustomRoles.Goose when !Goose.CanBeGuessed.GetBool():
case CustomRoles.Disco:
+1
View File
@@ -151,6 +151,7 @@ public static class NameColorManager
CustomRoles.Augmenter when ((Augmenter)Main.PlayerStates[seer.PlayerId].Role).Target == target.PlayerId => "000000",
CustomRoles.Socialite when ((Socialite)Main.PlayerStates[seer.PlayerId].Role).GuestList.Contains(target.PlayerId) => "000000",
CustomRoles.Socialite when ((Socialite)Main.PlayerStates[seer.PlayerId].Role).MarkedPlayerId == target.PlayerId => Main.RoleColors[seerRole],
CustomRoles.Beehive when ((Beehive)Main.PlayerStates[seer.PlayerId].Role).StungPlayers.ContainsKey(target.PlayerId) => "000000",
_ => color
};
+13 -10
View File
@@ -655,6 +655,8 @@ public static class Options
public static OptionItem UsePets;
public static OptionItem PetToAssignToEveryone;
public static OptionItem UseUnshiftTrigger;
public static OptionItem UseUnshiftTriggerForNKs;
public static OptionItem UsePhantomBasis;
public static OptionItem UsePhantomBasisForNKs;
public static OptionItem UseVoteCancelling;
@@ -1620,23 +1622,24 @@ public static class Options
UsePets = new BooleanOptionItem(23850, "UsePets", false, TabGroup.TaskSettings)
.SetHeader(true)
.SetColor(new Color32(60, 0, 255, byte.MaxValue))
.RegisterUpdateValueEvent((o, _) =>
{
if ((((OptionItem)o)!).GetBool()) UsePhantomBasis.SetValue(0);
});
.SetColor(new Color32(60, 0, 255, byte.MaxValue));
PetToAssignToEveryone = new StringOptionItem(23854, "PetToAssign", PetToAssign, 24, TabGroup.TaskSettings)
.SetParent(UsePets)
.SetColor(new Color32(60, 0, 255, byte.MaxValue));
UseUnshiftTrigger = new BooleanOptionItem(23871, "UseUnshiftTrigger", false, TabGroup.TaskSettings)
.SetGameMode(CustomGameMode.Standard)
.SetHeader(true)
.SetColor(new Color32(255, 44, 44, byte.MaxValue));
UseUnshiftTriggerForNKs = new BooleanOptionItem(23872, "UseUnshiftTriggerForNKs", false, TabGroup.TaskSettings)
.SetParent(UseUnshiftTrigger)
.SetGameMode(CustomGameMode.Standard)
.SetColor(new Color32(255, 44, 44, byte.MaxValue));
UsePhantomBasis = new BooleanOptionItem(23851, "UsePhantomBasis", false, TabGroup.TaskSettings)
.SetGameMode(CustomGameMode.Standard)
.SetHeader(true)
.SetColor(new Color32(255, 255, 44, byte.MaxValue))
.RegisterUpdateValueEvent((o, _) =>
{
if ((((OptionItem)o)!).GetBool()) UsePets.SetValue(0);
});
.SetColor(new Color32(255, 255, 44, byte.MaxValue));
UsePhantomBasisForNKs = new BooleanOptionItem(23864, "UsePhantomBasisForNKs", false, TabGroup.TaskSettings)
.SetGameMode(CustomGameMode.Standard)
.SetParent(UsePhantomBasis)
+1 -2
View File
@@ -4,7 +4,6 @@ using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using Il2CppInterop.Runtime.InteropTypes;
using StringComparison = Il2CppSystem.StringComparison;
namespace EHR;
@@ -32,7 +31,7 @@ public static class ServerAddManager
// regionInfos.Add(CreateHttp("35.247.251.253", "Modded SA (MSA)", 22023, false));
regionInfos.Where(x => !ServerManager.AvailableRegions.Contains(x)).Do(ServerManager.AddOrUpdateRegion);
ServerManager.CurrentRegion = ServerManager.AvailableRegions.FirstOrDefault(x => x.Name.Contains("Europe", StringComparison.OrdinalIgnoreCase)) ?? ServerManager.AvailableRegions.FirstOrDefault() ?? regionInfos.First();
ServerManager.AvailableRegions = ServerManager.AvailableRegions.OrderByDescending(ServerManager.DefaultRegions.Contains).ToArray();
}
private static IRegionInfo CreateHttp(string ip, string name, ushort port, bool ishttps)
+70 -4
View File
@@ -653,6 +653,7 @@ public static class Utils
case CustomRoles.Eclipse:
case CustomRoles.Pyromaniac:
case CustomRoles.NSerialKiller:
case CustomRoles.Beehive:
case CustomRoles.RouleteGrandeur:
case CustomRoles.Nonplus:
case CustomRoles.Tremor:
@@ -1578,7 +1579,7 @@ public static class Utils
{
if (!AmongUsClient.Instance.AmHost) return;
if (title == "") title = "<color=#8b32a8>" + GetString("DefaultSystemMessageTitle") + "</color>";
if (title.Contains('\u2605'))
if (title.Count(x => x == '\u2605') == 2 && !title.Contains('\n'))
{
if (title.Contains('<') && title.Contains('>') && title.Contains('#'))
title = $"{title[..(title.IndexOf('>') + 1)]}\u27a1{title.Replace("\u2605", "")[..(title.LastIndexOf('<') - 2)]}\u2b05";
@@ -2023,6 +2024,7 @@ public static class Utils
TargetMark.Append(ColorString(GetRoleColor(CustomRoles.BallLightning), "■"));
TargetMark.Append(Snitch.GetWarningMark(seer, target));
TargetMark.Append(Marshall.GetWarningMark(seer, target));
if ((seer.Data.IsDead || Main.LoversPlayers.Any(x => x.PlayerId == seer.PlayerId)) && Main.LoversPlayers.Any(x => x.PlayerId == target.PlayerId))
{
@@ -2270,7 +2272,58 @@ public static class Utils
Main.Instance.StartCoroutine(GameOptionsSender.SendAllGameOptionsAsync());
}
public static string GetGameStateData()
public static void RpcChangeSkin(PlayerControl pc, NetworkedPlayerInfo.PlayerOutfit newOutfit)
{
var sender = CustomRpcSender.Create(name: $"Utils.RpcChangeSkin({pc.Data.PlayerName})");
pc.SetName(newOutfit.PlayerName);
sender.AutoStartRpc(pc.NetId, (byte)RpcCalls.SetName)
.Write(pc.Data.NetId)
.Write(newOutfit.PlayerName)
.EndRpc();
Main.AllPlayerNames[pc.PlayerId] = newOutfit.PlayerName;
pc.SetColor(newOutfit.ColorId);
sender.AutoStartRpc(pc.NetId, (byte)RpcCalls.SetColor)
.Write(pc.Data.NetId)
.Write((byte)newOutfit.ColorId)
.EndRpc();
pc.SetHat(newOutfit.HatId, newOutfit.ColorId);
sender.AutoStartRpc(pc.NetId, (byte)RpcCalls.SetHatStr)
.Write(newOutfit.HatId)
.Write(pc.GetNextRpcSequenceId(RpcCalls.SetHatStr))
.EndRpc();
pc.SetSkin(newOutfit.SkinId, newOutfit.ColorId);
sender.AutoStartRpc(pc.NetId, (byte)RpcCalls.SetSkinStr)
.Write(newOutfit.SkinId)
.Write(pc.GetNextRpcSequenceId(RpcCalls.SetSkinStr))
.EndRpc();
pc.SetVisor(newOutfit.VisorId, newOutfit.ColorId);
sender.AutoStartRpc(pc.NetId, (byte)RpcCalls.SetVisorStr)
.Write(newOutfit.VisorId)
.Write(pc.GetNextRpcSequenceId(RpcCalls.SetVisorStr))
.EndRpc();
pc.SetPet(newOutfit.PetId);
sender.AutoStartRpc(pc.NetId, (byte)RpcCalls.SetPetStr)
.Write(newOutfit.PetId)
.Write(pc.GetNextRpcSequenceId(RpcCalls.SetPetStr))
.EndRpc();
pc.SetNamePlate(newOutfit.NamePlateId);
sender.AutoStartRpc(pc.NetId, (byte)RpcCalls.SetNamePlateStr)
.Write(newOutfit.NamePlateId)
.Write(pc.GetNextRpcSequenceId(RpcCalls.SetNamePlateStr))
.EndRpc();
sender.SendMessage();
}
public static string GetGameStateData(bool clairvoyant = false)
{
var nums = Enum.GetValues<Options.GameStateInfo>().ToDictionary(x => x, _ => 0);
@@ -2300,8 +2353,9 @@ public static class Utils
// 24: Romantic exists, has picked a partner who is alive, and Romantic is alive
var sb = new StringBuilder();
var checkDict = clairvoyant ? Clairvoyant.Settings : Options.GameStateSettings;
var states = nums.ToDictionary(x => x.Key, x => x.Key == Options.GameStateInfo.RomanticState ? GetString($"GSRomanticState.{x.Value}") : (object)x.Value);
states.DoIf(x => Options.GameStateSettings[x.Key].GetBool(), x => sb.AppendLine(string.Format(GetString($"GSInfo.{x.Key}"), x.Value)));
states.DoIf(x => checkDict[x.Key].GetBool(), x => sb.AppendLine(string.Format(GetString($"GSInfo.{x.Key}"), x.Value)));
return sb.ToString().TrimEnd();
}
@@ -2325,6 +2379,7 @@ public static class Utils
CustomRoles.SecurityGuard => Options.SecurityGuardSkillCooldown.GetInt() + (includeDuration ? Options.SecurityGuardSkillDuration.GetInt() : 0),
CustomRoles.TimeMaster => Options.TimeMasterSkillCooldown.GetInt() + (includeDuration ? Options.TimeMasterSkillDuration.GetInt() : 0),
CustomRoles.Veteran => Options.VeteranSkillCooldown.GetInt() + (includeDuration ? Options.VeteranSkillDuration.GetInt() : 0),
CustomRoles.Rhapsode => Rhapsode.AbilityCooldown.GetInt() + (includeDuration ? Rhapsode.AbilityDuration.GetInt() : 0),
CustomRoles.Perceiver => Perceiver.CD.GetInt(),
CustomRoles.Convener => Convener.CD.GetInt(),
CustomRoles.DovesOfNeace => Options.DovesOfNeaceCooldown.GetInt(),
@@ -2376,7 +2431,7 @@ public static class Utils
if (loversChat) GameEndChecker.Prefix();
Lovers.IsChatActivated = false;
Main.ProcessShapeshifts = true;
if (!Options.UseUnshiftTrigger.GetBool()) Main.ProcessShapeshifts = true;
AFKDetector.NumAFK = 0;
AFKDetector.PlayerData.Clear();
@@ -2400,6 +2455,14 @@ public static class Utils
if (Options.UsePets.GetBool()) pc.AddAbilityCD(includeDuration: false);
if (pc.GetCustomRole().SimpleAbilityTrigger() && Options.UseUnshiftTrigger.GetBool() && (!pc.IsNeutralKiller() || Options.UseUnshiftTriggerForNKs.GetBool()))
{
var target = Main.AllAlivePlayerControls.Without(pc).RandomElement();
var outfit = pc.Data.DefaultOutfit;
pc.RpcShapeshift(target, false);
RpcChangeSkin(pc, outfit);
}
AFKDetector.RecordPosition(pc);
Main.PlayerStates[pc.PlayerId].Role.AfterMeetingTasks();
@@ -2418,6 +2481,8 @@ public static class Utils
Main.CheckShapeshift[pc.PlayerId] = false;
}
LateTask.New(() => Main.ProcessShapeshifts = true, 1f, log: false);
CopyCat.ResetRoles();
if (Options.DiseasedCDReset.GetBool())
@@ -2554,6 +2619,7 @@ public static class Utils
Scout.OnPlayerDeath(target);
Adventurer.OnAnyoneDead(target);
Soothsayer.OnAnyoneDeath(target.GetRealKiller(), target);
Amnesiac.OnAnyoneDeath(target);
EHR.Impostor.Sentry.OnAnyoneMurder(target);
if (QuizMaster.On) QuizMaster.Data.NumPlayersDeadThisRound++;
+8 -2
View File
@@ -5,6 +5,7 @@ using System.Linq;
using AmongUs.GameOptions;
using BepInEx.Unity.IL2CPP.Utils.Collections;
using EHR.AddOns.GhostRoles;
using EHR.Crewmate;
using EHR.Impostor;
using EHR.Modules;
using EHR.Neutral;
@@ -389,8 +390,10 @@ class GameEndChecker
return true;
}
var sheriffCount = AlivePlayersCount(CountTypes.Sheriff);
int Imp = AlivePlayersCount(CountTypes.Impostor);
int Crew = AlivePlayersCount(CountTypes.Crew);
int Crew = AlivePlayersCount(CountTypes.Crew) + sheriffCount;
Dictionary<(CustomRoles? ROLE, CustomWinner WINNER), int> roleCounts = [];
@@ -464,6 +467,9 @@ class GameEndChecker
// There are multiple types of NKs alive, game must continue
case > 1:
return false;
// If the Sheriff keeps the game going, the game must continue
case 1 when Sheriff.KeepsGameGoing.GetBool() && sheriffCount > 0:
return false;
// There is only one type of NK alive, they've won
case 1:
{
@@ -788,4 +794,4 @@ class CheckGameEndPatch
__result = GameEndChecker.Predicate?.CheckGameEndByTask(out _) ?? false;
return false;
}
}
}
+2
View File
@@ -46,6 +46,8 @@ internal class PingTrackerUpdatePatch
};
Sb.Append(GameStates.InGame ? " - " : "\r\n");
Sb.Append($"<color={color}>{GetString("PingText")}: {ping} ms</color>");
Sb.Append(GameStates.InGame ? " - " : "\r\n");
Sb.Append(string.Format(GetString("Server"), Utils.GetRegionName()));
if (GameStates.InGame) Sb.Append("\r\n.");
// if (Options.NoGameEnd.GetBool()) Sb.Append("\r\n<size=1.2>").Append(Utils.ColorString(Color.red, GetString("NoGameEnd"))).Append("</size>");
+1 -1
View File
@@ -795,7 +795,7 @@ public class GameSettingMenuPatch
{
settingsTab.gameObject.SetActive(true);
__instance.MenuDescriptionText.DestroyTranslator();
__instance.MenuDescriptionText.text = Translator.GetString($"TabInfo.{tabGroup}");
__instance.MenuDescriptionText.text = Translator.GetString("TabInfoTip");
}
}
+18
View File
@@ -741,6 +741,24 @@ class IntroCutsceneDestroyPatch
LateTask.New(() => Main.ProcessShapeshifts = true, 1f, "Enable SS Processing");
}
if (Options.UseUnshiftTrigger.GetBool())
{
LateTask.New(() =>
{
foreach (var pc in Main.AllAlivePlayerControls)
{
if (pc.GetCustomRole().SimpleAbilityTrigger() && (!pc.IsNeutralKiller() || Options.UseUnshiftTriggerForNKs.GetBool()))
{
var target = Main.AllAlivePlayerControls.Without(pc).RandomElement();
var outfit = pc.Data.DefaultOutfit;
pc.RpcShapeshift(target, false);
Utils.RpcChangeSkin(pc, outfit);
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc, NoCache: true);
}
}
}, 2f, "UnshiftTrigger SS");
}
if (PlayerControl.LocalPlayer.Is(CustomRoles.GM))
{
PlayerControl.LocalPlayer.RpcExile();
+8 -5
View File
@@ -423,15 +423,17 @@ internal class SelectRolesPatch
HashSet<byte> bloodlustList = RoleResult.Where(x => x.Value.IsCrewmate() && !x.Value.IsTaskBasedCrewmate()).Select(x => x.Key.PlayerId).ToHashSet();
if (bloodlustList.Count == 0) bloodlustSpawn = false;
if (Main.AlwaysSpawnTogetherCombos[OptionItem.CurrentPreset].Values.Any(l => l.Contains(CustomRoles.Bloodlust)))
if (Main.AlwaysSpawnTogetherCombos.TryGetValue(OptionItem.CurrentPreset, out var combos) && combos.Values.Any(l => l.Contains(CustomRoles.Bloodlust)))
{
var roles = Main.AlwaysSpawnTogetherCombos[OptionItem.CurrentPreset].Where(x => x.Value.Contains(CustomRoles.Bloodlust)).Select(x => x.Key).ToHashSet();
var roles = combos.Where(x => x.Value.Contains(CustomRoles.Bloodlust)).Select(x => x.Key).ToHashSet();
var players = RoleResult.Where(x => roles.Contains(x.Value) && x.Value.IsCrewmate() && !x.Value.IsTaskBasedCrewmate()).Select(x => x.Key.PlayerId).ToHashSet();
if (players.Count > 0)
{
bloodlustList = players;
bloodlustSpawn = true;
}
combos.Do(x => x.Value.Remove(CustomRoles.Bloodlust));
}
if (Main.SetAddOns.Values.Any(x => x.Contains(CustomRoles.Bloodlust)))
@@ -522,9 +524,9 @@ internal class SelectRolesPatch
(CustomRoles addon, (bool SpawnFlag, HashSet<byte> RoleList) value) = roleSpawnMapping.ElementAt(i);
if (value.RoleList.Count == 0) value.SpawnFlag = false;
if (Main.AlwaysSpawnTogetherCombos[OptionItem.CurrentPreset].Values.Any(l => l.Contains(addon)))
if (Main.AlwaysSpawnTogetherCombos.TryGetValue(OptionItem.CurrentPreset, out var combos) && combos.Values.Any(l => l.Contains(addon)))
{
var roles = Main.AlwaysSpawnTogetherCombos[OptionItem.CurrentPreset].Where(x => x.Value.Contains(addon)).Select(x => x.Key).ToHashSet();
var roles = combos.Where(x => x.Value.Contains(addon)).Select(x => x.Key).ToHashSet();
var players = RoleResult.Where(x => roles.Contains(x.Value) && x.Value.IsCrewmate() && (addon == CustomRoles.Nimble || x.Value.GetRoleTypes() == RoleTypes.Crewmate) && !IsBasisChangingPlayer(x.Key.PlayerId, CustomRoles.Bloodlust)).Select(x => x.Key.PlayerId).ToHashSet();
if (players.Count > 0)
{
@@ -532,6 +534,8 @@ internal class SelectRolesPatch
value.SpawnFlag = true;
roleSpawnMapping[addon] = value;
}
combos.Do(x => x.Value.Remove(addon));
}
if (Main.SetAddOns.Values.Any(x => x.Contains(addon)))
@@ -725,7 +729,6 @@ internal class SelectRolesPatch
if (Main.NeverSpawnTogetherCombos.TryGetValue(OptionItem.CurrentPreset, out var neverList) && neverList.TryGetValue(state.MainRole, out var bannedAddonList))
{
bannedAddonList.ForEach(x => state.RemoveSubRole(x));
continue;
}
if (Main.AlwaysSpawnTogetherCombos.TryGetValue(OptionItem.CurrentPreset, out var alwaysList) && alwaysList.TryGetValue(state.MainRole, out var addonList))
+36 -12
View File
@@ -735,6 +735,8 @@ class ShapeshiftPatch
return true;
}
if (AmongUsClient.Instance.AmHost && shapeshifting && !Rhapsode.CheckAbilityUse(shapeshifter)) return false;
Main.CheckShapeshift[shapeshifter.PlayerId] = shapeshifting;
Main.ShapeshiftTarget[shapeshifter.PlayerId] = target.PlayerId;
@@ -756,6 +758,8 @@ class ShapeshiftPatch
var role = shapeshifter.GetCustomRole();
bool forceCancel = role.ForceCancelShapeshift();
bool unshiftTrigger = role.SimpleAbilityTrigger() && Options.UseUnshiftTrigger.GetBool() && (!role.IsNeutral() || Options.UseUnshiftTriggerForNKs.GetBool());
forceCancel |= unshiftTrigger;
if (shapeshifter.Is(CustomRoles.Camouflager) && !shapeshifting) Camouflager.Reset();
if (Changeling.ChangedRole.TryGetValue(shapeshifter.PlayerId, out var changed) && changed && shapeshifter.GetRoleTypes() != RoleTypes.Shapeshifter)
@@ -797,7 +801,16 @@ class ShapeshiftPatch
return false;
}
return isSSneeded || (!shouldCancel && !forceCancel) || (!shapeshifting && !shouldAlwaysCancel);
if (unshiftTrigger)
{
var rndTarget = Main.AllAlivePlayerControls.Without(shapeshifter).RandomElement();
var outfit = shapeshifter.Data.DefaultOutfit;
shapeshifter.RpcShapeshift(rndTarget, false);
RpcChangeSkin(shapeshifter, outfit);
NotifyRoles(SpecifySeer: shapeshifter, SpecifyTarget: shapeshifter, NoCache: true);
}
return isSSneeded || (!shouldCancel && !forceCancel) || (!shapeshifting && !shouldAlwaysCancel && !unshiftTrigger);
}
// Tasks that should run when someone performs a shapeshift (with the egg animation) should be here.
@@ -1083,7 +1096,12 @@ class ReportDeadBodyPatch
LateTask.New(SyncAllSettings, 3f, "SyncAllSettings on meeting start");
LateTask.New(() => Main.ProcessShapeshifts = false, 5f, log: false);
Main.ProcessShapeshifts = false;
foreach (var pc in Main.AllAlivePlayerControls)
{
if (pc.GetCustomRole().SimpleAbilityTrigger() && Options.UseUnshiftTrigger.GetBool() && (!pc.IsNeutralKiller() || Options.UseUnshiftTriggerForNKs.GetBool()))
pc.RpcShapeshift(pc, false);
}
}
}
@@ -1849,13 +1867,13 @@ class CoEnterVentPatch
LateTask.New(() =>
{
__instance.myPlayer?.Notify(GetString("FFA-NoVentingBecauseKCDIsUP"), 7f);
__instance.myPlayer?.MyPhysics?.RpcBootFromVent(id);
__instance.RpcBootFromVent(id);
}, 0.5f, "FFA-NoVentingWhenKCDIsUP");
return true;
case CustomGameMode.MoveAndStop:
case CustomGameMode.HotPotato:
case CustomGameMode.Speedrun:
LateTask.New(() => { __instance.myPlayer?.MyPhysics?.RpcBootFromVent(id); }, 0.5f, log: false);
LateTask.New(() => __instance.RpcBootFromVent(id), 0.5f, log: false);
return true;
case CustomGameMode.HideAndSeek:
HnSManager.OnCoEnterVent(__instance, id);
@@ -1867,14 +1885,20 @@ class CoEnterVentPatch
LateTask.New(() =>
{
__instance.myPlayer?.Notify(BlockedAction.Vent.GetBlockNotify());
__instance.myPlayer?.MyPhysics?.RpcBootFromVent(id);
__instance.RpcBootFromVent(id);
}, 0.5f, "RoleBlockedBootFromVent");
return true;
}
if (!Rhapsode.CheckAbilityUse(__instance.myPlayer))
{
LateTask.New(() => __instance.RpcBootFromVent(id), 0.5f, log: false);
return true;
}
if (Penguin.IsVictim(__instance.myPlayer))
{
LateTask.New(() => { __instance.myPlayer?.MyPhysics?.RpcBootFromVent(id); }, 0.5f, "PenguinVictimBootFromVent");
LateTask.New(() => __instance.RpcBootFromVent(id), 0.5f, "PenguinVictimBootFromVent");
return true;
}
@@ -1883,7 +1907,7 @@ class CoEnterVentPatch
LateTask.New(() =>
{
__instance.myPlayer?.Notify(GetString("SoulHunterTargetNotifyNoVent"));
__instance.myPlayer?.MyPhysics?.RpcBootFromVent(id);
__instance.RpcBootFromVent(id);
LateTask.New(() =>
{
if (SoulHunter.IsSoulHunterTarget(__instance.myPlayer.PlayerId)) __instance.myPlayer.Notify(string.Format(GetString("SoulHunterTargetNotify"), SoulHunter.GetSoulHunter(__instance.myPlayer.PlayerId).SoulHunter_.GetRealName()), 300f);
@@ -1900,7 +1924,7 @@ class CoEnterVentPatch
LateTask.New(() =>
{
pc?.Notify(GetString("EnteredBlockedVent"));
pc?.MyPhysics?.RpcBootFromVent(id);
__instance.RpcBootFromVent(id);
}, 0.5f, "VentguardBlockedVentBootFromVent");
if (Ventguard.VentguardNotifyOnBlockedVentUse.GetBool())
@@ -1922,7 +1946,7 @@ class CoEnterVentPatch
if (__instance.myPlayer.GetCustomRole().GetDYRole() == RoleTypes.Impostor && !Main.PlayerStates[__instance.myPlayer.PlayerId].Role.CanUseImpostorVentButton(__instance.myPlayer) && Options.CurrentGameMode is CustomGameMode.Standard or CustomGameMode.HideAndSeek && !__instance.myPlayer.Is(CustomRoles.Nimble) && !__instance.myPlayer.Is(CustomRoles.Bloodlust))
{
LateTask.New(() => { __instance.RpcBootFromVent(id); }, 0.5f, "CannotUseVentBootFromVent");
LateTask.New(() => __instance.RpcBootFromVent(id), 0.5f, "CannotUseVentBootFromVent");
}
if (((__instance.myPlayer.Data.Role.Role != RoleTypes.Engineer && !__instance.myPlayer.CanUseImpostorVentButton()) ||
@@ -1932,7 +1956,7 @@ class CoEnterVentPatch
{
try
{
LateTask.New(() => { __instance.RpcBootFromVent(id); }, 0.5f, "CannotUseVentBootFromVent2");
LateTask.New(() => __instance.RpcBootFromVent(id), 0.5f, "CannotUseVentBootFromVent2");
return true;
}
catch
@@ -2192,8 +2216,8 @@ class CheckVanishPatch
{
Logger.Info($" {__instance.GetNameWithRole()}", "CheckVanish");
bool allow = Main.PlayerStates[__instance.PlayerId].Role.OnVanish(__instance);
if (!allow) __instance.RpcResetAbilityCooldown();
return allow;
if (!allow) LateTask.New(__instance.RpcResetAbilityCooldown, 0.2f, log: false);
return true;
}
}
+34 -18
View File
@@ -6,6 +6,7 @@
"HostColor": "#4bf4ff",
"Icon": "♥",
"NameColor": "#00ffa5",
"Server": "<#00ffa5>Server:</color> <b>{0}</b>",
"SubText.Crewmate": "Find and exile the <color=#ff1919>Impostors</color>",
"SubText.Impostor": "Sabotage and kill everyone",
"SubText.Neutral": "A team on their own",
@@ -31,23 +32,6 @@
"MadmateSub": "Help the <color=#ff1919>Impostors</color>",
"KB_Normal": "Challenger",
"KB_NormalInfo": "Kill all of them!",
"Role.Crewmate": "<color=#8cffff>Crewmate</color>",
"Role.Jester": "<color=#ec62a5>Jester</color>",
"Role.Opportunist": "<color=#4dff4d>Opportunist</color>",
"Role.Convict": "<color=#ff1919>Convict</color>",
"Role.Celebrity": "<color=#ee4a55>Celebrity</color>",
"Role.Bodyguard": "<color=#185abd>Bodyguard</color>",
"Role.Dictator": "<color=#df9b00>Dictator</color>",
"Role.Mayor": "<color=#204d42>Mayor</color>",
"Role.Doctor": "<color=#80ffdd>Doctor</color>",
"Role.Maverick": "<color=#781717>Maverick</color>",
"Role.Witch": "<color=#BF5FFF>Witch</color>",
"Role.Pursuer": "<color=#617218>Pursuer</color>",
"Role.Follower": "<color=#ff9409>Follower</color>",
"Role.Amnesiac": "<color=#7FBFFF>Amnesiac</color>",
"Role.Sheriff": "<color=#ffb347>Sheriff</color>",
"Role.Knight": "<color=#7A7A7A>Vigilante</color>",
"Role.Deputy": "<color=#DF9026>Deputy</color>",
"UnsupportedMap": "This map is not supported by EHR\\nPlease use a supported map or you'll experience issues",
"GuesserMode": "Guesser Mode",
"CrewmatesCanGuess": "<color=#8cffff>Crewmates</color> can guess",
@@ -1036,6 +1020,7 @@
"IncreasedVision": "Increased Vision",
"IncreasedVisionDuration": "Increased Vision Duration",
"ShieldDuration": "Shield Duration",
"DecreasedSpeed": "Decreased Speed",
"ChangeDecontaminationTime": "Change Decontamination Time (<color=#e84b56>MIRA HQ</color>/<color=#a167c0>Polus</color>)",
"DecontaminationTimeOnMiraHQ": "Decontamination Time On <color=#e84b56>MIRA HQ</color>",
"DecontaminationTimeOnPolus": "Decontamination Time On <color=#a167c0>Polus</color>",
@@ -1322,6 +1307,7 @@
"SheriffCanKillLovers": "Can Kill <color=#ff9ace>Lovers</color>",
"SheriffCanKillMadmate": "Can Kill <color=#ff1919>Madmates</color>",
"SheriffCanKillContagious": "Can Kill <color=#2E8B57>Contagious</color> players",
"SheriffKeepsGameGoing": "Keeps the game going",
"SheriffSetMadCanKill": "Non-<color=#8cffff>Crew</color> <color=#f8cd46>Sheriff</color> Configuration",
"SheriffMadCanKillImp": "Can kill <color=#ff1919>Impostors</color>",
"SheriffMadCanKillNeutral": "Can kill <color=#ffab1b>Neutrals</color>",
@@ -2033,6 +2019,7 @@
"TrapConsecutiveBodies": "Trap Consecutive Bodies",
"HauntedByEvilSpirit": "Haunted by an Evil Spirit",
"AbilityCooldown": "Ability Cooldown",
"AbilityDuration": "Ability Duration",
"MonarchKnightCooldown": "Knight Cooldown",
"MonarchKnightMax": "Maximum Knights",
"MonarchKnightedPlayer": "You successfully knighted a player!",
@@ -2361,6 +2348,7 @@
"TabInfo.Addons": "Settings for Add-ons",
"TabInfo.OtherRoles": "Settings for Ghost roles",
"TabInfo.TaskSettings": "Modded, specific settings that have a major impact on the game",
"TabInfoTip": "<b>Tip:</b> Hold SHIFT to adjust number values by 5 or CTRL to adjust by 10!",
"OtherRoles.CrewmateRoles": "★ Crewmate Roles",
"OtherRoles.NeutralRoles": "★ Neutral Roles",
"OtherRoles.ImpostorRoles": "★ Impostor Roles",
@@ -2568,6 +2556,8 @@
"CanGuessTarget": "Can Guess their Target",
"UsePhantomBasis": "Use Phantom Basis for some roles",
"UsePhantomBasisForNKs": "Even for <#ffab1b>Neutral</color> <#ff1919>Killing</color> (Desynced) roles <#ffff00>(EXPERIMENTAL)</color>",
"UseUnshiftTrigger": "Use Unshift Button as Ability Trigger",
"UseUnshiftTriggerForNKs": "Even for <#ffab1b>Neutral</color> <#ff1919>Killing</color> (Desynced) roles <#ffff00>(EXPERIMENTAL)</color>",
"Mad-": "Mad ",
"Charmed-": "Charmed ",
"Infected-": "Infected ",
@@ -3128,6 +3118,16 @@
"DonutGot-4": "\\nDing-dong! A donut delivery is at your door.\\nCourtesy of the Donut Delivery crewmate.\\nSavor the sweetness!",
"DonutGot-5": "\\nSpecial delivery alert!\\nYou've just received a 'killer' donut from the Donut Delivery crewmate.\\nEnjoy the crime scene... I mean snack!",
"DonutDeliverCD": "Deliver Cooldown",
"DonutDeliverSpeedEffect": "Speed Boost For Players Who Get Donuts",
"DonutDeliverSEDelay": "Speed Boost Delay",
"DonutDeliverSEAmount": "Increase Speed by",
"DonutDeliverSEDuration": "Speed Boost Duration",
"DonutDeliverSEEvilsGetDecreased": "<#ff1919>Evil</color> Players Get Decreased Speed",
"DonutDeliverSEEvilsDecreaseAmount": "Decrease Speed by",
"Rhapsode": "Rhapsode",
"RhapsodeInfo": "Sing to Distract the Killers",
"RhapsodeInfoLong": "(Crewmates):\\nAs the Rhapsode, you can vent/pet your pet to start singing. During this time, no one can vent or shapeshift since they're distracted by your song. (Settings may exclude Crewmates.)",
"Rhapsode.ExcludeCrewmates": "Exclude <#8cffff>Crewmates</color>",
"Chronomancer": "Chronomancer",
"ChronomancerInfo": "Charge up your kill button and go ham!",
"ChronomancerInfoLong": "(Impostors):\\nAs the Chronomancer, when your kill cooldown is up, your kill button starts charging (you'll see the percentage of the charge under your name). When you make a kill, you use the charge. Depending on how much you've charged your kill button up, you'll have a 0 second kill cooldown until the charge runs out. When the charge runs out, your kill cooldown is reset.",
@@ -3625,7 +3625,7 @@
"AdventurerGun.RNG": "RNG",
"Chef": "Chef",
"ChefInfo": "Cook Delicious Meals for Everyone",
"ChefInfoLong": "(Crewmates):\\nAs the Chef, you can cook meals for everyone. If a crewmate gets a meal, they'll get a random boost (speed, vision, shield). If an impostor or a neutral killer gets a meal, it will be rotten and they have to spit it out by venting or killing in a specified amount of time or they'll get blinded and frozen for some time.",
"ChefInfoLong": "(Crewmates):\\nAs the Chef, you can cook meals for everyone by completing tasks. If a crewmate gets a meal, they'll get a random boost (speed, vision, shield). If an impostor or a neutral killer gets a meal, it will be rotten and they have to spit it out by venting or killing in a specified amount of time or they'll get blinded and frozen for some time.",
"Chef.EventTarget": "Effect Applies to",
"Chef.ET.RandomPlayer": "Random Player",
"Chef.ET.NearestPlayer": "Nearest Player",
@@ -4036,6 +4036,22 @@
"AADelay": "Time to Leave Device",
"AAWarning": "<#ffff00>You must move away from this device or you die!</color>",
"AADone": "The process has finished",
"Oxyman": "Oxyman",
"OxymanInfo": "Your Oxygen Level Affects Everything",
"OxymanInfoLong": "(Crewmates):\\nAs the Oxyman, you have an Oxygen level below your name. The Oxygen level decreases overtime. You have to vent to increase your Oxygen. If the Oxygen level reaches 0%, you die. If it's very low, you're blind. If it's low, you're slower. If it's high, you're faster. If it's very high, you're invulnerable.",
"Oxyman.Slow.BelowPercentage": "Slow Below",
"Oxyman.Blind.BelowPercentage": "Blind Below",
"Oxyman.Fast.AbovePercentage": "Fast Above",
"Oxyman.Invulnerable.AbovePercentage": "Invulnerable Above",
"Oxyman.IncrementByVenting": "On Venting, Oxygen Level Increases by",
"Oxyman.DecreasementEachSecond": "Every Second, Oxygen Level Decreases by",
"Beehive": "Beehive",
"BeehiveInfo": "Sting Players",
"BeehiveInfoLong": "(Neutrals):\\nAs the Beehive, you can sting players by single clicking your kill button on them. Stung players will have a certain time to walk a certain distance (get away from your bees) (distance set by the host), or they die.\\nDouble click on someone with your kill button to kill them normally.\\nKill everyone to win.",
"Beehive.Distance": "Distance to Walk",
"Beehive.Time": "Time to Walk the Distance",
"Beehive.StingCooldown": "Sting Cooldown",
"Beehive.Notify": "<#ffff00>You were stung by the Beehive!\\nWalk {0} units away from the Beehive in {1}s or you die!</color>",
"Spurt": "Spurt",
"Prefix.Spurt": "Spurt",
"SpurtInfo": "Boosts Movement",
+8 -1
View File
@@ -155,7 +155,7 @@ namespace EHR.Crewmate
public override void OnGlobalFixedUpdate(PlayerControl pc, bool lowLoad)
{
if (lowLoad) return;
if (lowLoad || !pc.IsAlive() || !GameStates.IsInTask || ExileController.Instance) return;
if (ActiveEvents.TryGetValue(pc.PlayerId, out var events))
events.ToArray().Do(x => x.Update());
@@ -186,6 +186,13 @@ namespace EHR.Crewmate
}
}
public override void OnReportDeadBody()
{
ActiveEvents.Clear();
RottenFood.Keys.Do(x => Utils.GetPlayerById(x).Suicide());
RottenFood.Clear();
}
public static void SpitOutFood(PlayerControl pc)
{
Instances.Do(x => x.RottenFood.Remove(pc.PlayerId));
+18 -3
View File
@@ -1,13 +1,28 @@
using AmongUs.GameOptions;
using System;
using System.Collections.Generic;
using AmongUs.GameOptions;
namespace EHR.Crewmate
{
public class Clairvoyant : RoleBase
{
public static bool On;
public static Dictionary<Options.GameStateInfo, OptionItem> Settings = [];
public override bool IsEnable => On;
public static void SetupCustomOption() => Options.SetupRoleOptions(644970, TabGroup.CrewmateRoles, CustomRoles.Clairvoyant);
public static void SetupCustomOption()
{
Options.SetupRoleOptions(644970, TabGroup.CrewmateRoles, CustomRoles.Clairvoyant);
int i = 2;
foreach (var s in Enum.GetValues<Options.GameStateInfo>())
{
Settings[s] = new BooleanOptionItem(644970 + i, $"GameStateCommand.Show{s}", true, TabGroup.CrewmateRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Clairvoyant]);
i++;
}
}
public override void Init()
{
@@ -26,7 +41,7 @@ namespace EHR.Crewmate
AURoleOptions.EngineerInVentMaxTime = 1f;
}
static void UseAbility(PlayerControl pc) => pc.Notify(Utils.GetRemainingKillers(notify: true));
static void UseAbility(PlayerControl pc) => pc.Notify(Utils.GetGameStateData(clairvoyant: true));
public override void OnPet(PlayerControl pc) => UseAbility(pc);
public override void OnEnterVent(PlayerControl pc, Vent vent) => UseAbility(pc);
}
+59 -4
View File
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using AmongUs.GameOptions;
using static EHR.Options;
using static EHR.Translator;
@@ -8,13 +9,22 @@ namespace EHR.Crewmate
public class DonutDelivery : RoleBase
{
private const int Id = 642700;
private static List<byte> playerIdList = [];
private static List<DonutDelivery> Instances = [];
private static Dictionary<byte, float> StartingSpeed = [];
private static OptionItem CD;
private static OptionItem UseLimit;
private static OptionItem SpeedEffect;
private static OptionItem SEDelay;
private static OptionItem SEAmount;
private static OptionItem SEDuration;
private static OptionItem SEEvilsGetDecreased;
private static OptionItem SEEvilsDecreaseAmount;
public static OptionItem UsePet;
private byte DonutDeliveryId;
private HashSet<byte> Players = [];
public override bool IsEnable => playerIdList.Count > 0;
public override bool IsEnable => Instances.Count > 0;
public static void SetupCustomOption()
{
@@ -25,17 +35,34 @@ namespace EHR.Crewmate
UseLimit = new IntegerOptionItem(Id + 12, "AbilityUseLimit", new(1, 20, 1), 5, TabGroup.CrewmateRoles)
.SetParent(CustomRoleSpawnChances[CustomRoles.DonutDelivery])
.SetValueFormat(OptionFormat.Times);
SpeedEffect = new BooleanOptionItem(Id + 14, "DonutDeliverSpeedEffect", false, TabGroup.CrewmateRoles)
.SetParent(CustomRoleSpawnChances[CustomRoles.DonutDelivery]);
SEDelay = new FloatOptionItem(Id + 15, "DonutDeliverSEDelay", new(0f, 30f, 0.5f), 3f, TabGroup.CrewmateRoles)
.SetParent(SpeedEffect)
.SetValueFormat(OptionFormat.Seconds);
SEAmount = new FloatOptionItem(Id + 16, "DonutDeliverSEAmount", new(0.05f, 3f, 0.05f), 0.5f, TabGroup.CrewmateRoles)
.SetParent(SpeedEffect);
SEDuration = new FloatOptionItem(Id + 17, "DonutDeliverSEDuration", new(0.5f, 60f, 0.5f), 5f, TabGroup.CrewmateRoles)
.SetParent(SpeedEffect)
.SetValueFormat(OptionFormat.Seconds);
SEEvilsGetDecreased = new BooleanOptionItem(Id + 18, "DonutDeliverSEEvilsGetDecreased", true, TabGroup.CrewmateRoles)
.SetParent(SpeedEffect);
SEEvilsDecreaseAmount = new FloatOptionItem(Id + 19, "DonutDeliverSEEvilsDecreaseAmount", new(0.1f, 5f, 0.1f), 1f, TabGroup.CrewmateRoles)
.SetParent(SEEvilsGetDecreased);
UsePet = CreatePetUseSetting(Id + 13, CustomRoles.DonutDelivery);
}
public override void Init()
{
playerIdList = [];
Instances = [];
StartingSpeed = Main.AllPlayerSpeed.ToDictionary(x => x.Key, x => x.Value);
}
public override void Add(byte playerId)
{
playerIdList.Add(playerId);
Instances.Add(this);
Players = [];
DonutDeliveryId = playerId;
playerId.SetAbilityUseLimit(UseLimit.GetInt());
}
@@ -56,9 +83,26 @@ namespace EHR.Crewmate
var num1 = IRandom.Instance.Next(0, 19);
killer.Notify(GetString($"DonutDelivered-{num1}"));
RandomNotifyTarget(target);
Players.Add(target.PlayerId);
killer.SetKillCooldown();
if (SpeedEffect.GetBool())
{
LateTask.New(() =>
{
if (target.IsCrewmate() || target.GetCustomRole().IsNonNK() || !SEEvilsGetDecreased.GetBool()) Main.AllPlayerSpeed[target.PlayerId] += SEAmount.GetFloat();
else Main.AllPlayerSpeed[target.PlayerId] -= SEEvilsDecreaseAmount.GetFloat();
target.MarkDirtySettings();
LateTask.New(() =>
{
Main.AllPlayerSpeed[target.PlayerId] = StartingSpeed[target.PlayerId];
target.MarkDirtySettings();
}, SEDuration.GetFloat(), log: false);
}, SEDelay.GetFloat(), log: false);
}
return false;
}
@@ -67,5 +111,16 @@ namespace EHR.Crewmate
var num2 = IRandom.Instance.Next(0, 6);
target.Notify(GetString($"DonutGot-{num2}"));
}
public static bool IsUnguessable(PlayerControl guesser, PlayerControl target)
{
foreach (DonutDelivery instance in Instances)
{
if (instance.DonutDeliveryId == target.PlayerId && instance.Players.Contains(guesser.PlayerId))
return true;
}
return false;
}
}
}
+1 -1
View File
@@ -42,7 +42,7 @@ public class Marshall : RoleBase
public static bool CanSeeMarshall(PlayerControl seer)
{
var team = seer.GetTeam();
var madmate = seer.GetCustomRole().IsMadmate() || seer.Is(CustomRoles.Madmate);
var madmate = seer.IsMadmate();
return team switch
{
Team.Crewmate when !madmate => true,
+2 -2
View File
@@ -65,7 +65,7 @@ public class Mediumshiper : RoleBase
if (OnlyReceiveMsgFromCrew.GetBool() && !pc.IsCrewmate()) return false;
if (pc.IsAlive()) return false;
msg = msg.ToLower().Trim();
if (!CheckCommond(ref msg, "通灵|ms|mediumship|medium", false)) return false;
if (!CheckCommand(ref msg, "通灵|ms|mediumship|medium", false)) return false;
bool ans;
if (msg.Contains('n') || msg.Contains(GetString("No")) || msg.Contains('错') || msg.Contains("不是")) ans = false;
@@ -84,7 +84,7 @@ public class Mediumshiper : RoleBase
return true;
}
public static bool CheckCommond(ref string msg, string command, bool exact = true)
private static bool CheckCommand(ref string msg, string command, bool exact = true)
{
var comList = command.Split('|');
foreach (string str in comList)
+174
View File
@@ -0,0 +1,174 @@
using System;
using System.Collections.Generic;
using AmongUs.GameOptions;
using EHR.Modules;
using UnityEngine;
namespace EHR.Crewmate
{
public class Oxyman : RoleBase
{
public static bool On;
private static Dictionary<Level, OptionItem> LevelSettings = [];
private static OptionItem IncrementByVenting;
private static OptionItem DecreasementEachSecond;
private static OptionItem IncreasedSpeed;
private static OptionItem DecreasedSpeed;
private long LastUpdate;
private int OxygenLevel;
private byte OxymanId;
private float StartingSpeed;
public override bool IsEnable => On;
public static void SetupCustomOption()
{
int id = 647700;
Options.SetupRoleOptions(id++, TabGroup.CrewmateRoles, CustomRoles.Oxyman);
(List<Level> trueList, List<Level> falseList) = Enum.GetValues<Level>().Without(Level.None).Split(x => x <= Level.Slow);
trueList.ForEach(x => LevelSettings[x] = new IntegerOptionItem(++id, $"Oxyman.{x}.BelowPercentage", new(0, 100, 1), x == Level.Blind ? 10 : 30, TabGroup.CrewmateRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Oxyman])
.SetValueFormat(OptionFormat.Percent));
falseList.ForEach(x => LevelSettings[x] = new IntegerOptionItem(++id, $"Oxyman.{x}.AbovePercentage", new(0, 100, 1), x == Level.Fast ? 60 : 80, TabGroup.CrewmateRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Oxyman])
.SetValueFormat(OptionFormat.Percent));
IncrementByVenting = new IntegerOptionItem(++id, "Oxyman.IncrementByVenting", new(0, 100, 1), 7, TabGroup.CrewmateRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Oxyman])
.SetValueFormat(OptionFormat.Percent);
DecreasementEachSecond = new IntegerOptionItem(++id, "Oxyman.DecreasementEachSecond", new(0, 10, 1), 1, TabGroup.CrewmateRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Oxyman])
.SetValueFormat(OptionFormat.Percent);
IncreasedSpeed = new FloatOptionItem(++id, "IncreasedSpeed", new(0f, 3f, 0.05f), 1.75f, TabGroup.CrewmateRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Oxyman])
.SetValueFormat(OptionFormat.Multiplier);
DecreasedSpeed = new FloatOptionItem(++id, "DecreasedSpeed", new(0f, 3f, 0.05f), 1f, TabGroup.CrewmateRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Oxyman])
.SetValueFormat(OptionFormat.Multiplier);
}
public override void Init()
{
On = false;
}
public override void Add(byte playerId)
{
On = true;
OxymanId = playerId;
OxygenLevel = 59;
LastUpdate = Utils.TimeStamp;
StartingSpeed = Main.AllPlayerSpeed[playerId];
}
public override void ApplyGameOptions(IGameOptions opt, byte playerId)
{
AURoleOptions.EngineerCooldown = 1f;
AURoleOptions.EngineerInVentMaxTime = 1f;
}
public override void OnCoEnterVent(PlayerPhysics physics, int ventId)
{
var pc = physics.myPlayer;
OxygenLevel += IncrementByVenting.GetValue();
Utils.SendRPC(CustomRPC.SyncRoleData, pc.PlayerId, OxygenLevel);
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
}
public override void OnFixedUpdate(PlayerControl pc)
{
if (!pc.IsAlive() || !GameStates.IsInTask || ExileController.Instance) return;
long now = Utils.TimeStamp;
if (now == LastUpdate) return;
LastUpdate = now;
if (OxygenLevel <= 0)
{
pc.Suicide();
return;
}
var previousLevel = GetCurrentLevel();
OxygenLevel -= DecreasementEachSecond.GetInt();
Utils.SendRPC(CustomRPC.SyncRoleData, pc.PlayerId, OxygenLevel);
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
var nowLevel = GetCurrentLevel();
if (nowLevel != previousLevel)
{
switch (nowLevel)
{
case Level.Blind:
Main.PlayerStates[pc.PlayerId].IsBlackOut = true;
Main.AllPlayerSpeed[pc.PlayerId] = DecreasedSpeed.GetFloat();
pc.MarkDirtySettings();
break;
case Level.Slow:
Main.PlayerStates[pc.PlayerId].IsBlackOut = false;
Main.AllPlayerSpeed[pc.PlayerId] = DecreasedSpeed.GetFloat();
pc.MarkDirtySettings();
break;
case Level.None:
Main.PlayerStates[pc.PlayerId].IsBlackOut = false;
Main.AllPlayerSpeed[pc.PlayerId] = StartingSpeed;
pc.MarkDirtySettings();
break;
case Level.Invulnerable:
case Level.Fast:
Main.PlayerStates[pc.PlayerId].IsBlackOut = false;
Main.AllPlayerSpeed[pc.PlayerId] = IncreasedSpeed.GetFloat();
pc.MarkDirtySettings();
break;
}
}
}
public override bool OnCheckMurderAsTarget(PlayerControl killer, PlayerControl target)
{
return GetCurrentLevel() != Level.Invulnerable;
}
Level GetCurrentLevel()
{
// ReSharper disable ConvertIfStatementToReturnStatement
if (OxygenLevel <= LevelSettings[Level.Blind].GetInt()) return Level.Blind;
if (OxygenLevel <= LevelSettings[Level.Slow].GetInt()) return Level.Slow;
if (OxygenLevel >= LevelSettings[Level.Invulnerable].GetInt()) return Level.Invulnerable;
if (OxygenLevel >= LevelSettings[Level.Fast].GetInt()) return Level.Fast;
return Level.None;
// ReSharper restore ConvertIfStatementToReturnStatement
}
Color GetLevelColor() => GetCurrentLevel() switch
{
Level.Blind => Palette.Orange,
Level.Slow => Color.yellow,
Level.Fast => Color.cyan,
Level.Invulnerable => Color.green,
_ => Color.white
};
public void ReceiveRPC(Hazel.MessageReader reader)
{
OxygenLevel = reader.ReadPackedInt32();
}
public override string GetSuffix(PlayerControl seer, PlayerControl target, bool isHUD = false, bool isMeeting = false)
{
if (seer.PlayerId != target.PlayerId || seer.PlayerId != OxymanId || (seer.IsModClient() && !isHUD)) return string.Empty;
return $"<#ff0000>O<sub>2</sub>:</color> {Utils.ColorString(GetLevelColor(), OxygenLevel.ToString())}%";
}
enum Level
{
Blind,
Slow,
None,
Fast,
Invulnerable
}
}
}
+118
View File
@@ -0,0 +1,118 @@
using System.Collections.Generic;
using System.Linq;
using AmongUs.GameOptions;
using EHR.Modules;
namespace EHR.Crewmate
{
public class Rhapsode : RoleBase
{
public static bool On;
private static List<Rhapsode> Instances = [];
public static OptionItem AbilityCooldown;
public static OptionItem AbilityDuration;
private static OptionItem ExcludeCrewmates;
private static OptionItem AbilityUseLimit;
public static OptionItem RhapsodeAbilityUseGainWithEachTaskCompleted;
public static OptionItem AbilityChargesWhenFinishedTasks;
private bool AbilityActive;
private long ActivateTimeStamp;
private long LastUpdate;
private byte RhapsodeId;
public override bool IsEnable => On;
public static void SetupCustomOption()
{
int id = 647650;
Options.SetupRoleOptions(id++, TabGroup.CrewmateRoles, CustomRoles.Rhapsode);
AbilityCooldown = new IntegerOptionItem(++id, "AbilityCooldown", new(0, 60, 1), 30, TabGroup.CrewmateRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Rhapsode])
.SetValueFormat(OptionFormat.Seconds);
AbilityDuration = new IntegerOptionItem(++id, "AbilityDuration", new(0, 60, 1), 10, TabGroup.CrewmateRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Rhapsode])
.SetValueFormat(OptionFormat.Seconds);
ExcludeCrewmates = new BooleanOptionItem(++id, "Rhapsode.ExcludeCrewmates", true, TabGroup.CrewmateRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Rhapsode]);
AbilityUseLimit = new IntegerOptionItem(++id, "AbilityUseLimit", new(0, 20, 1), 1, TabGroup.CrewmateRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Rhapsode])
.SetValueFormat(OptionFormat.Times);
RhapsodeAbilityUseGainWithEachTaskCompleted = new FloatOptionItem(++id, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.05f), 0.3f, TabGroup.CrewmateRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Rhapsode])
.SetValueFormat(OptionFormat.Times);
AbilityChargesWhenFinishedTasks = new FloatOptionItem(++id, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.05f), 0.2f, TabGroup.CrewmateRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Rhapsode])
.SetValueFormat(OptionFormat.Times);
}
public override void Init()
{
On = false;
Instances = [];
}
public override void Add(byte playerId)
{
On = true;
Instances.Add(this);
RhapsodeId = playerId;
AbilityActive = false;
ActivateTimeStamp = 0;
LastUpdate = 0;
playerId.SetAbilityUseLimit(AbilityUseLimit.GetInt());
}
public override void ApplyGameOptions(IGameOptions opt, byte playerId)
{
if (Options.UsePets.GetBool()) return;
AURoleOptions.EngineerCooldown = AbilityCooldown.GetInt();
AURoleOptions.EngineerInVentMaxTime = 1f;
}
public override void OnCoEnterVent(PlayerPhysics physics, int ventId) => ActivateAbility(physics.myPlayer);
public override void OnPet(PlayerControl pc) => ActivateAbility(pc);
private void ActivateAbility(PlayerControl pc)
{
AbilityActive = true;
ActivateTimeStamp = Utils.TimeStamp;
Utils.SendRPC(CustomRPC.SyncRoleData, pc.PlayerId, AbilityActive);
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
}
public override void OnFixedUpdate(PlayerControl pc)
{
long now = Utils.TimeStamp;
if (now == LastUpdate) return;
LastUpdate = now;
if (AbilityActive && Utils.TimeStamp - ActivateTimeStamp >= AbilityDuration.GetInt())
{
AbilityActive = false;
Utils.SendRPC(CustomRPC.SyncRoleData, pc.PlayerId, AbilityActive);
}
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
}
public static bool CheckAbilityUse(PlayerControl pc)
{
if (pc.IsCrewmate() && ExcludeCrewmates.GetBool()) return true;
return !Instances.Any(x => x.AbilityActive);
}
public void ReceiveRPC(Hazel.MessageReader reader)
{
AbilityActive = reader.ReadBoolean();
if (AbilityActive) ActivateTimeStamp = Utils.TimeStamp;
}
public override string GetSuffix(PlayerControl seer, PlayerControl target, bool isHUD = false, bool isMeeting = false)
{
if (seer.PlayerId != target.PlayerId || seer.PlayerId != RhapsodeId || isHUD || isMeeting || !AbilityActive) return string.Empty;
return $"\u25b6 ({AbilityDuration.GetInt() - (Utils.TimeStamp - ActivateTimeStamp)}s)";
}
}
}
+2
View File
@@ -27,6 +27,7 @@ public class Sheriff : RoleBase
public static OptionItem NonCrewCanKillCrew;
public static OptionItem NonCrewCanKillImp;
public static OptionItem NonCrewCanKillNeutral;
public static OptionItem KeepsGameGoing;
public static OptionItem UsePet;
public static Dictionary<CustomRoles, OptionItem> KillTargetOptions = [];
@@ -62,6 +63,7 @@ public class Sheriff : RoleBase
NonCrewCanKillImp = new BooleanOptionItem(Id + 19, "SheriffMadCanKillImp", true, TabGroup.CrewmateRoles).SetParent(SetNonCrewCanKill);
NonCrewCanKillCrew = new BooleanOptionItem(Id + 21, "SheriffMadCanKillCrew", true, TabGroup.CrewmateRoles).SetParent(SetNonCrewCanKill);
NonCrewCanKillNeutral = new BooleanOptionItem(Id + 20, "SheriffMadCanKillNeutral", true, TabGroup.CrewmateRoles).SetParent(SetNonCrewCanKill);
KeepsGameGoing = new BooleanOptionItem(Id + 26, "SheriffKeepsGameGoing", false, TabGroup.CrewmateRoles).SetParent(Options.CustomRoleSpawnChances[CustomRoles.Sheriff]);
UsePet = Options.CreatePetUseSetting(Id + 29, CustomRoles.Sheriff);
}
+1
View File
@@ -62,6 +62,7 @@ namespace EHR.Impostor
public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting)
{
if (!shapeshifting && !Options.UseUnshiftTrigger.GetBool()) return true;
CreateBlackHole(shapeshifter);
return false;
}
+8 -14
View File
@@ -129,10 +129,7 @@ internal class Assassin : RoleBase
public override bool OnShapeshift(PlayerControl pc, PlayerControl t, bool shapeshifting)
{
if (!pc.IsAlive() || Pelican.IsEaten(pc.PlayerId)) return false;
if (!shapeshifting)
{
return true;
}
if (!shapeshifting && !UseUnshiftTrigger.GetBool()) return true;
Take(pc);
@@ -154,17 +151,14 @@ internal class Assassin : RoleBase
if (IsUndertaker) target.TP(pc);
else pc.TP(target);
LateTask.New(() =>
if (!(target == null || !target.IsAlive() || Pelican.IsEaten(target.PlayerId) || target.inVent || !GameStates.IsInTask) && pc.RpcCheckAndMurder(target))
{
if (!(target == null || !target.IsAlive() || Pelican.IsEaten(target.PlayerId) || target.inVent || !GameStates.IsInTask) && pc.RpcCheckAndMurder(target))
{
MarkedPlayer = byte.MaxValue;
SendRPC(pc.PlayerId);
pc.ResetKillCooldown();
pc.SyncSettings();
pc.SetKillCooldown(DefaultKillCooldown);
}
}, UsePets.GetBool() ? 0.1f : 1.2f, "Assassin Assassinate");
MarkedPlayer = byte.MaxValue;
SendRPC(pc.PlayerId);
pc.ResetKillCooldown();
pc.SyncSettings();
pc.SetKillCooldown(DefaultKillCooldown);
}
}
}
+1 -1
View File
@@ -94,7 +94,7 @@ namespace EHR.Impostor
public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting)
{
if (!shapeshifting) return true;
if (!shapeshifting && !UseUnshiftTrigger.GetBool()) return true;
Bomb(shapeshifter);
return false;
+8 -2
View File
@@ -57,12 +57,18 @@ namespace EHR.Impostor
public override bool OnShapeshift(PlayerControl pc, PlayerControl target, bool shapeshifting)
{
if (shapeshifting && pc.GetAbilityUseLimit() < 1)
if (!shapeshifting && !Options.UseUnshiftTrigger.GetBool())
{
Camouflage.CheckCamouflage();
return true;
}
if (pc.GetAbilityUseLimit() < 1)
{
pc.SetKillCooldown(CamouflageDuration.GetFloat() + 1f);
}
if (shapeshifting) pc.RpcRemoveAbilityUse();
pc.RpcRemoveAbilityUse();
IsActive = true;
Camouflage.CheckCamouflage();
+1 -1
View File
@@ -56,7 +56,7 @@ public class Disperser : RoleBase
public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting)
{
if (shapeshifter == null || !shapeshifting) return false;
if (shapeshifter == null || (!shapeshifting && !UseUnshiftTrigger.GetBool())) return false;
if (shapeshifter.GetAbilityUseLimit() < 1)
{
shapeshifter.SetKillCooldown(DisperserShapeshiftDuration.GetFloat() + 1f);
+1 -1
View File
@@ -75,7 +75,7 @@ namespace EHR.Impostor
public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting)
{
if (shapeshifting)
if (shapeshifting || Options.UseUnshiftTrigger.GetBool())
{
TeleportOrMark(shapeshifter);
}
+2 -2
View File
@@ -129,7 +129,7 @@ namespace EHR.Impostor
ChangeSilencingMode(pc);
return !shapeshifting || ShowSSAnimation.GetBool();
return (!shapeshifting && !UseUnshiftTrigger.GetBool()) || ShowSSAnimation.GetBool();
}
public override bool OnVanish(PlayerControl pc)
@@ -151,7 +151,7 @@ namespace EHR.Impostor
public override void OnFixedUpdate(PlayerControl pc)
{
if (!IsEnable) return;
if (ShowSSAnimation.GetBool() && !UsePhantomBasis.GetBool()) return;
if (ShowSSAnimation.GetBool() && !UsePhantomBasis.GetBool() && !UseUnshiftTrigger.GetBool()) return;
if (IsInSilencingMode.SILENCING && IsInSilencingMode.LAST_CHANGE + SSDur.GetInt() < TimeStamp)
{
+1 -1
View File
@@ -50,7 +50,7 @@ namespace EHR.Impostor
public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting)
{
if (!shapeshifting) return true;
if (!shapeshifting && !Options.UseUnshiftTrigger.GetBool()) return true;
TeleportToVent(shapeshifter);
return false;
+1 -1
View File
@@ -72,7 +72,7 @@ internal class QuickShooter : RoleBase
public override bool OnShapeshift(PlayerControl pc, PlayerControl target, bool shapeshifting)
{
if (Main.KillTimers[pc.PlayerId] <= 0 && shapeshifting)
if (Main.KillTimers[pc.PlayerId] <= 0 && (shapeshifting || Options.UseUnshiftTrigger.GetBool()))
{
Store(pc);
}
+1 -1
View File
@@ -123,7 +123,7 @@ namespace EHR.Impostor
public override bool OnShapeshift(PlayerControl player, PlayerControl target, bool shapeshifting)
{
if (player == null) return false;
if (!shapeshifting) return true;
if (!shapeshifting && !UseUnshiftTrigger.GetBool()) return true;
if (Marks.Count >= 2) return false;
Mark(player);
+1
View File
@@ -62,6 +62,7 @@ namespace EHR.Impostor
public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting)
{
if (!shapeshifting && !UseUnshiftTrigger.GetBool()) return true;
return PlaceBomb(shapeshifter);
}
+1 -1
View File
@@ -171,7 +171,7 @@ public class Sniper : RoleBase
public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting)
{
return Snipe(shapeshifter, shapeshifting);
return Options.UseUnshiftTrigger.GetBool() ? Snipe(shapeshifter, !IsAim) : Snipe(shapeshifter, shapeshifting);
}
public override void OnPet(PlayerControl pc)
+9
View File
@@ -43,6 +43,8 @@ namespace EHR.Impostor
{
if (Options.UsePhantomBasis.GetBool())
AURoleOptions.PhantomCooldown = DashCD.GetFloat();
if (Options.UseUnshiftTrigger.GetBool())
AURoleOptions.ShapeshifterCooldown = DashCD.GetFloat();
}
public override void OnPet(PlayerControl pc)
@@ -56,6 +58,13 @@ namespace EHR.Impostor
return false;
}
public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting)
{
if (!shapeshifting && !Options.UseUnshiftTrigger.GetBool()) return true;
Dash(shapeshifter);
return false;
}
private static void Dash(PlayerControl pc)
{
if (pc == null || DashStart.ContainsKey(pc.PlayerId)) return;
+1 -1
View File
@@ -168,7 +168,7 @@ namespace EHR.Impostor
public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting)
{
if (!shapeshifting) return true;
if (!shapeshifting && !UseUnshiftTrigger.GetBool()) return true;
Curse(shapeshifter);
+31 -4
View File
@@ -10,7 +10,7 @@ namespace EHR.Neutral;
public class Amnesiac : RoleBase
{
private const int Id = 35000;
private static List<byte> playerIdList = [];
private static List<Amnesiac> Instances = [];
public static OptionItem RememberCooldown;
public static OptionItem IncompatibleNeutralMode;
@@ -31,7 +31,9 @@ public class Amnesiac : RoleBase
"AmnesiacRM.ByReportingBody"
];
public override bool IsEnable => playerIdList.Count > 0;
private byte AmnesiacId;
public override bool IsEnable => Instances.Count > 0;
public static void SetupCustomOption()
{
@@ -49,12 +51,13 @@ public class Amnesiac : RoleBase
public override void Init()
{
playerIdList = [];
Instances = [];
}
public override void Add(byte playerId)
{
playerIdList.Add(playerId);
Instances.Add(this);
AmnesiacId = playerId;
}
public override void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = RememberCooldown.GetFloat();
@@ -62,6 +65,19 @@ public class Amnesiac : RoleBase
public override bool CanUseImpostorVentButton(PlayerControl pc) => CanVent.GetBool();
public override void ApplyGameOptions(IGameOptions opt, byte playerId) => opt.SetVision(false);
public static void OnAnyoneDeath(PlayerControl target)
{
if (RememberMode.GetValue() == 1)
{
foreach (Amnesiac instance in Instances)
{
LocateArrow.Add(instance.AmnesiacId, target.Pos());
var amne = Utils.GetPlayerById(instance.AmnesiacId);
Utils.NotifyRoles(SpecifySeer: amne, SpecifyTarget: amne);
}
}
}
public override bool OnCheckMurder(PlayerControl killer, PlayerControl target)
{
if (RememberMode.GetValue() == 0)
@@ -173,6 +189,11 @@ public class Amnesiac : RoleBase
target.RpcGuardAndKill(target);
}
public override void OnReportDeadBody()
{
LocateArrow.RemoveAllTarget(AmnesiacId);
}
public override bool KnowRole(PlayerControl player, PlayerControl target)
{
if (player.Is(CustomRoles.Refugee) && target.Is(CustomRoleTypes.Impostor)) return true;
@@ -184,4 +205,10 @@ public class Amnesiac : RoleBase
ActionButton amneButton = RememberMode.GetValue() == 0 ? hud.KillButton : hud.ReportButton;
amneButton?.OverrideText(GetString("RememberButtonText"));
}
public override string GetSuffix(PlayerControl seer, PlayerControl target, bool isHUD = false, bool isMeeting = false)
{
if (seer.PlayerId != target.PlayerId || seer.PlayerId != AmnesiacId || isMeeting || isHUD) return string.Empty;
return LocateArrow.GetArrows(seer);
}
}
+9
View File
@@ -217,6 +217,8 @@ namespace EHR.Neutral
opt.SetVision(HasImpostorVision.GetBool());
if (UsePhantomBasis.GetBool() && UsePhantomBasisForNKs.GetBool())
AURoleOptions.PhantomCooldown = 1f;
if (UseUnshiftTrigger.GetBool() && UseUnshiftTriggerForNKs.GetBool())
AURoleOptions.ShapeshifterCooldown = 1f;
}
void Update() => BargainerId.SetAbilityUseLimit(Money);
@@ -265,6 +267,13 @@ namespace EHR.Neutral
return false;
}
public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting)
{
if (!shapeshifting && !UseUnshiftTrigger.GetBool()) return true;
CycleItem(shapeshifter);
return false;
}
public override void AfterMeetingTasks()
{
if (Gains.TryGetValue(MoneyGainingAction.SurviveMeeting, out var gain))
+119
View File
@@ -0,0 +1,119 @@
using System;
using System.Collections.Generic;
using AmongUs.GameOptions;
using EHR.Modules;
using UnityEngine;
namespace EHR.Neutral
{
public class Beehive : RoleBase
{
public static bool On;
private static OptionItem Distance;
private static OptionItem Time;
private static OptionItem StingCooldown;
private static OptionItem KillCooldown;
private static OptionItem CanVent;
private static OptionItem HasImpostorVision;
private byte BeehiveId;
public Dictionary<byte, (long TimeStamp, Vector2 InitialPosition)> StungPlayers = [];
public override bool IsEnable => On;
public static void SetupCustomOption()
{
int id = 647350;
Options.SetupRoleOptions(id++, TabGroup.NeutralRoles, CustomRoles.Beehive);
Distance = new FloatOptionItem(++id, "Beehive.Distance", new(0f, 20f, 0.5f), 15f, TabGroup.NeutralRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Beehive]);
Time = new FloatOptionItem(++id, "Beehive.Time", new(0f, 30f, 0.5f), 10f, TabGroup.NeutralRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Beehive])
.SetValueFormat(OptionFormat.Seconds);
StingCooldown = new FloatOptionItem(++id, "Beehive.StingCooldown", new(0f, 180f, 0.5f), 5f, TabGroup.NeutralRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Beehive])
.SetValueFormat(OptionFormat.Seconds);
KillCooldown = new FloatOptionItem(++id, "KillCooldown", new(0f, 180f, 0.5f), 22.5f, TabGroup.NeutralRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Beehive])
.SetValueFormat(OptionFormat.Seconds);
CanVent = new BooleanOptionItem(++id, "CanVent", true, TabGroup.NeutralRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Beehive]);
HasImpostorVision = new BooleanOptionItem(++id, "ImpostorVision", true, TabGroup.NeutralRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Beehive]);
}
public override void Init()
{
On = false;
}
public override void Add(byte playerId)
{
On = true;
BeehiveId = playerId;
StungPlayers = [];
}
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 OnCheckMurder(PlayerControl killer, PlayerControl target)
{
if (!base.OnCheckMurder(killer, target)) return false;
return killer.CheckDoubleTrigger(target, () =>
{
Vector2 pos = target.Pos();
StungPlayers[target.PlayerId] = (Utils.TimeStamp, pos);
killer.SetKillCooldown(time: StingCooldown.GetFloat());
Utils.NotifyRoles(SpecifySeer: killer, SpecifyTarget: target);
Utils.SendRPC(CustomRPC.SyncRoleData, BeehiveId, 1, target.PlayerId, pos);
target.Notify(string.Format(Translator.GetString("Beehive.Notify"), Math.Round(Distance.GetFloat(), 1), Math.Round(Time.GetFloat(), 1)), 8f);
});
}
public override void OnGlobalFixedUpdate(PlayerControl pc, bool lowLoad)
{
if (lowLoad || !pc.IsAlive() || !GameStates.IsInTask || ExileController.Instance) return;
if (StungPlayers.TryGetValue(pc.PlayerId, out var sp))
{
if (Utils.TimeStamp - sp.TimeStamp >= Time.GetFloat())
{
StungPlayers.Remove(pc.PlayerId);
Utils.SendRPC(CustomRPC.SyncRoleData, BeehiveId, 2, pc.PlayerId);
if (Vector2.Distance(pc.Pos(), sp.InitialPosition) < Distance.GetFloat())
pc.Suicide(realKiller: Utils.GetPlayerById(BeehiveId));
}
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
}
}
public void ReceiveRPC(Hazel.MessageReader reader)
{
switch (reader.ReadPackedInt32())
{
case 1:
StungPlayers[reader.ReadByte()] = (Utils.TimeStamp, reader.ReadVector2());
break;
case 2:
StungPlayers.Remove(reader.ReadByte());
break;
}
}
public override string GetSuffix(PlayerControl seer, PlayerControl target, bool isHUD = false, bool isMeeting = false)
{
if (seer.PlayerId != target.PlayerId || isMeeting || isHUD || !StungPlayers.TryGetValue(seer.PlayerId, out var sp)) return string.Empty;
var walked = Math.Round(Vector2.Distance(seer.Pos(), sp.InitialPosition), 1);
var distance = Math.Round(Distance.GetFloat(), 1);
var time = Time.GetInt() - (Utils.TimeStamp - sp.TimeStamp);
var color = walked >= distance ? "<#00ffa5>" : "<#ffa500>";
var color2 = walked >= distance ? "<#00ffff>" : "<#ffff00>";
return $"{color}{walked}</color>{color2}/{distance}</color> <#ffffff>({time}s)</color>";
}
}
}
+12
View File
@@ -213,6 +213,8 @@ namespace EHR.Neutral
opt.SetVision(HasImpostorVision.GetBool());
if (UsePhantomBasis.GetBool() && UsePhantomBasisForNKs.GetBool())
AURoleOptions.PhantomCooldown = 1f;
if (UseUnshiftTrigger.GetBool() && UseUnshiftTriggerForNKs.GetBool())
AURoleOptions.ShapeshifterCooldown = 1f;
}
static ItemType GetItemType(Item item) => item switch
@@ -486,6 +488,16 @@ namespace EHR.Neutral
return false;
}
public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting)
{
if (!shapeshifting && !UseUnshiftTrigger.GetBool()) return true;
if (SortedAvailableProcesses.Count == 0) return false;
Cycle(shapeshifter);
return false;
}
private void Cycle(PlayerControl pc)
{
var index = SortedAvailableProcesses.IndexOf(SelectedProcess);
+9
View File
@@ -54,6 +54,8 @@ namespace EHR.Neutral
opt.SetVision(true);
if (UsePhantomBasis.GetBool() && UsePhantomBasisForNKs.GetBool())
AURoleOptions.PhantomCooldown = Time.GetInt() + 2f;
if (UsePhantomBasis.GetBool() && UsePhantomBasisForNKs.GetBool())
AURoleOptions.ShapeshifterCooldown = Time.GetInt() + 2f;
}
@@ -74,6 +76,13 @@ namespace EHR.Neutral
return false;
}
public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting)
{
if (!shapeshifting && !UseUnshiftTrigger.GetBool()) return true;
MarkPosition();
return false;
}
void MarkPosition()
{
if (!IsEnable || Enderman_.HasAbilityCD()) return;
+9
View File
@@ -55,6 +55,8 @@ namespace EHR.Neutral
opt.SetVision(HasImpostorVision.GetBool());
if (UsePhantomBasis.GetBool() && UsePhantomBasisForNKs.GetBool())
AURoleOptions.PhantomCooldown = 1f;
if (UsePhantomBasis.GetBool() && UsePhantomBasisForNKs.GetBool())
AURoleOptions.ShapeshifterCooldown = 1f;
}
void SendRPC()
@@ -92,6 +94,13 @@ namespace EHR.Neutral
return false;
}
public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting)
{
if (!shapeshifting && !UseUnshiftTrigger.GetBool()) return true;
ExecuteAction();
return false;
}
void ExecuteAction()
{
if (MarkedPlayerId == byte.MaxValue) return;
+3 -15
View File
@@ -22,19 +22,6 @@ public class Lawyer : RoleBase
public static Dictionary<byte, byte> Target = [];
public static readonly string[] ChangeRoles =
[
"Role.Crewmate",
"Role.Jester",
"Role.Opportunist",
"Role.Convict",
"Role.Celebrity",
"Role.Bodyguard",
"Role.Dictator",
"Role.Mayor",
"Role.Doctor"
];
public static readonly CustomRoles[] CRoleChangeRoles =
[
CustomRoles.CrewmateEHR,
@@ -45,7 +32,8 @@ public class Lawyer : RoleBase
CustomRoles.Bodyguard,
CustomRoles.Dictator,
CustomRoles.Mayor,
CustomRoles.Doctor
CustomRoles.Doctor,
CustomRoles.Amnesiac
];
public override bool IsEnable => playerIdList.Count > 0;
@@ -59,7 +47,7 @@ public class Lawyer : RoleBase
CanTargetJester = new BooleanOptionItem(Id + 13, "LawyerCanTargetJester", false, TabGroup.NeutralRoles).SetParent(CustomRoleSpawnChances[CustomRoles.Lawyer]);
KnowTargetRole = new BooleanOptionItem(Id + 14, "KnowTargetRole", true, TabGroup.NeutralRoles).SetParent(CustomRoleSpawnChances[CustomRoles.Lawyer]);
TargetKnowsLawyer = new BooleanOptionItem(Id + 15, "TargetKnowsLawyer", true, TabGroup.NeutralRoles).SetParent(CustomRoleSpawnChances[CustomRoles.Lawyer]);
ChangeRolesAfterTargetKilled = new StringOptionItem(Id + 16, "LawyerChangeRolesAfterTargetKilled", ChangeRoles, 2, TabGroup.NeutralRoles).SetParent(CustomRoleSpawnChances[CustomRoles.Lawyer]);
ChangeRolesAfterTargetKilled = new StringOptionItem(Id + 16, "LawyerChangeRolesAfterTargetKilled", CRoleChangeRoles.Select(x => x.ToColoredString()).ToArray(), 2, TabGroup.NeutralRoles, noTranslation: true).SetParent(CustomRoleSpawnChances[CustomRoles.Lawyer]);
}
public override void Init()
+11 -1
View File
@@ -110,6 +110,8 @@ public class Magician : RoleBase
opt.SetVision(HasImpostorVision.GetBool());
if (UsePhantomBasis.GetBool() && UsePhantomBasisForNKs.GetBool())
AURoleOptions.PhantomCooldown = 1f;
if (UsePhantomBasis.GetBool() && UsePhantomBasisForNKs.GetBool())
AURoleOptions.ShapeshifterCooldown = 1f;
}
public override void OnMurder(PlayerControl killer, PlayerControl target)
@@ -123,7 +125,7 @@ public class Magician : RoleBase
sb.Append("\n\n");
sb.AppendLine(ColorString(GetRoleColor(CustomRoles.Magician), $"Card name: <color=#ffffff>{GetString($"Magician-GetIdToName-{CardId}")}</color>"));
sb.AppendLine(ColorString(GetRoleColor(CustomRoles.Magician), $"Description: <color=#ffffff>{GetString($"Magician-GetIdToDesc-{CardId}")}</color>"));
sb.AppendLine(ColorString(GetRoleColor(CustomRoles.Magician), $"Trigger by: <color=#ffffff>{(UsePets.GetBool() ? "Pet button" : UsePhantomBasis.GetBool() && UsePhantomBasisForNKs.GetBool() ? "Vanish button" : "Sabotage")}</color>"));
sb.AppendLine(ColorString(GetRoleColor(CustomRoles.Magician), $"Trigger by: <color=#ffffff>{(UsePets.GetBool() ? "Pet button" : UsePhantomBasis.GetBool() && UsePhantomBasisForNKs.GetBool() ? "Vanish button" : UseUnshiftTrigger.GetBool() && UseUnshiftTriggerForNKs.GetBool() ? "Shapeshift button" : "Sabotage")}</color>"));
killer.Notify(sb.ToString(), 15f);
}
@@ -145,6 +147,14 @@ public class Magician : RoleBase
return false;
}
public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting)
{
if (shapeshifter == null) return false;
if (!shapeshifting && !UseUnshiftTrigger.GetBool()) return false;
UseCard(shapeshifter);
return false;
}
public static void UseCard(PlayerControl pc)
{
if (pc == null) return;
+15 -1
View File
@@ -16,7 +16,8 @@ namespace EHR.Neutral
"VentButtonText", // 0
"SabotageButtonText", // 1
"PetButtonText", // 2
"AbilityButtonText.Phantom" // 3
"AbilityButtonText.Phantom", // 3
"AbilityButtonText.Shapeshifter" // 4
];
private static OptionItem KillCooldown;
@@ -74,6 +75,8 @@ namespace EHR.Neutral
opt.SetVision(HasImpostorVision.GetBool());
if (UsePhantomBasis.GetBool() && UsePhantomBasisForNKs.GetBool())
AURoleOptions.PhantomCooldown = CD.GetInt();
if (UsePhantomBasis.GetBool() && UsePhantomBasisForNKs.GetBool())
AURoleOptions.ShapeshifterCooldown = CD.GetInt();
}
void SendRPC()
@@ -136,6 +139,17 @@ namespace EHR.Neutral
return false;
}
public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting)
{
if (!shapeshifting && !UseUnshiftTrigger.GetBool()) return true;
if (SpreadAction.GetValue() == 4)
{
SpreadSpores();
}
return false;
}
void SpreadSpores()
{
if (!IsEnable || Mycologist_.HasAbilityCD()) return;
+9
View File
@@ -63,6 +63,8 @@ namespace EHR.Neutral
{
if (Options.UsePhantomBasis.GetBool() && Options.UsePhantomBasisForNKs.GetBool())
AURoleOptions.PhantomCooldown = 1f;
if (Options.UsePhantomBasis.GetBool() && Options.UsePhantomBasisForNKs.GetBool())
AURoleOptions.ShapeshifterCooldown = 1f;
var room = Utils.GetPlayerById(id)?.GetPlainShipRoom();
if (room == null) return;
opt.SetVision(room == RoomBoosts[Boost.Vision]);
@@ -123,6 +125,13 @@ namespace EHR.Neutral
return false;
}
public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting)
{
if (!shapeshifting && !Options.UseUnshiftTrigger.GetBool()) return true;
OnPet(shapeshifter);
return false;
}
enum Boost
{
Speed,
+9
View File
@@ -62,6 +62,8 @@ namespace EHR.Neutral
opt.SetVision(HasImpostorVision.GetBool());
if (Options.UsePhantomBasis.GetBool() && Options.UsePhantomBasisForNKs.GetBool())
AURoleOptions.PhantomCooldown = 1f;
if (Options.UsePhantomBasis.GetBool() && Options.UsePhantomBasisForNKs.GetBool())
AURoleOptions.ShapeshifterCooldown = 1f;
}
public override void OnExitVent(PlayerControl pc, Vent vent)
@@ -88,6 +90,13 @@ namespace EHR.Neutral
return false;
}
public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting)
{
if (!shapeshifting && !Options.UseUnshiftTrigger.GetBool()) return true;
Roll(shapeshifter);
return false;
}
void Roll(PlayerControl pc)
{
long now = Utils.TimeStamp;
+9
View File
@@ -67,6 +67,8 @@ namespace EHR.Neutral
opt.SetVision(HasImpostorVision.GetBool());
if (UsePhantomBasis.GetBool() && UsePhantomBasisForNKs.GetBool())
AURoleOptions.PhantomCooldown = 1f;
if (UsePhantomBasis.GetBool() && UsePhantomBasisForNKs.GetBool())
AURoleOptions.ShapeshifterCooldown = 1f;
}
public override bool OnCheckMurder(PlayerControl killer, PlayerControl target)
@@ -131,6 +133,13 @@ namespace EHR.Neutral
return false;
}
public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting)
{
if (!shapeshifting && !UseUnshiftTrigger.GetBool()) return true;
OnPet(shapeshifter);
return false;
}
public override void OnReportDeadBody()
{
if (Executed)
+9
View File
@@ -88,6 +88,8 @@ namespace EHR.Neutral
opt.SetVision(HasImpostorVision.GetBool());
if (UsePhantomBasis.GetBool() && UsePhantomBasisForNKs.GetBool())
AURoleOptions.PhantomCooldown = CD.GetInt();
if (UsePhantomBasis.GetBool() && UsePhantomBasisForNKs.GetBool())
AURoleOptions.ShapeshifterCooldown = CD.GetInt();
}
public override bool OnSabotage(PlayerControl pc)
@@ -107,6 +109,13 @@ namespace EHR.Neutral
return false;
}
public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting)
{
if (!shapeshifting && !UseUnshiftTrigger.GetBool()) return true;
PlaceTrap();
return false;
}
void PlaceTrap()
{
if (!IsEnable || SprayerId.GetAbilityUseLimit() <= 0 || Sprayer_.HasAbilityCD()) return;
+13
View File
@@ -95,6 +95,19 @@ namespace EHR.Neutral
return false;
}
public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting)
{
if (!shapeshifting && !Options.UseUnshiftTrigger.GetBool()) return true;
if (CooldownTimer <= 0f)
{
StartEnraging();
CooldownTimer = EnrageCooldown.GetFloat() + EnrageDuration.GetFloat();
}
return false;
}
void StartEnraging()
{
EnrageTimer = EnrageDuration.GetFloat();
+9
View File
@@ -92,6 +92,8 @@ public class WeaponMaster : RoleBase
opt.SetVision(HasImpostorVision.GetBool());
if (UsePhantomBasis.GetBool() && UsePhantomBasisForNKs.GetBool())
AURoleOptions.PhantomCooldown = 1f;
if (UsePhantomBasis.GetBool() && UsePhantomBasisForNKs.GetBool())
AURoleOptions.ShapeshifterCooldown = 1f;
}
public override bool CanUseKillButton(PlayerControl pc) => Mode != 3;
@@ -113,6 +115,13 @@ public class WeaponMaster : RoleBase
return false;
}
public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting)
{
if (!shapeshifting && !UseUnshiftTrigger.GetBool()) return true;
SwitchMode();
return false;
}
void SwitchMode()
{
var id = playerIdList[0];
+9
View File
@@ -71,6 +71,8 @@ public class Werewolf : RoleBase
opt.SetVision(HasImpostorVision.GetBool());
if (UsePhantomBasis.GetBool() && UsePhantomBasisForNKs.GetBool())
AURoleOptions.PhantomCooldown = 1f;
if (UsePhantomBasis.GetBool() && UsePhantomBasisForNKs.GetBool())
AURoleOptions.ShapeshifterCooldown = 1f;
}
void SendRPC()
@@ -160,6 +162,13 @@ public class Werewolf : RoleBase
return false;
}
public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting)
{
if (!shapeshifting && !UseUnshiftTrigger.GetBool()) return true;
Rampage(shapeshifter);
return false;
}
private void Rampage(PlayerControl pc)
{
if (!AmongUsClient.Instance.AmHost || IsRampaging) return;
+4
View File
@@ -355,6 +355,8 @@ public class Main : BasePlugin
{ CustomRoles.Convener, "#34eb7a" },
{ CustomRoles.Mathematician, "#eb3474" },
{ CustomRoles.Transmitter, "#c9a11e" },
{ CustomRoles.Oxyman, "#ffa58c" },
{ CustomRoles.Rhapsode, "#f5ad42" },
{ CustomRoles.Chef, "#d6d6ff" },
{ CustomRoles.Lyncher, "#14ba7d" },
{ CustomRoles.Socialite, "#32a8a8" },
@@ -461,6 +463,7 @@ public class Main : BasePlugin
{ CustomRoles.HexMaster, "#ff00ff" },
{ CustomRoles.Wraith, "#4B0082" },
{ CustomRoles.NSerialKiller, "#233fcc" },
{ CustomRoles.Beehive, "#ffff00" },
{ CustomRoles.RouleteGrandeur, "#a88332" },
{ CustomRoles.Nonplus, "#09632f" },
{ CustomRoles.Tremor, "#e942f5" },
@@ -771,6 +774,7 @@ public enum CustomWinner
Necromancer = CustomRoles.Necromancer,
Wraith = CustomRoles.Wraith,
SerialKiller = CustomRoles.NSerialKiller,
Beehive = CustomRoles.Beehive,
RouleteGrandeur = CustomRoles.RouleteGrandeur,
Nonplus = CustomRoles.Nonplus,
Tremor = CustomRoles.Tremor,