diff --git a/GameMode/SoloPVP.cs b/GameMode/SoloPVP.cs index 7f56a9291..4b15a635e 100644 --- a/GameMode/SoloPVP.cs +++ b/GameMode/SoloPVP.cs @@ -26,7 +26,6 @@ internal static class SoloPVP private static Dictionary BackCountdown = []; private static Dictionary LastHurt = []; - private static Dictionary LastRecover = []; private static Dictionary LastCountdownTime = []; public static bool SoloAlive(this PlayerControl pc) @@ -93,7 +92,6 @@ internal static class SoloPVP PlayerDF = []; LastHurt = []; - LastRecover = []; LastCountdownTime = []; OriginalSpeed = []; BackCountdown = []; @@ -111,7 +109,6 @@ internal static class SoloPVP KBScore.TryAdd(pc.PlayerId, 0); LastHurt.TryAdd(pc.PlayerId, Utils.TimeStamp); - LastRecover.TryAdd(pc.PlayerId, Utils.TimeStamp); LastCountdownTime.TryAdd(pc.PlayerId, Utils.TimeStamp); } } @@ -141,6 +138,10 @@ internal static class SoloPVP string finalText = string.Empty; if (pc.IsHost()) return finalText; + finalText += ""; + finalText += GetHudText(); + finalText += "\n"; + finalText += ""; finalText += $"\n{Translator.GetString("PVP.ATK")}: {PlayerATK[pc.PlayerId]:N1}"; finalText += $"\n{Translator.GetString("PVP.DF")}: {PlayerDF[pc.PlayerId]:N1}"; @@ -210,11 +211,11 @@ internal static class SoloPVP float kcd = KB_ATKCooldown.GetFloat(); if (killer.IsHost()) kcd += Math.Max(0.5f, Utils.CalculatePingDelay()); - killer.SetKillCooldown(kcd, target); + RPC.PlaySoundRPC(killer.PlayerId, Sounds.KillSound); RPC.PlaySoundRPC(target.PlayerId, Sounds.KillSound); - if (!target.IsModClient() && !target.AmOwner) target.RpcGuardAndKill(); + if (!target.IsModClient() && !target.AmOwner) target.SetKillCooldown(0.01f); Utils.NotifyRoles(SpecifySeer: killer, SpecifyTarget: target); Utils.NotifyRoles(SpecifySeer: target, SpecifyTarget: killer); @@ -326,49 +327,50 @@ internal static class SoloPVP byte id = __instance.PlayerId; if (!GameStates.IsInTask || !CustomGameMode.SoloKombat.IsActiveOrIntegrated() || !AmongUsClient.Instance.AmHost || id == 255) return; - if (!__instance.SoloAlive()) - { - if (__instance.inVent && KB_BootVentWhenDead.GetBool()) - __instance.MyPhysics.RpcExitVent(2); + bool soloAlive = __instance.SoloAlive(); + bool inVent = __instance.inVent; - Vector2 pos = Pelican.GetBlackRoomPS(); - float dis = Vector2.Distance(pos, __instance.Pos()); - if (dis > 1f) __instance.TP(pos); + switch (soloAlive) + { + case false: + { + if (inVent && KB_BootVentWhenDead.GetBool()) + __instance.MyPhysics.RpcExitVent(2); + + Vector2 pos = Pelican.GetBlackRoomPS(); + float dis = Vector2.Distance(pos, __instance.Pos()); + if (dis > 1f) __instance.TP(pos); + break; + } + case true when !inVent: + { + Vector2 pos = Pelican.GetBlackRoomPS(); + float dis = Vector2.Distance(pos, __instance.Pos()); + if (dis < 1.1f) PlayerRandomSpwan(__instance); + break; + } } - var notifyRoles = false; long now = Utils.TimeStamp; + if (LastCountdownTime[id] == now) return; + LastCountdownTime[id] = now; - if (LastHurt[id] + KB_RecoverAfterSecond.GetInt() < now && LastRecover[id] != now && PlayerHP[id] < PlayerHPMax[id] && __instance.SoloAlive() && !__instance.inVent) + if (LastHurt[id] + KB_RecoverAfterSecond.GetInt() < now && PlayerHP[id] < PlayerHPMax[id] && soloAlive && !inVent) { - LastRecover[id] = now; PlayerHP[id] += PlayerHPReco[id]; PlayerHP[id] = Math.Min(PlayerHPMax[id], PlayerHP[id]); - notifyRoles = true; } - if (__instance.SoloAlive() && !__instance.inVent) + if (BackCountdown.ContainsKey(id)) { - Vector2 pos = Pelican.GetBlackRoomPS(); - float dis = Vector2.Distance(pos, __instance.Pos()); - if (dis < 1.1f) PlayerRandomSpwan(__instance); - } - - if (BackCountdown.ContainsKey(id) && LastCountdownTime[id] != now) - { - LastCountdownTime[id] = now; BackCountdown[id]--; if (BackCountdown[id] <= 0) OnPlayerBack(__instance); - notifyRoles = true; } - if (NameNotify.ContainsKey(id) && NameNotify[id].TimeStamp < now) - { + if (NameNotify.TryGetValue(id, out var nameNotify) && nameNotify.TimeStamp < now) NameNotify.Remove(id); - notifyRoles = true; - } - if (notifyRoles) Utils.NotifyRoles(SpecifySeer: __instance, SpecifyTarget: __instance); + Utils.NotifyRoles(SpecifySeer: __instance, SpecifyTarget: __instance); if (LastFixedUpdate == now) return; diff --git a/Modules/CustomRoleSelector.cs b/Modules/CustomRoleSelector.cs index 117901178..be335996f 100644 --- a/Modules/CustomRoleSelector.cs +++ b/Modules/CustomRoleSelector.cs @@ -170,6 +170,18 @@ internal static class CustomRoleSelector .Where(x => x.Key.GetTabFromOptionType() == TabGroup.NeutralRoles || x.Value[0].GetBool()) .ToDictionary(x => x.Key, x => IRandom.Instance.Next(x.Value[1].GetInt(), x.Value[2].GetInt() + 1)); + try + { + var impLimits = subCategoryLimits.Where(x => x.Key.GetTabFromOptionType() == TabGroup.ImpostorRoles).ToDictionary(x => x.Key, x => x.Value); + + if (impLimits.Count > 0 && impLimits.Sum(x => x.Value) < optImpNum) + { + // ReSharper disable once AccessToModifiedClosure + impLimits.Keys.Do(x => subCategoryLimits[x] = Options.RoleSubCategoryLimits[x][2].GetInt()); + } + } + catch (Exception e) { Utils.ThrowException(e); } + if (subCategoryLimits.Count > 0) Logger.Info($"Sub-Category Limits: {string.Join(", ", subCategoryLimits.Select(x => $"{x.Key}: {x.Value}"))}", "SubCategoryLimits"); int nkLimit = subCategoryLimits[RoleOptionType.Neutral_Killing]; diff --git a/Modules/Utils.cs b/Modules/Utils.cs index ee39b2df9..94afb8991 100644 --- a/Modules/Utils.cs +++ b/Modules/Utils.cs @@ -2841,6 +2841,9 @@ public static class Utils switch (target.GetCustomRole()) { + case CustomRoles.Hypnotist when disconnect && Hypnotist.DoReportAfterHypnosisEnds.GetBool(): + ReportDeadBodyPatch.CanReport.SetAllValues(true); + break; case CustomRoles.Curser: ((Curser)Main.PlayerStates[target.PlayerId].Role).OnDeath(); break; diff --git a/Patches/OnGameStartedPatch.cs b/Patches/OnGameStartedPatch.cs index 665aa58ad..bf142a569 100644 --- a/Patches/OnGameStartedPatch.cs +++ b/Patches/OnGameStartedPatch.cs @@ -229,10 +229,14 @@ internal class ChangeRoleSettings ChatCommands.LastSpectators.Clear(); ChatCommands.LastSpectators.UnionWith(ChatCommands.Spectators); - var impLimits = Options.FactionMinMaxSettings[Team.Impostor]; - int optImpNum = IRandom.Instance.Next(impLimits.MinSetting.GetInt(), impLimits.MaxSetting.GetInt() + 1); - GameOptionsManager.Instance.currentNormalGameOptions.NumImpostors = optImpNum; - GameOptionsManager.Instance.CurrentGameOptions.SetInt(Int32OptionNames.NumImpostors, optImpNum); + try + { + var impLimits = Options.FactionMinMaxSettings[Team.Impostor]; + int optImpNum = IRandom.Instance.Next(impLimits.MinSetting.GetInt(), impLimits.MaxSetting.GetInt() + 1); + GameOptionsManager.Instance.currentNormalGameOptions.NumImpostors = optImpNum; + GameOptionsManager.Instance.CurrentGameOptions.SetInt(Int32OptionNames.NumImpostors, optImpNum); + } + catch (Exception e) { Utils.ThrowException(e); } GameOptionsManager.Instance.currentNormalGameOptions.ConfirmImpostor = false; Main.RealOptionsData = new(GameOptionsManager.Instance.CurrentGameOptions); diff --git a/Roles/Impostor/Hypnotist.cs b/Roles/Impostor/Hypnotist.cs index dbdc6c9d9..4f6c9948c 100644 --- a/Roles/Impostor/Hypnotist.cs +++ b/Roles/Impostor/Hypnotist.cs @@ -15,7 +15,7 @@ public class Hypnotist : RoleBase public static OptionItem AbilityDuration; public static OptionItem AbilityUseLimit; public static OptionItem AbilityUseGainWithEachKill; - private static OptionItem DoReportAfterHypnosisEnds; + public static OptionItem DoReportAfterHypnosisEnds; private long ActivateTS; private int Count; @@ -96,7 +96,6 @@ public class Hypnotist : RoleBase pc.RpcResetAbilityCooldown(); Utils.SendRPC(CustomRPC.SyncRoleData, HypnotistId, ActivateTS); if (DoReportAfterHypnosisEnds.GetBool()) ReportDeadBodyPatch.CanReport.SetAllValues(true); - break; case <= 6 when Count++ >= 30: Count = 0;