From 89e90bfef8fe514ffc244b43279c17703c04b267 Mon Sep 17 00:00:00 2001 From: NockyCZ <63038995+NockyCZ@users.noreply.github.com> Date: Fri, 1 Mar 2024 15:34:02 +0100 Subject: [PATCH] Update v1.0.8 --- source/Commands.cs | 5 ++ source/Configs.cs | 1 + source/Deathmatch.cs | 33 ++++--- source/Events.cs | 79 +++++------------ source/Functions/Players.cs | 23 ++--- source/Functions/Spawns.cs | 169 +++++++++++++++++++++++++----------- source/Functions/Weapons.cs | 2 +- 7 files changed, 176 insertions(+), 136 deletions(-) diff --git a/source/Commands.cs b/source/Commands.cs index e86c3bb..14415ab 100644 --- a/source/Commands.cs +++ b/source/Commands.cs @@ -131,6 +131,11 @@ public void OnStartMode_CMD(CCSPlayerController player, CommandInfo info) [RequiresPermissions("@css/root")] public void OnEditor_CMD(CCSPlayerController player, CommandInfo info) { + if (Config.Gameplay.DefaultSpawns) + { + info.ReplyToCommand($"{Localizer["Prefix"]} The Spawn Editor cannot be used if you are using the default spawns!"); + return; + } g_bIsActiveEditor = !g_bIsActiveEditor; info.ReplyToCommand($"{Localizer["Prefix"]} Spawn Editor has been {ChatColors.Green}{(g_bIsActiveEditor ? "Enabled" : "Disabled")}"); if (g_bIsActiveEditor) diff --git a/source/Configs.cs b/source/Configs.cs index df901b8..3da2228 100644 --- a/source/Configs.cs +++ b/source/Configs.cs @@ -37,6 +37,7 @@ public class Gameplay [JsonPropertyName("Default Weapons")] public int DefaultModeWeapons { get; set; } = 2; [JsonPropertyName("Switch Weapons")] public bool SwitchWeapons { get; set; } = true; [JsonPropertyName("Allow Buymenu")] public bool AllowBuyMenu { get; set; } = true; + [JsonPropertyName("Use Default Spawns")] public bool DefaultSpawns { get; set; } = false; [JsonPropertyName("Respawn Players After New Mode")] public bool RespawnPlayersAtNewMode { get; set; } = false; } public class General diff --git a/source/Deathmatch.cs b/source/Deathmatch.cs index cedb86b..80d24d7 100644 --- a/source/Deathmatch.cs +++ b/source/Deathmatch.cs @@ -12,12 +12,12 @@ namespace Deathmatch; -[MinimumApiVersion(166)] +[MinimumApiVersion(178)] public partial class DeathmatchCore : BasePlugin, IPluginConfig { public override string ModuleName => "Deathmatch Core"; public override string ModuleAuthor => "Nocky"; - public override string ModuleVersion => "1.0.7"; + public override string ModuleVersion => "1.0.8"; public static DeathmatchCore Instance { get; set; } = new(); public class ModeInfo { @@ -27,7 +27,6 @@ public class ModeInfo public bool OnlyHS { get; set; } = false; public bool KnifeDamage { get; set; } = true; public bool RandomWeapons { get; set; } = true; - public bool CenterMessage { get; set; } = false; public string CenterMessageText { get; set; } = ""; } @@ -66,6 +65,7 @@ public enum AcquireMethod : int public static bool g_bIsActiveEditor = false; public static bool g_bDefaultMapSpawnDisabled = false; public static bool g_bWeaponRestrictGlobal; + public static bool IsCasualGamemode; public MemoryFunctionWithReturn? CCSPlayer_CanAcquireFunc; public MemoryFunctionWithReturn? GetCSWeaponDataFromKeyFunc; @@ -111,6 +111,7 @@ public override void Load(bool hotReload) AddCustomCommands(cmd, "", 3); foreach (string radioName in RadioMessagesList) AddCommandListener(radioName, OnPlayerRadioMessage); + AddCommandListener("autobuy", OnRandomWeapons); RegisterListener(() => { modeTimer?.Kill(); }); RegisterListener(mapName => @@ -152,14 +153,11 @@ public override void Load(bool hotReload) }, TimerFlags.REPEAT | TimerFlags.STOP_ON_MAPCHANGE); } - AddTimer(1.0f, () => - { - RemoveEntities(); - LoadMapSpawns(ModuleDirectory + $"/spawns/{mapName}.json", true); - SetupDeathMatchConfigValues(); - SetupCustomMode(Config.Gameplay.MapStartMode.ToString()); - SetupDeathmatchMenus(); - }); + RemoveEntities(); + SetupDeathMatchConfigValues(); + SetupCustomMode(Config.Gameplay.MapStartMode.ToString()); + SetupDeathmatchMenus(); + LoadMapSpawns(ModuleDirectory + $"/spawns/{mapName}.json", true); }); }); RegisterListener(() => @@ -177,7 +175,7 @@ public override void Load(bool hotReload) { foreach (var p in Utilities.GetPlayers().Where(p => playerData.ContainsPlayer(p) && playerData[p].HudMessages)) { - if (ModeData.CenterMessage && !string.IsNullOrEmpty(ModeData.CenterMessageText) && MenuManager.GetActiveMenu(p) == null) + if (!string.IsNullOrEmpty(ModeData.CenterMessageText) && MenuManager.GetActiveMenu(p) == null) { p.PrintToCenterHtml($"{ModeData.CenterMessageText}"); } @@ -223,7 +221,6 @@ public void SetupCustomMode(string modetype) ModeData.OnlyHS = modeValue["only_hs"]?.Value() ?? false; ModeData.KnifeDamage = modeValue["allow_knife_damage"]?.Value() ?? true; ModeData.RandomWeapons = modeValue["random_weapons"]?.Value() ?? false; - ModeData.CenterMessage = modeValue["allow_center_message"]?.Value() ?? false; ModeData.CenterMessageText = modeValue["center_message_text"]?.ToString() ?? ""; g_iActiveMode = int.Parse(modetype); @@ -298,6 +295,10 @@ public void SetupDeathmatchConfiguration(bool isNewMode) } public void SetupDeathMatchConfigValues() { + var gameType = ConVar.Find("game_type")!.GetPrimitiveValue(); + Server.PrintToConsole($"gametype {gameType}"); + IsCasualGamemode = gameType != 1; + var iHideSecond = Config.General.HideRoundSeconds ? 1 : 0; var time = ConVar.Find("mp_timelimit")!.GetPrimitiveValue(); var iFFA = Config.Gameplay.IsFFA ? 1 : 0; @@ -310,6 +311,12 @@ public void SetupDeathMatchConfigValues() Server.ExecuteCommand("mp_buy_anywhere 1;mp_buytime 60000;mp_buy_during_immunity 0"); else Server.ExecuteCommand("mp_buy_anywhere 0;mp_buytime 0;mp_buy_during_immunity 0"); + + if (!IsCasualGamemode) + { + var TeamMode = Config.Gameplay.IsFFA ? 0 : 1; + Server.ExecuteCommand($"mp_dm_teammode {TeamMode}; mp_dm_bonus_length_max 0;mp_dm_bonus_length_min 0;mp_dm_time_between_bonus_max 9999;mp_dm_time_between_bonus_min 9999;mp_respawn_immunitytime 0"); + } } public int GetModeType() { diff --git a/source/Events.cs b/source/Events.cs index 359e677..fbe56dd 100644 --- a/source/Events.cs +++ b/source/Events.cs @@ -101,30 +101,7 @@ public HookResult OnPlayerDeath(EventPlayerDeath @event, GameEventInfo info) timer = AdminManager.PlayerHasPermissions(player, Config.PlayersSettings.VIPFlag) ? Config.PlayersSettings.RespawnTimeVIP : Config.PlayersSettings.RespawnTime; @event.FireEventToClient(player); } - - AddTimer(timer, () => - { - if (player != null && player.IsValid) - { - string[] spawns = CheckAvaibleSpawns(player, player.TeamNum, IsBot); - if (!string.IsNullOrEmpty(spawns[0])) - { - switch (spawns[0]) - { - case "not found": - RespawnPlayer(player, spawns, false); - SendConsoleMessage($"[Deathmatch] Player {player.PlayerName} was respawned, but no available spawn point was found! Therefore, a random spawn was selected.", ConsoleColor.DarkYellow); - break; - case "default": - RespawnPlayer(player, spawns, false); - break; - default: - RespawnPlayer(player, spawns); - break; - } - } - } - }, TimerFlags.STOP_ON_MAPCHANGE); + AddTimer(timer, () => { PerformRespawn(player, player.TeamNum, IsBot); }, TimerFlags.STOP_ON_MAPCHANGE); if (attacker != player && playerData.ContainsPlayer(attacker) && attacker.PlayerPawn.Value != null) { @@ -191,37 +168,30 @@ private HookResult OnPlayerRadioMessage(CCSPlayerController? player, CommandInfo return HookResult.Continue; } + + private HookResult OnRandomWeapons(CCSPlayerController? player, CommandInfo info) + { + return HookResult.Stop; + } private HookResult OnTakeDamage(DynamicHook hook) { - var p = hook.GetParam(0).Index; - if (p == 0) - return HookResult.Continue; - - var playerPawn = Utilities.GetEntityFromIndex((int)p); - if (playerPawn.OriginalController.Value is not { } player) - return HookResult.Continue; - var damageInfo = hook.GetParam(1); - var a = damageInfo.Attacker.Index; - if (a == 0) - return HookResult.Continue; + var player = new CCSPlayerController(new CCSPlayerPawn(hook.GetParam(0).Handle).Controller.Value!.Handle); + var attacker = new CCSPlayerController(new CCSPlayerPawn(damageInfo.Attacker.Value!.Handle).Controller.Value!.Handle); - var attackerPawn = Utilities.GetEntityFromIndex((int)a); - if (attackerPawn.OriginalController.Value is not { } attacker) + if (player == null || !player.IsValid || attacker == null || !attacker.IsValid) return HookResult.Continue; - if (player != null && player.IsValid && attacker != null && attacker.IsValid) + if (playerData.ContainsPlayer(player) && playerData[player].SpawnProtection) { - if (playerData.ContainsPlayer(player) && playerData[player].SpawnProtection) - { - damageInfo.Damage = 0; - } - if (!ModeData.KnifeDamage && damageInfo.Ability.IsValid && (damageInfo.Ability.Value!.DesignerName.Contains("knife") || damageInfo.Ability.Value!.DesignerName.Contains("bayonet"))) - { - attacker.PrintToCenter(Localizer["Knife_damage_disabled"]); - damageInfo.Damage = 0; - } + damageInfo.Damage = 0; + return HookResult.Continue; + } + if (!ModeData.KnifeDamage && damageInfo.Ability.IsValid && (damageInfo.Ability.Value!.DesignerName.Contains("knife") || damageInfo.Ability.Value!.DesignerName.Contains("bayonet"))) + { + attacker.PrintToCenter(Localizer["Knife_damage_disabled"]); + damageInfo.Damage = 0; } return HookResult.Continue; } @@ -246,6 +216,12 @@ private HookResult OnWeaponCanAcquire(DynamicHook hook) return HookResult.Continue; } + if (!IsCasualGamemode && blockRandomWeaponsIntegeration.Contains(player)) + { + hook.SetReturn(AcquireResult.AlreadyPurchased); + return HookResult.Stop; + } + if (ModeData.RandomWeapons) { if (!string.IsNullOrEmpty(Config.SoundSettings.CantEquipSound)) @@ -257,15 +233,6 @@ private HookResult OnWeaponCanAcquire(DynamicHook hook) if (!AllowedPrimaryWeaponsList.Contains(vdata!.Name!) && !AllowedSecondaryWeaponsList.Contains(vdata.Name)) { - /*if (vdata.Name.Contains("knife") || vdata.Name.Contains("bayonet")) - { - if (player.IsBot) - { - hook.SetReturn(AcquireResult.AlreadyPurchased); - return HookResult.Stop; - } - return HookResult.Continue; - }*/ if (!player.IsBot) { if (!string.IsNullOrEmpty(Config.SoundSettings.CantEquipSound)) diff --git a/source/Functions/Players.cs b/source/Functions/Players.cs index 3f279b9..70859ba 100644 --- a/source/Functions/Players.cs +++ b/source/Functions/Players.cs @@ -9,6 +9,7 @@ namespace Deathmatch { public partial class DeathmatchCore { + public List blockRandomWeaponsIntegeration = new List(); public class DeathmatchPlayerData { public required string PrimaryWeapon { get; set; } @@ -205,6 +206,11 @@ public void GivePlayerWeapons(CCSPlayerController player, bool bNewMode) playerData[player].SpawnProtection = true; var timer = AdminManager.PlayerHasPermissions(player, Config.PlayersSettings.VIPFlag) ? Config.PlayersSettings.ProtectionTimeVIP : Config.PlayersSettings.ProtectionTime; AddTimer(timer, () => playerData[player].SpawnProtection = false, TimerFlags.STOP_ON_MAPCHANGE); + if (!IsCasualGamemode && !blockRandomWeaponsIntegeration.Contains(player)) + { + blockRandomWeaponsIntegeration.Add(player); + AddTimer(0.25f, () => blockRandomWeaponsIntegeration.Remove(player), TimerFlags.STOP_ON_MAPCHANGE); + } } int slot = IsHaveWeaponFromSlot(player, 0); @@ -330,23 +336,6 @@ public void GivePlayerWeapons(CCSPlayerController player, bool bNewMode) } }, TimerFlags.STOP_ON_MAPCHANGE); } - public static void RespawnPlayer(CCSPlayerController player, string[] spawn, bool teleport = true) - { - if (!player.IsValid || !player.PlayerPawn.IsValid || player.PawnIsAlive) - return; - - if (player.TeamNum == 2 || player.TeamNum == 3) - { - player.Respawn(); - - if (teleport) - { - var position = ParseVector(spawn[0]); - var angle = ParseQAngle(spawn[1]); - player.PlayerPawn.Value!.Teleport(position, angle, new Vector(0, 0, 0)); - } - } - } public static bool IsPlayerValid(CCSPlayerController player) { if (player is null || !player.IsValid || !player.PlayerPawn.IsValid || player.IsBot || player.IsHLTV || player.SteamID.ToString().Length != 17) diff --git a/source/Functions/Spawns.cs b/source/Functions/Spawns.cs index 52bf854..de8cd30 100644 --- a/source/Functions/Spawns.cs +++ b/source/Functions/Spawns.cs @@ -15,16 +15,10 @@ public partial class DeathmatchCore public static Dictionary spawnPositionsCT = new Dictionary(); public static Dictionary spawnPositionsT = new Dictionary(); - public string[] CheckAvaibleSpawns(CCSPlayerController player, int team, bool IsBot) + public void PerformRespawn(CCSPlayerController player, int team, bool IsBot) { - if (GameRules().WarmupPeriod || !Config.Gameplay.CheckDistance || !g_bDefaultMapSpawnDisabled) - { - return new string[] { "default" }; - } - if (team == 1 || team == 0) - { - return new string[] { "" }; - } + if (player == null || !player.IsValid || !player.PlayerPawn.IsValid || player.PawnIsAlive || team == 1 || team == 0) + return; var spawnsDictionary = team == (byte)CsTeam.Terrorist ? spawnPositionsT : spawnPositionsCT; var spawnsList = spawnsDictionary.ToList(); @@ -34,6 +28,22 @@ public string[] CheckAvaibleSpawns(CCSPlayerController player, int team, bool Is Random random = new Random(); spawnsList = spawnsList.OrderBy(x => random.Next()).ToList(); + var randomSpawn = spawnsList.FirstOrDefault(); + Vector position; + QAngle angle; + + if (GameRules().WarmupPeriod || !Config.Gameplay.CheckDistance || !g_bDefaultMapSpawnDisabled || Config.Gameplay.DefaultSpawns) + { + if (!IsBot) + playerData[player].LastSpawn = randomSpawn.Key; + + player.Respawn(); + position = ParseVector(randomSpawn.Key); + angle = ParseQAngle(randomSpawn.Value); + player.PlayerPawn.Value!.Teleport(position, angle, new Vector(0, 0, 0)); + return; + } + var closestDistances = CalculateClosestDistances(player, spawnsList); var Spawn = spawnsList.FirstOrDefault(spawn => @@ -47,13 +57,22 @@ public string[] CheckAvaibleSpawns(CCSPlayerController player, int team, bool Is { if (!IsBot) playerData[player].LastSpawn = Spawn.Key; - return new string[] { Spawn.Key, Spawn.Value }; + + player.Respawn(); + position = ParseVector(Spawn.Key); + angle = ParseQAngle(Spawn.Value); + player.PlayerPawn.Value!.Teleport(position, angle, new Vector(0, 0, 0)); + return; } if (!IsBot) - playerData[player].LastSpawn = "0"; + playerData[player].LastSpawn = randomSpawn.Key; - return new string[] { "not found" }; + player.Respawn(); + position = ParseVector(randomSpawn.Key); + angle = ParseQAngle(randomSpawn.Value); + player.PlayerPawn.Value!.Teleport(position, angle, new Vector(0, 0, 0)); + SendConsoleMessage($"[Deathmatch] Player {player.PlayerName} was respawned, but no available spawn point was found! Therefore, a random spawn was selected.", ConsoleColor.DarkYellow); } private Dictionary CalculateClosestDistances(CCSPlayerController player, List> spawnsList) @@ -239,38 +258,65 @@ public static void RemoveMapDefaulSpawns() { if (!g_bDefaultMapSpawnDisabled) { - int iDefaultCTSpawns = 0; - int iDefaultTSpawns = 0; - var ctSpawns = Utilities.FindAllEntitiesByDesignerName("info_player_counterterrorist"); - foreach (var entity in ctSpawns) + if (IsCasualGamemode) { - if (entity.IsValid) + int iDefaultCTSpawns = 0; + int iDefaultTSpawns = 0; + var ctSpawns = Utilities.FindAllEntitiesByDesignerName("info_player_counterterrorist"); + foreach (var entity in ctSpawns) + { + if (entity.IsValid) + { + entity.AcceptInput("SetDisabled"); + iDefaultCTSpawns++; + } + } + var tSpawns = Utilities.FindAllEntitiesByDesignerName("info_player_terrorist"); + foreach (var entity in tSpawns) { - entity.AcceptInput("SetDisabled"); - iDefaultCTSpawns++; + if (entity.IsValid) + { + entity.AcceptInput("SetDisabled"); + iDefaultTSpawns++; + } } + SendConsoleMessage($"[Deathmatch] Total {iDefaultTSpawns} T and {iDefaultCTSpawns} CT default Spawns disabled!", ConsoleColor.Green); } - var tSpawns = Utilities.FindAllEntitiesByDesignerName("info_player_terrorist"); - foreach (var entity in tSpawns) + else { - if (entity.IsValid) + int DMSpawns = 0; + var dmSpawns = Utilities.FindAllEntitiesByDesignerName("info_deathmatch_spawn"); + foreach (var entity in dmSpawns) { - entity.AcceptInput("SetDisabled"); - iDefaultTSpawns++; + if (entity.IsValid) + { + entity.AcceptInput("SetDisabled"); + DMSpawns++; + } } + SendConsoleMessage($"[Deathmatch] Total {DMSpawns} default Spawns disabled!", ConsoleColor.Green); + } - SendConsoleMessage($"[Deathmatch] Total {iDefaultTSpawns} T and {iDefaultCTSpawns} CT default Spawns disabled!", ConsoleColor.Green); g_bDefaultMapSpawnDisabled = true; CreateCustomMapSpawns(); } } public static void CreateCustomMapSpawns() { + string infoPlayerCT = IsCasualGamemode ? "info_player_counterterrorist" : "info_deathmatch_spawn"; + string infoPlayerT = IsCasualGamemode ? "info_player_terrorist" : "info_deathmatch_spawn"; + foreach (var spawn in spawnPositionsCT) { var position = ParseVector(spawn.Key); var angle = ParseQAngle(spawn.Value); - var entity = Utilities.CreateEntityByName("info_player_counterterrorist"); + + CBaseEntity entity; + if (IsCasualGamemode) + entity = Utilities.CreateEntityByName(infoPlayerCT)!; + else + entity = Utilities.CreateEntityByName(infoPlayerCT)!; + if (entity == null) { SendConsoleMessage($"[Deathmatch] Failed to create spawn point for CT", ConsoleColor.DarkYellow); @@ -283,7 +329,11 @@ public static void CreateCustomMapSpawns() { var position = ParseVector(spawn.Key); var angle = ParseQAngle(spawn.Value); - var entity = Utilities.CreateEntityByName("info_player_terrorist"); + CBaseEntity entity; + if (IsCasualGamemode) + entity = Utilities.CreateEntityByName(infoPlayerT)!; + else + entity = Utilities.CreateEntityByName(infoPlayerT)!; if (entity == null) { SendConsoleMessage($"[Deathmatch] Failed to create spawn point for T", ConsoleColor.DarkYellow); @@ -293,40 +343,61 @@ public static void CreateCustomMapSpawns() entity.DispatchSpawn(); } } - public static void LoadMapSpawns(string filepath, bool mapstart) + public void LoadMapSpawns(string filepath, bool mapstart) { spawnPositionsCT.Clear(); spawnPositionsT.Clear(); - - if (!File.Exists(filepath)) + if (Config.Gameplay.DefaultSpawns) { - SendConsoleMessage($"[Deathmatch] No spawn points found for this map! (Deathmatch/spawns/{Server.MapName}.json)", ConsoleColor.Red); + foreach (var spawn in Utilities.FindAllEntitiesByDesignerName("info_player_counterterrorist")) + { + if (spawn == null) + return; + spawnPositionsCT.Add($"{spawn.AbsOrigin}", $"{spawn.AbsRotation}"); + } + foreach (var spawn in Utilities.FindAllEntitiesByDesignerName("info_player_terrorist")) + { + if (spawn == null) + return; + + spawnPositionsT.Add($"{spawn.AbsOrigin}", $"{spawn.AbsRotation}"); + } + + g_iTotalCTSpawns = spawnPositionsCT.Count; + g_iTotalTSpawns = spawnPositionsT.Count; } else { - var jsonContent = File.ReadAllText(filepath); - JObject jsonData = JsonConvert.DeserializeObject(jsonContent)!; - - foreach (var teamData in jsonData["spawnpoints"]!) + if (!File.Exists(filepath)) + { + SendConsoleMessage($"[Deathmatch] No spawn points found for this map! (Deathmatch/spawns/{Server.MapName}.json)", ConsoleColor.Red); + } + else { - string teamType = teamData["team"]!.ToString(); - string pos = teamData["pos"]!.ToString(); - string angle = teamData["angle"]!.ToString(); + var jsonContent = File.ReadAllText(filepath); + JObject jsonData = JsonConvert.DeserializeObject(jsonContent)!; - if (teamType == "ct") - { - spawnPositionsCT.Add(pos, angle); - } - else if (teamType == "t") + foreach (var teamData in jsonData["spawnpoints"]!) { - spawnPositionsT.Add(pos, angle); + string teamType = teamData["team"]!.ToString(); + string pos = teamData["pos"]!.ToString(); + string angle = teamData["angle"]!.ToString(); + + if (teamType == "ct") + { + spawnPositionsCT.Add(pos, angle); + } + else if (teamType == "t") + { + spawnPositionsT.Add(pos, angle); + } } - } - g_iTotalCTSpawns = spawnPositionsCT.Count; - g_iTotalTSpawns = spawnPositionsT.Count; - if (mapstart) - RemoveMapDefaulSpawns(); + g_iTotalCTSpawns = spawnPositionsCT.Count; + g_iTotalTSpawns = spawnPositionsT.Count; + if (mapstart) + RemoveMapDefaulSpawns(); + } } } private static Vector ParseVector(string pos) diff --git a/source/Functions/Weapons.cs b/source/Functions/Weapons.cs index a7d8c89..89268ab 100644 --- a/source/Functions/Weapons.cs +++ b/source/Functions/Weapons.cs @@ -231,7 +231,7 @@ public string GetWeaponFromSlot(CCSPlayerController player, int slot) } public int IsHaveWeaponFromSlot(CCSPlayerController player, int slot) { - if (!player.IsValid && player == null && player!.PlayerPawn == null || player.PlayerPawn.Value == null || player.PlayerPawn.Value.WeaponServices == null || !player.PawnIsAlive) + if (player == null || !player.IsValid || player.PlayerPawn == null || player.PlayerPawn.Value == null || player.PlayerPawn.Value.WeaponServices == null || !player.PawnIsAlive) return 3; foreach (var weapon in player.PlayerPawn.Value.WeaponServices.MyWeapons)