diff --git a/Modules/CustomRoleSelector.cs b/Modules/CustomRoleSelector.cs index 1fb57270e..97850c09e 100644 --- a/Modules/CustomRoleSelector.cs +++ b/Modules/CustomRoleSelector.cs @@ -104,6 +104,7 @@ internal static class CustomRoleSelector case CustomRoles.Changeling when Changeling.GetAvailableRoles(true).Count == 0: case CustomRoles.Camouflager when Camouflager.DoesntSpawnOnFungle.GetBool() && Main.CurrentMap == MapNames.Fungle: case CustomRoles.DarkHide when Main.CurrentMap == MapNames.Fungle: + case CustomRoles.Doormaster when Main.CurrentMap == MapNames.Mira: case CustomRoles.Pelican when Roles[RoleAssignType.Impostor].Any(x => x.Role == CustomRoles.Duellist): case CustomRoles.Duellist when Roles[RoleAssignType.NeutralKilling].Any(x => x.Role == CustomRoles.Pelican): case CustomRoles.VengefulRomantic: diff --git a/Patches/ChatCommandPatch.cs b/Patches/ChatCommandPatch.cs index 7163ddfb9..292eb7434 100644 --- a/Patches/ChatCommandPatch.cs +++ b/Patches/ChatCommandPatch.cs @@ -661,14 +661,16 @@ internal static class ChatCommands IEnumerable impRoles = allRoles.Where(x => x.IsImpostor()).Shuffle().Take(Options.FactionMinMaxSettings[Team.Impostor].MaxSetting.GetInt()); IEnumerable nkRoles = allRoles.Where(x => x.IsNK()).Shuffle().Take(Options.RoleSubCategoryLimits[RoleOptionType.Neutral_Killing][2].GetInt()); IEnumerable nnkRoles = allRoles.Where(x => x.IsNonNK()).Shuffle().Take(Options.RoleSubCategoryLimits[RoleOptionType.Neutral_Evil][2].GetInt() + Options.RoleSubCategoryLimits[RoleOptionType.Neutral_Benign][2].GetInt()); + IEnumerable covenRoles = allRoles.Where(x => x.IsCoven()).Shuffle().Take(Options.FactionMinMaxSettings[Team.Coven].MaxSetting.GetInt()); allRoles.RemoveAll(x => x.IsImpostor()); allRoles.RemoveAll(x => x.IsNK()); allRoles.RemoveAll(x => x.IsNonNK()); + allRoles.RemoveAll(x => x.IsCoven()); DraftRoles = allRoles .Take(allPlayerIds.Length * 5) - .CombineWith(impRoles, nkRoles, nnkRoles) + .CombineWith(impRoles, nkRoles, nnkRoles, covenRoles) .Shuffle() .Partition(allPlayerIds.Length) .Zip(allPlayerIds) @@ -694,10 +696,9 @@ internal static class ChatCommands private static void MuteCommand(PlayerControl player, string text, string[] args) { if (!player.IsHost() && (GameStates.InGame || MutedPlayers.ContainsKey(player.PlayerId))) return; + if (!byte.TryParse(args[1], out byte id) || id.IsHost()) return; - if (args.Length < 3 || !byte.TryParse(args[1], out byte id) || id.IsHost()) return; - - int duration = !int.TryParse(args[2], out int dur) ? 60 : dur; + int duration = args.Length < 3 || !int.TryParse(args[2], out int dur) ? 60 : dur; MutedPlayers[id] = (Utils.TimeStamp, duration); Utils.SendMessage("\n", player.PlayerId, string.Format(GetString("PlayerMuted"), id.ColoredPlayerName(), duration)); Utils.SendMessage("\n", id, string.Format(GetString("YouMuted"), player.PlayerId.ColoredPlayerName(), duration)); diff --git a/Patches/PlayerJoinAndLeftPatch.cs b/Patches/PlayerJoinAndLeftPatch.cs index 4fe1b5212..12a8a44f6 100644 --- a/Patches/PlayerJoinAndLeftPatch.cs +++ b/Patches/PlayerJoinAndLeftPatch.cs @@ -76,7 +76,7 @@ internal static class OnGameJoinedPatch { JoiningGame = false; - if (GameStates.IsOnlineGame && GameStates.CurrentServerType == GameStates.ServerType.Vanilla) + if (GameStates.IsOnlineGame && GameStates.CurrentServerType != GameStates.ServerType.Custom) { try { diff --git a/Resources/Lang/en_US.json b/Resources/Lang/en_US.json index d7fabd27f..46c707106 100644 --- a/Resources/Lang/en_US.json +++ b/Resources/Lang/en_US.json @@ -5500,6 +5500,8 @@ "DoomsayerGuessSameRoleAgainMsg": "You tried to guess the same role or add-on that you guessed before", "DoYourTasksPlease": "Please do your tasks!", "OnlyShowPart": "Shown only part", + "YouReceivedTheNecronomicon": "You have received the <{0}>Necronomicon! This grants you the ability to kill normally, and other abilities based on your role.", + "PlayerReceivedTheNecronomicon": "{0} has received the <{1}>Necronomicon!", "CovenLeader": "Coven Leader", "CovenLeaderInfo": "Lead the Coven & Kill", "CovenLeaderInfoLong": "(Coven):\\nYou will always spawn if the Coven is enabled. You are the only Coven member who can directly kill. You gain the Necronomicon first. When your powers are enhanced by the Necronomicon, your kill cooldown is halved, and you gain a long kill distance.", diff --git a/Roles/Coven/Banshee.cs b/Roles/Coven/Banshee.cs index eae6e4700..e55f1a115 100644 --- a/Roles/Coven/Banshee.cs +++ b/Roles/Coven/Banshee.cs @@ -64,6 +64,7 @@ public class Banshee : Coven w.WritePacked(1); w.WritePacked(ScreechedPlayers.Count); ScreechedPlayers.Do(x => w.Write(x)); + Utils.EndRPC(w); Utils.NotifyRoles(SpecifySeer: pc); } diff --git a/Roles/Coven/Coven.cs b/Roles/Coven/Coven.cs index ba6290118..441a89e48 100644 --- a/Roles/Coven/Coven.cs +++ b/Roles/Coven/Coven.cs @@ -17,17 +17,23 @@ public abstract class Coven : RoleBase protected bool HasNecronomicon { get; private set; } protected virtual void OnReceiveNecronomicon() { } - + private static void GiveNecronomicon() { - var covenPlayers = Main.PlayerStates.Values.Select(x => x.Role as Coven).Where(x => x != null).ToList(); - covenPlayers.RemoveAll(x => x.HasNecronomicon || x.NecronomiconReceivePriority == NecronomiconReceivePriorities.Never); - - if (covenPlayers.Count == 0) return; + var psDict = Main.PlayerStates.Where(x => x.Value.Role is Coven { HasNecronomicon: false } coven && coven.NecronomiconReceivePriority != NecronomiconReceivePriorities.Never).ToDictionary(x => x.Key, x => x.Value); + if (psDict.Count == 0) return; - var receiver = covenPlayers.Find(x => x.NecronomiconReceivePriority == NecronomiconReceivePriorities.First) ?? covenPlayers.RandomElement(); - receiver.HasNecronomicon = true; - receiver.OnReceiveNecronomicon(); + var receiver = psDict.Shuffle().OrderBy(x => ((Coven)x.Value.Role).NecronomiconReceivePriority).First(); + + var covenRole = (Coven)receiver.Value.Role; + covenRole.HasNecronomicon = true; + covenRole.OnReceiveNecronomicon(); + + LateTask.New(() => + { + Utils.SendMessage("\n", receiver.Key, string.Format(Translator.GetString("YouReceivedTheNecronomicon"), Main.CovenColor)); + Main.AllPlayerControls.Where(x => x.Is(Team.Coven)).Select(x => x.PlayerId).Do(x => Utils.SendMessage("\n", x, string.Format(Translator.GetString("PlayerReceivedTheNecronomicon"), receiver.Key.ColoredPlayerName(), Main.CovenColor))); + }, 12f, log: false); } [HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.Start))] diff --git a/Roles/Neutral/Werewolf.cs b/Roles/Neutral/Werewolf.cs index c708b8a3d..98081f773 100644 --- a/Roles/Neutral/Werewolf.cs +++ b/Roles/Neutral/Werewolf.cs @@ -61,14 +61,14 @@ public class Werewolf : RoleBase WWId = playerId; RampageTime = -10; - lastTime = -10; - CD = StartingKillCooldown.GetInt(); + lastTime = Utils.TimeStamp + 12; + CD = 0; LateTask.New(() => { if (UseUnshiftTrigger.GetBool() && UseUnshiftTriggerForNKs.GetBool()) Utils.GetPlayerById(playerId).RpcResetAbilityCooldown(); - }, 9f, log: false); + }, 12f, log: false); } public override void Remove(byte playerId) @@ -146,9 +146,13 @@ public class Werewolf : RoleBase { lastTime = -10; bool unshift = UseUnshiftTrigger.GetBool() && UseUnshiftTriggerForNKs.GetBool(); - if (!player.IsModClient()) player.Notify(GetString(unshift ? "WWCanRampageUnshift" : "WWCanRampage")); - - if (!player.IsModClient()) player.RpcChangeRoleBasis(unshift ? CustomRoles.Werewolf : CustomRoles.EngineerEHR); + + if (!player.IsModClient()) + { + player.Notify(GetString(unshift ? "WWCanRampageUnshift" : "WWCanRampage")); + player.RpcChangeRoleBasis(unshift ? CustomRoles.Werewolf : CustomRoles.EngineerEHR); + } + SendRPC(); CD = 0; }