mirror of
https://github.com/Gurge44/EndlessHostRoles.git
synced 2026-10-19 15:51:58 +00:00
Unshift button trigger (it's amazing), Add Beehive, Add Oxyman, Add Rhapsode, Bug Fixes
This commit is contained in:
1 parent
cf44d2b106
commit
1e9079d5bc
56 files changed
+927
-118
No files matched your search
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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++;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>");
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
@@ -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",
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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))
|
||||
|
||||
@@ -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>";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in new issue
Block a user