Updates & Fixes

# Updates & Fixes
- New Commands: Added `css_bot_place` which teleports a bot to the player's position with optional godmode and translation support.
- Miner (New Skill): Added a new skill that allows for detonating HE grenades near enemies.
- Bomb Abort Support: Introduced `BombAbortplant` support across `ISkill` and event registration; added handlers for aborting plants in Planter, ChillOut, and other skills.
- System (Rework & Optimization):
    - Reworked player event dispatching to call `SkillAction` once per distinct active skill, reducing redundant invocations.
    - Switched timing logic to use `Server.CurrentTime` (replacing `EngineTime`).
    - Added extensive null and validity guards for player and pawn objects.
- Skill-specific Changes:
    - AimLock: Fixed vector/validation issues and updated config defaults (cooldown, duration, and offset).
    - AreaReaper: Now uses `BombPlantedHere` state and includes `OnTick` alerts.
    - ChillOut & Planter: Improved tracking for planting players with center-print and HUD updates.
    - HomingNades: Simplified callbacks and fixed detonation timing.
    - Muhammed: Tweaked explosion delay handling and reduced friendly fire damage.
- Core & Utils:
    - TraceRay: Implemented `CS2TraceRay` for skills to prevent activation through doors or on dropped weapons.
    - Dependencies: Bumped `CounterStrikeSharp.API` to 1.0.364 and `MaxMind.Db` to 5.0.0.
    - Bug Fixes: Resolved multiple HUD/print update issues and fixed various translation keys.
This commit is contained in:
Juzlus 2026-04-05 03:08:43 +02:00
parent 8634665983
commit a8890bde6a
22 changed files with 669 additions and 149 deletions

View file

@ -15,9 +15,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.363" /> <PackageReference Include="CounterStrikeSharp.API" Version="1.0.364" />
<PackageReference Include="CS2TraceRay" Version="1.0.9" /> <PackageReference Include="CS2TraceRay" Version="1.0.9" />
<PackageReference Include="MaxMind.Db" Version="4.3.4"> <PackageReference Include="MaxMind.Db" Version="5.0.0">
</PackageReference> </PackageReference>
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
</ItemGroup> </ItemGroup>

View file

@ -42,6 +42,7 @@ namespace src.command
{ SplitCommands(config.NormalCommands.HealCommand.Alias), ("Heal", Command_Heal) }, { SplitCommands(config.NormalCommands.HealCommand.Alias), ("Heal", Command_Heal) },
{ SplitCommands(config.NormalCommands.HealthCommand.Alias), ("Set heath", Command_Health) }, { SplitCommands(config.NormalCommands.HealthCommand.Alias), ("Set heath", Command_Health) },
{ SplitCommands(config.NormalCommands.PlantedBomb.Alias), ("Spawn planted bomb", Command_PlantedBomb) }, { SplitCommands(config.NormalCommands.PlantedBomb.Alias), ("Spawn planted bomb", Command_PlantedBomb) },
{ SplitCommands(config.NormalCommands.BotPlace.Alias), ("Place bot on your position", Command_BotPlace) },
{ SplitCommands(config.NormalCommands.HudCommand.Alias), ("Enable/Disable HUD", Command_HUD) }, { SplitCommands(config.NormalCommands.HudCommand.Alias), ("Enable/Disable HUD", Command_HUD) },
{ SplitCommands(config.NormalCommands.SetStaticSkillCommand.Alias), ("Set static skill", Command_SetStaticSkill) }, { SplitCommands(config.NormalCommands.SetStaticSkillCommand.Alias), ("Set static skill", Command_SetStaticSkill) },
{ SplitCommands(config.NormalCommands.ChangeLanguageCommand.Alias), ("Change language", Command_ChangeLanguage) }, { SplitCommands(config.NormalCommands.ChangeLanguageCommand.Alias), ("Change language", Command_ChangeLanguage) },
@ -337,7 +338,7 @@ namespace src.command
if (int.TryParse(command.GetArg(1), out int health)) if (int.TryParse(command.GetArg(1), out int health))
SkillUtils.AddHealth(pawn, health - pawn.Health, health); SkillUtils.AddHealth(pawn, health - pawn.Health, health);
player.PrintToChat($" {ChatColors.Green}{player.GetTranslation("healed")}"); player.PrintToChat($" {ChatColors.Green}{player.GetTranslation("set_health")}");
} }
[CommandHelper(minArgs: 0, whoCanExecute: CommandUsage.CLIENT_ONLY)] [CommandHelper(minArgs: 0, whoCanExecute: CommandUsage.CLIENT_ONLY)]
@ -358,7 +359,38 @@ namespace src.command
if (!int.TryParse(command.GetArg(1), out int time)) if (!int.TryParse(command.GetArg(1), out int time))
time = 40; time = 40;
bomb.C4Blow = (float)Server.EngineTime + time; bomb.C4Blow = Server.CurrentTime + time;
player.PrintToChat($" {ChatColors.Green}{player.GetTranslation("planted_bomb_spawned", [time])}");
}
[CommandHelper(minArgs: 0, whoCanExecute: CommandUsage.CLIENT_ONLY)]
private static void Command_BotPlace(CCSPlayerController? player, CommandInfo command)
{
Debug.WriteToDebug($"Player {player?.PlayerName} used the css_bot_place {command.ArgString} command.");
if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return;
if (!string.IsNullOrEmpty(config.NormalCommands.BotPlace.Permissions) && !AdminManager.PlayerHasPermissions(player, config.NormalCommands.BotPlace.Permissions)) return;
var pawn = player.PlayerPawn.Value;
if (!player.PawnIsAlive || pawn.AbsOrigin == null || pawn.AbsRotation == null) return;
if (!int.TryParse(command.GetArg(1), out int botSlot))
botSlot = -1;
var bot = Utilities.GetPlayers().Where(p => p != null && p.IsValid && p.IsBot && p.PawnIsAlive && (botSlot == -1 || p.Slot == botSlot)).FirstOrDefault();
if (bot == null || bot.PlayerPawn.Value == null || !bot.PlayerPawn.Value.IsValid)
{
player.PrintToChat($" {ChatColors.Green}{player.GetTranslation("bot_placed_not_found")}");
return;
}
bot.PlayerPawn.Value.Teleport(new Vector(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z), new QAngle(pawn.AbsRotation.X, pawn.AbsRotation.Y, pawn.AbsRotation.Z), Vector.Zero);
bot.PlayerPawn.Value.TakesDamage = true;
if ((bool.TryParse(command.GetArg(2), out bool godmode) && godmode == true)
|| (int.TryParse(command.GetArg(2), out int godmodeInt) && godmodeInt == 1))
bot.PlayerPawn.Value.TakesDamage = false;
player.PrintToChat($" {ChatColors.Green}{player.GetTranslation("bot_placed")}");
} }
[CommandHelper(minArgs: 0, whoCanExecute: CommandUsage.CLIENT_ONLY)] [CommandHelper(minArgs: 0, whoCanExecute: CommandUsage.CLIENT_ONLY)]

View file

@ -118,8 +118,8 @@ namespace src
public Skills SpecialSkill { get; set; } public Skills SpecialSkill { get; set; }
public float? SkillChance { get; set; } public float? SkillChance { get; set; }
public bool IsDrawing { get; set; } public bool IsDrawing { get; set; }
public DateTime SkillHudExpired { get; set; } public DateTime SkillHudExpired { get; set; } = Config.LoadedConfig.SkillHudDuration == -1 ? DateTime.MaxValue : DateTime.Now.AddSeconds(Config.LoadedConfig.SkillHudDuration);
public DateTime SkillDescriptionHudExpired { get; set; } public DateTime SkillDescriptionHudExpired { get; set; } = Config.LoadedConfig.SkillDescriptionDuration == -1 ? DateTime.MaxValue : DateTime.Now.AddSeconds(Config.LoadedConfig.SkillDescriptionDuration);
public string? PrintHTML { get; set; } public string? PrintHTML { get; set; }
public bool DisplayHUD { get; set; } public bool DisplayHUD { get; set; }
public bool SkillUsed = false; public bool SkillUsed = false;

View file

@ -32,6 +32,7 @@ public interface ISkill
public static void GrenadeThrown(EventGrenadeThrown _) { } public static void GrenadeThrown(EventGrenadeThrown _) { }
public static void BombBeginplant(EventBombBeginplant _) { } public static void BombBeginplant(EventBombBeginplant _) { }
public static void BombAbortplant(EventBombAbortplant _) { }
public static void BombPlanted(EventBombPlanted _) { } public static void BombPlanted(EventBombPlanted _) { }
public static void BombBegindefuse(EventBombBegindefuse _) { } public static void BombBegindefuse(EventBombBegindefuse _) { }
@ -121,6 +122,7 @@ public enum Skills
Magneto, Magneto,
Magnifier, Magnifier,
Medic, Medic,
Miner,
MoneySwap, MoneySwap,
Muhammed, Muhammed,
Ninja, Ninja,

View file

@ -8,6 +8,9 @@ using CounterStrikeSharp.API.Modules.Memory;
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
using CounterStrikeSharp.API.Modules.UserMessages; using CounterStrikeSharp.API.Modules.UserMessages;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using CS2TraceRay.Class;
using CS2TraceRay.Enum;
using CS2TraceRay.Struct;
using src.player.skills; using src.player.skills;
using src.utils; using src.utils;
using System.Collections.Concurrent; using System.Collections.Concurrent;
@ -58,6 +61,7 @@ namespace src.player
Instance.RegisterEventHandler<EventGrenadeThrown>(GrenadeThrown); Instance.RegisterEventHandler<EventGrenadeThrown>(GrenadeThrown);
Instance.RegisterEventHandler<EventBombBeginplant>(BombBeginplant); Instance.RegisterEventHandler<EventBombBeginplant>(BombBeginplant);
Instance.RegisterEventHandler<EventBombAbortplant>(BombAbortplant);
Instance.RegisterEventHandler<EventBombPlanted>(BombPlanted); Instance.RegisterEventHandler<EventBombPlanted>(BombPlanted);
Instance.RegisterEventHandler<EventBombBegindefuse>(BombBegindefuse); Instance.RegisterEventHandler<EventBombBegindefuse>(BombBegindefuse);
@ -82,9 +86,13 @@ namespace src.player
{ {
lock (setLock) lock (setLock)
{ {
foreach (var playerSkill in Instance.SkillPlayer) var activeSkills = Instance.SkillPlayer
if (!playerSkill.IsDrawing) .Where(p => !p.IsDrawing)
Instance.SkillAction(playerSkill.Skill.ToString(), "PlayerMakeSound", [um]); .Select(p => p.Skill.ToString())
.Distinct();
foreach (string skillName in activeSkills)
Instance.SkillAction(skillName, "PlayerMakeSound", [um]);
return HookResult.Continue; return HookResult.Continue;
} }
} }
@ -93,9 +101,13 @@ namespace src.player
{ {
lock (setLock) lock (setLock)
{ {
foreach (var playerSkill in Instance.SkillPlayer) var activeSkills = Instance.SkillPlayer
if (!playerSkill.IsDrawing) .Where(p => !p.IsDrawing)
Instance.SkillAction(playerSkill.Skill.ToString(), "WeaponFire", [@event]); .Select(p => p.Skill.ToString())
.Distinct();
foreach (string skillName in activeSkills)
Instance.SkillAction(skillName, "WeaponFire", [@event]);
return HookResult.Continue; return HookResult.Continue;
} }
} }
@ -104,9 +116,13 @@ namespace src.player
{ {
lock (setLock) lock (setLock)
{ {
foreach (var playerSkill in Instance.SkillPlayer) var activeSkills = Instance.SkillPlayer
if (!playerSkill.IsDrawing) .Where(p => !p.IsDrawing)
Instance.SkillAction(playerSkill.Skill.ToString(), "WeaponEquip", [@event]); .Select(p => p.Skill.ToString())
.Distinct();
foreach (string skillName in activeSkills)
Instance.SkillAction(skillName, "WeaponEquip", [@event]);
return HookResult.Continue; return HookResult.Continue;
} }
} }
@ -115,9 +131,13 @@ namespace src.player
{ {
lock (setLock) lock (setLock)
{ {
foreach (var playerSkill in Instance.SkillPlayer) var activeSkills = Instance.SkillPlayer
if (!playerSkill.IsDrawing) .Where(p => !p.IsDrawing)
Instance.SkillAction(playerSkill.Skill.ToString(), "WeaponPickup", [@event]); .Select(p => p.Skill.ToString())
.Distinct();
foreach (string skillName in activeSkills)
Instance.SkillAction(skillName, "WeaponPickup", [@event]);
return HookResult.Continue; return HookResult.Continue;
} }
} }
@ -126,9 +146,13 @@ namespace src.player
{ {
lock (setLock) lock (setLock)
{ {
foreach (var playerSkill in Instance.SkillPlayer) var activeSkills = Instance.SkillPlayer
if (!playerSkill.IsDrawing) .Where(p => !p.IsDrawing)
Instance.SkillAction(playerSkill.Skill.ToString(), "WeaponReload", [@event]); .Select(p => p.Skill.ToString())
.Distinct();
foreach (string skillName in activeSkills)
Instance.SkillAction(skillName, "WeaponReload", [@event]);
return HookResult.Continue; return HookResult.Continue;
} }
} }
@ -137,9 +161,13 @@ namespace src.player
{ {
lock (setLock) lock (setLock)
{ {
foreach (var playerSkill in Instance.SkillPlayer) var activeSkills = Instance.SkillPlayer
if (!playerSkill.IsDrawing) .Where(p => !p.IsDrawing)
Instance.SkillAction(playerSkill.Skill.ToString(), "GrenadeThrown", [@event]); .Select(p => p.Skill.ToString())
.Distinct();
foreach (string skillName in activeSkills)
Instance.SkillAction(skillName, "GrenadeThrown", [@event]);
return HookResult.Continue; return HookResult.Continue;
} }
} }
@ -148,9 +176,28 @@ namespace src.player
{ {
lock (setLock) lock (setLock)
{ {
foreach (var playerSkill in Instance.SkillPlayer) var activeSkills = Instance.SkillPlayer
if (!playerSkill.IsDrawing) .Where(p => !p.IsDrawing)
Instance.SkillAction(playerSkill.Skill.ToString(), "BombBeginplant", [@event]); .Select(p => p.Skill.ToString())
.Distinct();
foreach (string skillName in activeSkills)
Instance.SkillAction(skillName, "BombBeginplant", [@event]);
return HookResult.Continue;
}
}
private static HookResult BombAbortplant(EventBombAbortplant @event, GameEventInfo info)
{
lock (setLock)
{
var activeSkills = Instance.SkillPlayer
.Where(p => !p.IsDrawing)
.Select(p => p.Skill.ToString())
.Distinct();
foreach (string skillName in activeSkills)
Instance.SkillAction(skillName, "BombAbortplant", [@event]);
return HookResult.Continue; return HookResult.Continue;
} }
} }
@ -159,9 +206,13 @@ namespace src.player
{ {
lock (setLock) lock (setLock)
{ {
foreach (var playerSkill in Instance.SkillPlayer) var activeSkills = Instance.SkillPlayer
if (!playerSkill.IsDrawing) .Where(p => !p.IsDrawing)
Instance.SkillAction(playerSkill.Skill.ToString(), "BombPlanted", [@event]); .Select(p => p.Skill.ToString())
.Distinct();
foreach (string skillName in activeSkills)
Instance.SkillAction(skillName, "BombPlanted", [@event]);
return HookResult.Continue; return HookResult.Continue;
} }
} }
@ -170,9 +221,13 @@ namespace src.player
{ {
lock (setLock) lock (setLock)
{ {
foreach (var playerSkill in Instance.SkillPlayer) var activeSkills = Instance.SkillPlayer
if (!playerSkill.IsDrawing) .Where(p => !p.IsDrawing)
Instance.SkillAction(playerSkill.Skill.ToString(), "BombBegindefuse", [@event]); .Select(p => p.Skill.ToString())
.Distinct();
foreach (string skillName in activeSkills)
Instance.SkillAction(skillName, "BombBegindefuse", [@event]);
return HookResult.Continue; return HookResult.Continue;
} }
} }
@ -181,9 +236,13 @@ namespace src.player
{ {
lock (setLock) lock (setLock)
{ {
foreach (var playerSkill in Instance.SkillPlayer) var activeSkills = Instance.SkillPlayer
if (!playerSkill.IsDrawing) .Where(p => !p.IsDrawing)
Instance.SkillAction(playerSkill.Skill.ToString(), "DecoyStarted", [@event]); .Select(p => p.Skill.ToString())
.Distinct();
foreach (string skillName in activeSkills)
Instance.SkillAction(skillName, "DecoyStarted", [@event]);
return HookResult.Continue; return HookResult.Continue;
} }
} }
@ -192,9 +251,13 @@ namespace src.player
{ {
lock (setLock) lock (setLock)
{ {
foreach (var playerSkill in Instance.SkillPlayer) var activeSkills = Instance.SkillPlayer
if (!playerSkill.IsDrawing) .Where(p => !p.IsDrawing)
Instance.SkillAction(playerSkill.Skill.ToString(), "DecoyDetonate", [@event]); .Select(p => p.Skill.ToString())
.Distinct();
foreach (string skillName in activeSkills)
Instance.SkillAction(skillName, "DecoyDetonate", [@event]);
return HookResult.Continue; return HookResult.Continue;
} }
} }
@ -203,9 +266,13 @@ namespace src.player
{ {
lock (setLock) lock (setLock)
{ {
foreach (var playerSkill in Instance.SkillPlayer) var activeSkills = Instance.SkillPlayer
if (!playerSkill.IsDrawing) .Where(p => !p.IsDrawing)
Instance.SkillAction(playerSkill.Skill.ToString(), "SmokegrenadeDetonate", [@event]); .Select(p => p.Skill.ToString())
.Distinct();
foreach (string skillName in activeSkills)
Instance.SkillAction(skillName, "SmokegrenadeDetonate", [@event]);
return HookResult.Continue; return HookResult.Continue;
} }
} }
@ -214,9 +281,13 @@ namespace src.player
{ {
lock (setLock) lock (setLock)
{ {
foreach (var playerSkill in Instance.SkillPlayer) var activeSkills = Instance.SkillPlayer
if (!playerSkill.IsDrawing) .Where(p => !p.IsDrawing)
Instance.SkillAction(playerSkill.Skill.ToString(), "SmokegrenadeExpired", [@event]); .Select(p => p.Skill.ToString())
.Distinct();
foreach (string skillName in activeSkills)
Instance.SkillAction(skillName, "SmokegrenadeExpired", [@event]);
return HookResult.Continue; return HookResult.Continue;
} }
} }
@ -225,9 +296,13 @@ namespace src.player
{ {
lock (setLock) lock (setLock)
{ {
foreach (var playerSkill in Instance.SkillPlayer) var activeSkills = Instance.SkillPlayer
if (!playerSkill.IsDrawing) .Where(p => !p.IsDrawing)
Instance.SkillAction(playerSkill.Skill.ToString(), "PlayerHurt", [@event]); .Select(p => p.Skill.ToString())
.Distinct();
foreach (string skillName in activeSkills)
Instance.SkillAction(skillName, "PlayerHurt", [@event]);
return HookResult.Continue; return HookResult.Continue;
} }
} }
@ -236,9 +311,13 @@ namespace src.player
{ {
lock (setLock) lock (setLock)
{ {
foreach (var playerSkill in Instance.SkillPlayer) var activeSkills = Instance.SkillPlayer
if (!playerSkill.IsDrawing) .Where(p => !p.IsDrawing)
Instance.SkillAction(playerSkill.Skill.ToString(), "PlayerJump", [@event]); .Select(p => p.Skill.ToString())
.Distinct();
foreach (string skillName in activeSkills)
Instance.SkillAction(skillName, "PlayerJump", [@event]);
return HookResult.Continue; return HookResult.Continue;
} }
} }
@ -247,9 +326,13 @@ namespace src.player
{ {
lock (setLock) lock (setLock)
{ {
foreach (var playerSkill in Instance.SkillPlayer) var activeSkills = Instance.SkillPlayer
if (!playerSkill.IsDrawing) .Where(p => !p.IsDrawing)
Instance.SkillAction(playerSkill.Skill.ToString(), "PlayerBlind", [@event]); .Select(p => p.Skill.ToString())
.Distinct();
foreach (string skillName in activeSkills)
Instance.SkillAction(skillName, "PlayerBlind", [@event]);
return HookResult.Continue; return HookResult.Continue;
} }
} }
@ -258,9 +341,13 @@ namespace src.player
{ {
lock (setLock) lock (setLock)
{ {
foreach (var playerSkill in Instance.SkillPlayer) var activeSkills = Instance.SkillPlayer
if (!playerSkill.IsDrawing) .Where(p => !p.IsDrawing)
Instance.SkillAction(playerSkill.Skill.ToString(), "OnTakeDamage", [h]); .Select(p => p.Skill.ToString())
.Distinct();
foreach (string skillName in activeSkills)
Instance.SkillAction(skillName, "OnTakeDamage", [h]);
return HookResult.Continue; return HookResult.Continue;
} }
} }
@ -272,9 +359,13 @@ namespace src.player
CBaseTrigger trigger = hook.GetParam<CBaseTrigger>(0); CBaseTrigger trigger = hook.GetParam<CBaseTrigger>(0);
CBaseEntity entity = hook.GetParam<CBaseEntity>(1); CBaseEntity entity = hook.GetParam<CBaseEntity>(1);
foreach (var playerSkill in Instance.SkillPlayer) var activeSkills = Instance.SkillPlayer
if (!playerSkill.IsDrawing) .Where(p => !p.IsDrawing)
Instance.SkillAction(playerSkill.Skill.ToString(), "OnTriggerEnter", [trigger, entity]); .Select(p => p.Skill.ToString())
.Distinct();
foreach (string skillName in activeSkills)
Instance.SkillAction(skillName, "OnTriggerEnter", [trigger, entity]);
return HookResult.Continue; return HookResult.Continue;
} }
} }
@ -286,9 +377,13 @@ namespace src.player
CBaseTrigger trigger = hook.GetParam<CBaseTrigger>(0); CBaseTrigger trigger = hook.GetParam<CBaseTrigger>(0);
CBaseEntity entity = hook.GetParam<CBaseEntity>(1); CBaseEntity entity = hook.GetParam<CBaseEntity>(1);
foreach (var playerSkill in Instance.SkillPlayer) var activeSkills = Instance.SkillPlayer
if (!playerSkill.IsDrawing) .Where(p => !p.IsDrawing)
Instance.SkillAction(playerSkill.Skill.ToString(), "OnTriggerExit", [trigger, entity]); .Select(p => p.Skill.ToString())
.Distinct();
foreach (string skillName in activeSkills)
Instance.SkillAction(skillName, "OnTriggerExit", [trigger, entity]);
return HookResult.Continue; return HookResult.Continue;
} }
} }
@ -297,12 +392,18 @@ namespace src.player
{ {
lock (setLock) lock (setLock)
{ {
foreach (var playerSkill in Instance.SkillPlayer) var activeSkills = Instance.SkillPlayer
if (!playerSkill.IsDrawing) .Where(p => !p.IsDrawing)
if (SkillsInfo.GetValue<bool>(playerSkill.Skill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime()) .Select(p => p.Skill)
return; .Distinct()
.OrderBy(skill => skill.ToString() == "AreaReaper")
.ThenBy(skill => skill.ToString() == "ChillOut");
foreach (var skill in activeSkills)
if (SkillsInfo.GetValue<bool>(skill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime())
continue;
else else
Instance.SkillAction(playerSkill.Skill.ToString(), "OnTick"); Instance.SkillAction(skill.ToString(), "OnTick");
} }
} }
@ -528,9 +629,13 @@ namespace src.player
{ {
lock (setLock) lock (setLock)
{ {
foreach (var playerSkill in Instance.SkillPlayer) var activeSkills = Instance.SkillPlayer
if (!playerSkill.IsDrawing) .Where(p => !p.IsDrawing)
Instance.SkillAction(playerSkill.Skill.ToString(), "PlayerDeath", [@event]); .Select(p => p.Skill.ToString())
.Distinct();
foreach (string skillName in activeSkills)
Instance.SkillAction(skillName, "PlayerDeath", [@event]);
var victim = @event.Userid; var victim = @event.Userid;
var attacker = @event.Attacker; var attacker = @event.Attacker;
@ -562,28 +667,48 @@ namespace src.player
private static void CheckUseSkill(CCSPlayerController player, PlayerButtons pressed, PlayerButtons released) private static void CheckUseSkill(CCSPlayerController player, PlayerButtons pressed, PlayerButtons released)
{ {
if (player == null || !player.IsValid || !player.PawnIsAlive) return;
lock (setLock) lock (setLock)
{ {
string? button = Config.LoadedConfig.AlternativeSkillButton; string? button = Config.LoadedConfig.AlternativeSkillButton;
if (string.IsNullOrEmpty(button) || button.Length < 2) return; if (string.IsNullOrEmpty(button) || button.Length < 2) return;
string buttonName = $"{char.ToUpper(button[0])}{button[1..].ToLower()}"; string buttonName = $"{char.ToUpper(button[0])}{button[1..].ToLower()}";
if (!Enum.TryParse<PlayerButtons>(buttonName, out var skillButton)) return;
if (Enum.TryParse<PlayerButtons>(buttonName, out var skillButton)) if ((pressed & skillButton) == 0) return;
{
if (pressed != skillButton) return;
}
else return;
if (player == null) return;
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo == null || playerInfo.IsDrawing) return; if (playerInfo == null || playerInfo.IsDrawing) return;
if (SkillsInfo.GetValue<bool>(playerInfo.Skill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime()) if (SkillsInfo.GetValue<bool>(playerInfo.Skill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime())
return; return;
var playerPawn = player.PlayerPawn.Value; if (skillButton == PlayerButtons.Use)
if (playerPawn?.CBodyComponent == null) return; {
if (!player.IsValid || !player.PawnIsAlive) return; var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid) return;
if (pawn.AbsOrigin == null || pawn.AbsRotation == null) return;
if (pawn.IsDefusing) return;
Vector eyePos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z);
Vector endPos = eyePos + SkillUtils.GetForwardVector(pawn.EyeAngles) * 80;
ulong mask = pawn.Collision.CollisionAttribute.InteractsWith | (ulong)(Contents.Solid | Contents.Hitbox | Contents.Pickup | Contents.TouchAll | Contents.CarriedObject | Contents.CarriedWeapon | Contents.Debris);
ulong contents = 0;
CGameTrace trace = TraceRay.TraceShape(eyePos, endPos, mask, contents, player);
if (trace.DidHit())
{
var entity = Activator.CreateInstance(typeof(CBaseEntity), trace.HitEntity) as CBaseEntity;
if (entity == null || !entity.IsValid) return;
string designer = entity.DesignerName;
if (designer.Contains("door") || designer.Contains("button") || designer.Contains("weapon") || designer.Contains("blocker")) return;
}
}
Debug.WriteToDebug($"Player {player.PlayerName} used the skill: {playerInfo.Skill} by PlayerButtons: {pressed}"); Debug.WriteToDebug($"Player {player.PlayerName} used the skill: {playerInfo.Skill} by PlayerButtons: {pressed}");
Instance.SkillAction(playerInfo.Skill.ToString(), "UseSkill", [player]); Instance.SkillAction(playerInfo.Skill.ToString(), "UseSkill", [player]);
@ -594,9 +719,13 @@ namespace src.player
{ {
lock (setLock) lock (setLock)
{ {
foreach (var playerSkill in Instance.SkillPlayer) var activeSkills = Instance.SkillPlayer
if (!playerSkill.IsDrawing) .Where(p => !p.IsDrawing)
Instance.SkillAction(playerSkill.Skill.ToString(), "OnEntitySpawned", [entity]); .Select(p => p.Skill.ToString())
.Distinct();
foreach (string skillName in activeSkills)
Instance.SkillAction(skillName, "OnEntitySpawned", [entity]);
} }
} }
@ -722,8 +851,12 @@ namespace src.player
}); });
Debug.WriteToDebug($"Player {skillPlayer.PlayerName} has got the skill \"{player.GetSkillName(randomSkill.Skill)}\"."); Debug.WriteToDebug($"Player {skillPlayer.PlayerName} has got the skill \"{player.GetSkillName(randomSkill.Skill)}\".");
skillPlayer.SkillHudExpired = DateTime.Now.AddSeconds(Config.LoadedConfig.SkillHudDuration);
skillPlayer.SkillDescriptionHudExpired = DateTime.Now.AddSeconds(Config.LoadedConfig.SkillDescriptionDuration); float hudExpired = Config.LoadedConfig.SkillHudDuration;
skillPlayer.SkillHudExpired = hudExpired == -1 ? DateTime.MaxValue : DateTime.Now.AddSeconds(hudExpired);
float descriptionHudExpired = Config.LoadedConfig.SkillHudDuration;
skillPlayer.SkillDescriptionHudExpired = descriptionHudExpired == -1 ? DateTime.MaxValue : DateTime.Now.AddSeconds(descriptionHudExpired);
if (Config.LoadedConfig.TeamMateSkillChatInfo) if (Config.LoadedConfig.TeamMateSkillChatInfo)
{ {
@ -859,9 +992,13 @@ namespace src.player
{ {
lock (setLock) lock (setLock)
{ {
foreach (var playerSkill in Instance.SkillPlayer) var activeSkills = Instance.SkillPlayer
if (!playerSkill.IsDrawing) .Where(p => !p.IsDrawing)
Instance.SkillAction(playerSkill.Skill.ToString(), "CheckTransmit", [infoList]); .Select(p => p.Skill.ToString())
.Distinct();
foreach (string skillName in activeSkills)
Instance.SkillAction(skillName, "CheckTransmit", [infoList]);
} }
} }

View file

@ -121,6 +121,7 @@ namespace src.player
if (string.IsNullOrEmpty(skillLine)) return; if (string.IsNullOrEmpty(skillLine)) return;
if (player == null || !player.IsValid) return; if (player == null || !player.IsValid) return;
if (SkillUtils.HasMenu(player)) return; if (SkillUtils.HasMenu(player)) return;
Event.UpdateSkillHUD(player, infoLine, skillLine, remainingLine, isDescription); Event.UpdateSkillHUD(player, infoLine, skillLine, remainingLine, isDescription);
} }
} }

View file

@ -31,7 +31,12 @@ namespace src.player.skills
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo?.Skill == skillName) if (playerInfo?.Skill == skillName)
if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo))
{
UpdateHUD(player, skillInfo); UpdateHUD(player, skillInfo);
if (skillInfo.Cooldown.AddSeconds(SkillsInfo.GetValue<float>(skillName, "duration")) > DateTime.Now)
LookAtEnemey(player);
}
} }
} }
@ -100,7 +105,7 @@ namespace src.player.skills
foreach (var enemy in Utilities.GetPlayers().Where(p => p.IsValid && p.PawnIsAlive && p.Team != player.Team)) foreach (var enemy in Utilities.GetPlayers().Where(p => p.IsValid && p.PawnIsAlive && p.Team != player.Team))
{ {
var enemyPawn = enemy.PlayerPawn.Value; var enemyPawn = enemy.PlayerPawn.Value;
if (enemyPawn == null || !enemyPawn.IsValid || enemyPawn.AbsOrigin == null) return; if (enemyPawn == null || !enemyPawn.IsValid || enemyPawn.AbsOrigin == null) continue;
double dist = SkillUtils.GetDistance(enemyPawn.AbsOrigin, pawn.AbsOrigin); double dist = SkillUtils.GetDistance(enemyPawn.AbsOrigin, pawn.AbsOrigin);
if (dist < minDist) if (dist < minDist)
@ -112,11 +117,13 @@ namespace src.player.skills
if (closetEnemy != null) if (closetEnemy != null)
{ {
Vector enemyPos = closetEnemy.PlayerPawn.Value!.AbsOrigin!; var enemyPawn = closetEnemy.PlayerPawn.Value;
Vector myPos = pawn.AbsOrigin; if (enemyPawn == null || enemyPawn.AbsOrigin == null) return;
Vector myEyePos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z);
Vector enemyEyePos = new(enemyPawn.AbsOrigin.X, enemyPawn.AbsOrigin.Y, enemyPawn.AbsOrigin.Z + enemyPawn.ViewOffset.Z + SkillsInfo.GetValue<float>(skillName, "offsetZ"));
Vector direction = enemyPos - myPos; Vector direction = enemyEyePos - myEyePos;
QAngle angle = VectorToAngle(direction); QAngle angle = VectorToAngle(direction);
pawn.Look(angle); pawn.Look(angle);
@ -138,9 +145,11 @@ namespace src.player.skills
public DateTime Cooldown { get; set; } public DateTime Cooldown { get; set; }
} }
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#fa7b48", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = true, bool needsTeammates = false, string requiredPermission = "", float cooldown = 5f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#fa7b48", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = true, bool needsTeammates = false, string requiredPermission = "", float cooldown = 20f, float duration = .3f, float offsetZ = 0) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)
{ {
public float Cooldown { get; set; } = cooldown; public float Cooldown { get; set; } = cooldown;
public float Duration { get; set; } = duration;
public float Offset { get; set; } = offsetZ;
} }
} }
} }

View file

@ -1,8 +1,8 @@
using CounterStrikeSharp.API; using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using static src.jRandomSkills;
using src.utils; using src.utils;
using static src.jRandomSkills;
namespace src.player.skills namespace src.player.skills
{ {
@ -21,7 +21,6 @@ namespace src.player.skills
{ {
foreach (var player in Utilities.GetPlayers()) foreach (var player in Utilities.GetPlayers())
SkillUtils.CloseMenu(player); SkillUtils.CloseMenu(player);
Instance.AddTimer(0.1f, EnableBombsite);
} }
public static void TypeSkill(CCSPlayerController player, string[] commands) public static void TypeSkill(CCSPlayerController player, string[] commands)
@ -44,7 +43,9 @@ namespace src.player.skills
var bombTargets = Utilities.FindAllEntitiesByDesignerName<CBombTarget>("func_bomb_target").ToArray(); var bombTargets = Utilities.FindAllEntitiesByDesignerName<CBombTarget>("func_bomb_target").ToArray();
if (bombTargets.Length == 2) if (bombTargets.Length == 2)
{ {
bombTargets[site].AcceptInput("Disable"); bombTargets[site].BombPlantedHere = true;
Utilities.SetStateChanged(bombTargets[site], "CBombTarget", "m_bBombPlantedHere");
playerInfo.SkillUsed = true; playerInfo.SkillUsed = true;
player.PrintToChat($" {ChatColors.Green}{player.GetTranslation("areareaper_site_disabled", (site == 0 ? 'A' : 'B'))}"); player.PrintToChat($" {ChatColors.Green}{player.GetTranslation("areareaper_site_disabled", (site == 0 ? 'A' : 'B'))}");
} }
@ -63,16 +64,43 @@ namespace src.player.skills
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
{ {
SkillUtils.CloseMenu(player); SkillUtils.CloseMenu(player);
Server.NextWorldUpdate(() =>
{
if (Instance.SkillPlayer.FirstOrDefault(p => p.Skill == skillName) != null) return; if (Instance.SkillPlayer.FirstOrDefault(p => p.Skill == skillName) != null) return;
EnableBombsite(); EnableBombsite();
});
} }
private static void EnableBombsite() private static void EnableBombsite()
{ {
var bombTargets = Utilities.FindAllEntitiesByDesignerName<CBombTarget>("func_bomb_target"); var bombTargets = Utilities.FindAllEntitiesByDesignerName<CBombTarget>("func_bomb_target");
foreach (var bombTarget in bombTargets) foreach (var bombTarget in bombTargets)
bombTarget.AcceptInput("Enable"); {
bombTarget.BombPlantedHere = false;
Utilities.SetStateChanged(bombTarget, "CBombTarget", "m_bBombPlantedHere");
}
}
public static void OnTick()
{
var bombTargets = Utilities.FindAllEntitiesByDesignerName<CBombTarget>("func_bomb_target");
foreach (var player in Utilities.GetPlayers().Where(p => p.Team == CsTeam.Terrorist))
{
if (!Instance.IsPlayerValid(player)) continue;
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo?.Skill == null) continue;
var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid) continue;
if (pawn.WeaponServices == null) continue;
var activeWeapon = pawn.WeaponServices.ActiveWeapon.Value;
if (activeWeapon == null || !activeWeapon.IsValid || activeWeapon.DesignerName != "weapon_c4") continue;
if (!pawn.InBombZone && pawn.InBombZoneTrigger)
player.PrintToCenterAlert(player.GetTranslation("areareaper_bombsite_disabled"));
}
} }
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#edf5b5", CsTeam onlyTeam = CsTeam.CounterTerrorist, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "") : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#edf5b5", CsTeam onlyTeam = CsTeam.CounterTerrorist, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "") : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)

View file

@ -2,6 +2,7 @@ using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using src.utils; using src.utils;
using System.Collections.Concurrent;
using static src.jRandomSkills; using static src.jRandomSkills;
namespace src.player.skills namespace src.player.skills
@ -9,16 +10,38 @@ namespace src.player.skills
public class ChillOut : ISkill public class ChillOut : ISkill
{ {
private const Skills skillName = Skills.ChillOut; private const Skills skillName = Skills.ChillOut;
private static readonly ConcurrentDictionary<ulong, float> plantingPlayers = [];
public static void LoadSkill() public static void LoadSkill()
{ {
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color")); SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
} }
public static void NewRound()
{
plantingPlayers.Clear();
}
public static void DisableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
plantingPlayers.TryRemove(player.SteamID, out _);
SkillUtils.ResetPrintHTML(player);
}
public static void BombAbortplant(EventBombAbortplant @event)
{
var user = @event.Userid;
if (user == null || !user.IsValid || !user.PawnIsAlive) return;
plantingPlayers.TryRemove(user.SteamID, out _);
SkillUtils.ResetPrintHTML(user);
}
public static void BombBeginplant(EventBombBeginplant @event) public static void BombBeginplant(EventBombBeginplant @event)
{ {
var player = @event.Userid; var player = @event.Userid;
if (!Instance.IsPlayerValid(player)) return; if (!Instance.IsPlayerValid(player)) return;
plantingPlayers.TryAdd(player!.SteamID, Server.CurrentTime);
var anyChillOut = Instance.SkillPlayer.FirstOrDefault(p => p.Skill == skillName); var anyChillOut = Instance.SkillPlayer.FirstOrDefault(p => p.Skill == skillName);
if (anyChillOut != null) if (anyChillOut != null)
@ -33,6 +56,42 @@ namespace src.player.skills
} }
} }
public static void BombPlanted(EventBombPlanted @event)
{
var player = @event.Userid;
if (!Instance.IsPlayerValid(player)) return;
plantingPlayers.TryRemove(player!.SteamID, out _);
SkillUtils.ResetPrintHTML(player);
}
public static void OnTick()
{
float currentTime = Server.CurrentTime;
float extraTime = SkillsInfo.GetValue<float>(skillName, "bombArmedTime");
foreach (var player in Utilities.GetPlayers().Where(p => p.Team == CsTeam.Terrorist))
{
if (!Instance.IsPlayerValid(player)) continue;
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo == null) continue;
var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid) continue;
if (pawn.WeaponServices == null) continue;
var activeWeapon = pawn.WeaponServices.ActiveWeapon.Value;
if (activeWeapon == null || !activeWeapon.IsValid || activeWeapon.DesignerName != "weapon_c4") continue;
if (plantingPlayers.TryGetValue(player.SteamID, out float plantTime))
{
float remaining = plantTime + extraTime - currentTime;
playerInfo.PrintHTML = $"{player.GetTranslation("planter_planting", $"<font color='#00FF00'>{Math.Max(0, remaining):0.0}s</font>")}";
player.PrintToCenter("");
}
}
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#343deb", CsTeam onlyTeam = CsTeam.CounterTerrorist, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float bombArmedTime = 10f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#343deb", CsTeam onlyTeam = CsTeam.CounterTerrorist, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float bombArmedTime = 10f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)
{ {
public float BombArmedTime { get; set; } = bombArmedTime; public float BombArmedTime { get; set; } = bombArmedTime;

View file

@ -11,7 +11,7 @@ namespace src.player.skills
public class HomingNades : ISkill public class HomingNades : ISkill
{ {
private const Skills skillName = Skills.HomingNades; private const Skills skillName = Skills.HomingNades;
private readonly static ConcurrentDictionary<uint, (Vector, double)> nades = []; private readonly static ConcurrentDictionary<uint, Vector> nades = [];
public static void LoadSkill() public static void LoadSkill()
{ {
@ -30,7 +30,7 @@ namespace src.player.skills
foreach (var index in nades.Keys.ToList()) foreach (var index in nades.Keys.ToList())
{ {
if (!nades.TryGetValue(index, out var data)) continue; if (!nades.TryGetValue(index, out var data)) continue;
(Vector oldPos, double createdTime) = data; Vector oldPos = data;
var nade = Utilities.GetEntityFromIndex<CBaseCSGrenadeProjectile>((int)index); var nade = Utilities.GetEntityFromIndex<CBaseCSGrenadeProjectile>((int)index);
if (nade == null || !nade.IsValid || nade.AbsOrigin == null) if (nade == null || !nade.IsValid || nade.AbsOrigin == null)
@ -43,14 +43,13 @@ namespace src.player.skills
double distanceMoved = SkillUtils.GetDistance(currentPos, oldPos); double distanceMoved = SkillUtils.GetDistance(currentPos, oldPos);
Vector calculatedVelocity = CalculateVelocity(nade, nade.TeamNum); Vector calculatedVelocity = CalculateVelocity(nade, nade.TeamNum);
Server.PrintToChatAll($"Dist: {distanceMoved}, vel: {calculatedVelocity}"); bool isZero = calculatedVelocity.IsZero();
if (distanceMoved < 4 || calculatedVelocity.IsZero()) if (distanceMoved < 4 || isZero)
{ {
Server.PrintToChatAll($"Short, {Server.TickedTime} -> {createdTime + 3}, {createdTime + 3 - Server.TickedTime}s"); nade.DetonateTime = isZero ? 0 : nade.CreateTime + 3;
nade.DetonateTime = (float)createdTime + 3;
Utilities.SetStateChanged(nade, "CBaseGrenade", "m_flDetonateTime"); Utilities.SetStateChanged(nade, "CBaseGrenade", "m_flDetonateTime");
nades.TryRemove(index, out _); nades.TryRemove(index, out _);
continue; continue;
} }
@ -63,7 +62,7 @@ namespace src.player.skills
if (speed > maxVelocity) if (speed > maxVelocity)
newVelocity *= (maxVelocity / speed); newVelocity *= (maxVelocity / speed);
nades[index] = (currentPos, createdTime); nades[index] = currentPos;
nade.Teleport(null, null, newVelocity); nade.Teleport(null, null, newVelocity);
} }
} }
@ -84,9 +83,6 @@ namespace src.player.skills
double dist = SkillUtils.GetDistance(nadePos, pawn.AbsOrigin); double dist = SkillUtils.GetDistance(nadePos, pawn.AbsOrigin);
if (dist < SkillsInfo.GetValue<float>(skillName, "detonationRange")) if (dist < SkillsInfo.GetValue<float>(skillName, "detonationRange"))
{ {
nade.DetonateTime = 0;
Utilities.SetStateChanged(nade, "CBaseGrenade", "m_flDetonateTime");
nades.TryRemove(nade.Index, out _); nades.TryRemove(nade.Index, out _);
return Vector.Zero; return Vector.Zero;
} }
@ -134,10 +130,15 @@ namespace src.player.skills
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo?.Skill != skillName) return; if (playerInfo?.Skill != skillName) return;
grenade.DetonateTime = (float)Server.TickedTime + 6;
Vector pos = new(grenade.AbsOrigin?.X, grenade.AbsOrigin?.Y, grenade.AbsOrigin?.Z); Vector pos = new(grenade.AbsOrigin?.X, grenade.AbsOrigin?.Y, grenade.AbsOrigin?.Z);
nades.TryAdd(grenade.Index, (pos, Server.TickedTime)); nades.TryAdd(grenade.Index, pos);
Server.NextWorldUpdate(() =>
{
if (grenade == null || !grenade.IsValid) return;
grenade.DetonateTime += 100f;
Utilities.SetStateChanged(grenade, "CBaseGrenade", "m_flDetonateTime");
});
} }
public static void EnableSkill(CCSPlayerController player) public static void EnableSkill(CCSPlayerController player)

View file

@ -0,0 +1,113 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Entities.Constants;
using CounterStrikeSharp.API.Modules.Utils;
using src.utils;
using System.Collections.Concurrent;
using static src.jRandomSkills;
namespace src.player.skills
{
public class Miner : ISkill
{
private const Skills skillName = Skills.Miner;
private readonly static ConcurrentDictionary<uint, byte> nades = [];
public static void LoadSkill()
{
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
}
public static void NewRound()
{
nades.Clear();
}
public static void OnTick()
{
if (Server.TickCount % 10 != 0) return;
float detonationRange = SkillsInfo.GetValue<float>(skillName, "detonationRange");
float currentTime = Server.CurrentTime;
foreach (var index in nades.Keys.ToList())
{
var nade = Utilities.GetEntityFromIndex<CBaseCSGrenadeProjectile>((int)index);
if (nade == null || !nade.IsValid || nade.AbsOrigin == null)
{
nades.TryRemove(index, out _);
continue;
}
if (nade.CreateTime + 3 > currentTime) return;
Vector currentPos = new(nade.AbsOrigin.X, nade.AbsOrigin.Y, nade.AbsOrigin.Z);
foreach (var enemy in Utilities.GetPlayers().Where(p => p.IsValid && p.PawnIsAlive && p.TeamNum != nade.TeamNum))
{
var enemyPawn = enemy.PlayerPawn.Value;
if (enemyPawn == null || !enemyPawn.IsValid || enemyPawn.AbsOrigin == null) continue;
Vector enemyPos = new(enemyPawn.AbsOrigin.X, enemyPawn.AbsOrigin.Y, enemyPawn.AbsOrigin.Z);
double distance = SkillUtils.GetDistance(currentPos, enemyPos);
if (distance <= detonationRange)
{
Detonate(nade);
nades.TryRemove(index, out _);
break;
}
}
}
}
private static void Detonate(CBaseCSGrenadeProjectile grenade)
{
if (grenade == null || !grenade.IsValid || grenade.AbsOrigin == null) return;
Vector position = grenade.AbsOrigin;
position.Z += 60;
grenade.Teleport(position);
grenade.EmitSound("IncGrenade.Bounce_M");
grenade.DetonateTime = Server.CurrentTime + .5f;
Utilities.SetStateChanged(grenade, "CBaseGrenade", "m_flDetonateTime");
}
public static void OnEntitySpawned(CEntityInstance @event)
{
var name = @event.DesignerName;
if (name != "hegrenade_projectile") return;
var grenade = @event.As<CBaseCSGrenadeProjectile>();
if (grenade == null || !grenade.IsValid) return;
if (grenade.OwnerEntity.Value == null || !grenade.OwnerEntity.Value.IsValid) return;
var pawn = grenade.OwnerEntity.Value.As<CCSPlayerPawn>();
if (pawn.Controller.Value == null || !pawn.Controller.Value.IsValid) return;
var player = pawn.Controller.Value.As<CCSPlayerController>();
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo?.Skill != skillName) return;
nades.TryAdd(grenade.Index, 0);
Server.NextWorldUpdate(() =>
{
if (grenade == null || !grenade.IsValid) return;
grenade.DetonateTime = float.MaxValue;
Utilities.SetStateChanged(grenade, "CBaseGrenade", "m_flDetonateTime");
});
}
public static void EnableSkill(CCSPlayerController player)
{
SkillUtils.TryGiveWeapon(player, CsItem.HEGrenade);
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#adf542", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float detonationRange = 130) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)
{
public float DetonationRange { get; set; } = detonationRange;
}
}
}

View file

@ -1,7 +1,9 @@
using CounterStrikeSharp.API; using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using src.utils; using src.utils;
using System.Collections.Concurrent;
using static src.jRandomSkills; using static src.jRandomSkills;
using Vector = CounterStrikeSharp.API.Modules.Utils.Vector; using Vector = CounterStrikeSharp.API.Modules.Utils.Vector;
@ -11,20 +13,37 @@ namespace src.player.skills
{ {
private const Skills skillName = Skills.Muhammed; private const Skills skillName = Skills.Muhammed;
private static readonly QAngle angle = new(10, -5, 9); private static readonly QAngle angle = new(10, -5, 9);
private static readonly ConcurrentDictionary<int, byte> nades = [];
public static void LoadSkill() public static void LoadSkill()
{ {
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color")); SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
} }
public static void NewRound()
{
nades.Clear();
}
public static void PlayerDeath(EventPlayerDeath @event) public static void PlayerDeath(EventPlayerDeath @event)
{ {
var player = @event.Userid; var player = @event.Userid;
if (!IsDeadPlayerValid(player)) return; if (!IsDeadPlayerValid(player)) return;
CsTeam lastTeam = player!.Team;
Server.NextWorldUpdate(() =>
{
if (player == null || !player.IsValid || player.Team != lastTeam) return;
var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid || pawn.Health == pawn.MaxHealth) return;
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID);
if (playerInfo?.Skill == skillName) if (playerInfo?.Skill == skillName)
SpawnExplosion(player!); SpawnExplosion(player!);
});
} }
private static void SpawnExplosion(CCSPlayerController player) private static void SpawnExplosion(CCSPlayerController player)
@ -32,7 +51,7 @@ namespace src.player.skills
var pawn = player.PlayerPawn.Value; var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) return; if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) return;
Vector pos = pawn.AbsOrigin; Vector pos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z);
pos.Z += 10; pos.Z += 10;
SkillUtils.CreateHEGrenadeProjectile(pos, angle, new Vector(0, 0, -10), player.TeamNum); SkillUtils.CreateHEGrenadeProjectile(pos, angle, new Vector(0, 0, -10), player.TeamNum);
@ -44,6 +63,8 @@ namespace src.player.skills
var fileNames = new[] { "radiobotfallback01", "radiobotfallback02", "radiobotfallback04" }; var fileNames = new[] { "radiobotfallback01", "radiobotfallback02", "radiobotfallback04" };
var randomFile = fileNames[new Random().Next(fileNames.Length)]; var randomFile = fileNames[new Random().Next(fileNames.Length)];
player.ExecuteClientCommand($"play vo/agents/balkan/{randomFile}.vsnd"); player.ExecuteClientCommand($"play vo/agents/balkan/{randomFile}.vsnd");
nades.AddOrUpdate(Server.TickCount, player.TeamNum, (_, _) => player.TeamNum);
} }
public static void OnEntitySpawned(CEntityInstance entity) public static void OnEntitySpawned(CEntityInstance entity)
@ -53,6 +74,8 @@ namespace src.player.skills
var heProjectile = entity.As<CBaseCSGrenadeProjectile>(); var heProjectile = entity.As<CBaseCSGrenadeProjectile>();
if (heProjectile == null || !heProjectile.IsValid || heProjectile.AbsRotation == null) return; if (heProjectile == null || !heProjectile.IsValid || heProjectile.AbsRotation == null) return;
int lastTick = Server.TickCount;
Server.NextFrame(() => Server.NextFrame(() =>
{ {
if (heProjectile == null || !heProjectile.IsValid) return; if (heProjectile == null || !heProjectile.IsValid) return;
@ -63,9 +86,37 @@ namespace src.player.skills
heProjectile.Damage = SkillsInfo.GetValue<int>(skillName, "explosionDamage"); heProjectile.Damage = SkillsInfo.GetValue<int>(skillName, "explosionDamage");
heProjectile.DmgRadius = SkillsInfo.GetValue<float>(skillName, "explosionRadius"); heProjectile.DmgRadius = SkillsInfo.GetValue<float>(skillName, "explosionRadius");
heProjectile.DetonateTime = 0; heProjectile.DetonateTime = 0;
if (nades.TryRemove(lastTick, out byte teamNum))
heProjectile.Globalname = $"muhammed_team_{teamNum}_{heProjectile.Index}";
}); });
} }
public static void OnTakeDamage(DynamicHook h)
{
CEntityInstance param = h.GetParam<CEntityInstance>(0);
CTakeDamageInfo param2 = h.GetParam<CTakeDamageInfo>(1);
if (param == null || param.Entity == null || param2 == null) return;
var nade = param2.Attacker.Value;
if (nade == null || !nade.IsValid) return;
if (nade.DesignerName != "hegrenade_projectile") return;
if (string.IsNullOrEmpty(nade.Globalname) || !nade.Globalname.StartsWith("muhammed_team_")) return;
if (!int.TryParse(nade.Globalname.Split('_')[2], out int nadeTeam)) return;
CCSPlayerPawn victimPawn = new(param.Handle);
if (victimPawn.DesignerName != "player") return;
if (victimPawn == null || victimPawn.Controller?.Value == null) return;
if (victimPawn.TeamNum != nadeTeam) return;
float reduction = SkillsInfo.GetValue<float>(skillName, "dmgReductionForTeamates");
param2.Damage *= 1f - Math.Clamp(reduction, 0f, 1f);
}
private static bool NearlyEquals(float a, float b, float epsilon = 0.001f) => Math.Abs(a - b) < epsilon; private static bool NearlyEquals(float a, float b, float epsilon = 0.001f) => Math.Abs(a - b) < epsilon;
private static bool IsDeadPlayerValid(CCSPlayerController? player) private static bool IsDeadPlayerValid(CCSPlayerController? player)
@ -73,12 +124,11 @@ namespace src.player.skills
return player != null && player.IsValid && player.PlayerPawn?.Value != null; return player != null && player.IsValid && player.PlayerPawn?.Value != null;
} }
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#F5CB42", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float explosionRadius = 500.0f, int explosionDamage = 999, float dmgReductionForTeamates = .5f, bool explosionAfterWorldDeath = true) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#F5CB42", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float explosionRadius = 500.0f, int explosionDamage = 999, float dmgReductionForTeamates = .5f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)
{ {
public float ExplosionRadius { get; set; } = explosionRadius; public float ExplosionRadius { get; set; } = explosionRadius;
public int ExplosionDamage { get; set; } = explosionDamage; public int ExplosionDamage { get; set; } = explosionDamage;
public float DmgReductionForTeamates { get; set; } = dmgReductionForTeamates; public float DmgReductionForTeamates { get; set; } = dmgReductionForTeamates;
public bool ExplosionAfterWorldDeath { get; set; } = explosionAfterWorldDeath;
} }
} }

View file

@ -3,6 +3,7 @@ using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Memory;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using src.utils; using src.utils;
using System.Collections.Concurrent;
using static src.jRandomSkills; using static src.jRandomSkills;
namespace src.player.skills namespace src.player.skills
@ -10,42 +11,91 @@ namespace src.player.skills
public class Planter : ISkill public class Planter : ISkill
{ {
private const Skills skillName = Skills.Planter; private const Skills skillName = Skills.Planter;
private static readonly ConcurrentDictionary<ulong, float> plantingPlayers = [];
public static void LoadSkill() public static void LoadSkill()
{ {
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color")); SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
} }
public static void BombBeginplant(EventBombBeginplant @event)
{
var user = @event.Userid;
if (user == null || !user.IsValid || !user.PawnIsAlive) return;
plantingPlayers.TryAdd(user.SteamID, Server.CurrentTime);
}
public static void BombAbortplant(EventBombAbortplant @event)
{
var user = @event.Userid;
if (user == null || !user.IsValid || !user.PawnIsAlive) return;
plantingPlayers.TryRemove(user.SteamID, out _);
SkillUtils.ResetPrintHTML(user);
}
public static void BombPlanted(EventBombPlanted @event) public static void BombPlanted(EventBombPlanted @event)
{ {
var player = @event.Userid; var player = @event.Userid;
if (!Instance.IsPlayerValid(player)) return; if (!Instance.IsPlayerValid(player)) return;
plantingPlayers.TryRemove(player!.SteamID, out _);
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID);
if (playerInfo?.Skill != skillName) return; if (playerInfo?.Skill != skillName) return;
playerInfo.PrintHTML = null;
var plantedBomb = Utilities.FindAllEntitiesByDesignerName<CPlantedC4>("planted_c4").FirstOrDefault(); var plantedBomb = Utilities.FindAllEntitiesByDesignerName<CPlantedC4>("planted_c4").FirstOrDefault();
if (plantedBomb != null) if (plantedBomb != null)
Server.NextFrame(() => plantedBomb.C4Blow = (float)Server.EngineTime + SkillsInfo.GetValue<int>(skillName, "extraC4BlowTime")); Server.NextFrame(() => plantedBomb.C4Blow = Server.CurrentTime + SkillsInfo.GetValue<int>(skillName, "extraC4BlowTime"));
player!.PrintToCenterAlert(player.GetTranslation("bombplanted", SkillsInfo.GetValue<int>(skillName, "extraC4BlowTime"))); foreach (var p in Utilities.GetPlayers().Where(p => p.IsValid && p.PawnIsAlive))
p.PrintToCenterAlert(p.GetTranslation("bombplanted", SkillsInfo.GetValue<int>(skillName, "extraC4BlowTime")));
}
public static void NewRound()
{
foreach (var player in Utilities.GetPlayers())
DisableSkill(player);
plantingPlayers.Clear();
} }
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
{ {
if (!Instance.IsPlayerValid(player)) return; if (player == null || !player.IsValid) return;
Schema.SetSchemaValue<bool>(player!.PlayerPawn.Value!.Handle, "CCSPlayerPawn", "m_bInBombZone", false); plantingPlayers.TryRemove(player.SteamID, out _);
SkillUtils.ResetPrintHTML(player);
var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid) return;
Schema.SetSchemaValue<bool>(pawn!.Handle, "CCSPlayerPawn", "m_bInBombZone", false);
} }
public static void OnTick() public static void OnTick()
{ {
foreach (var player in Utilities.GetPlayers()) float currentTime = Server.CurrentTime;
foreach (var player in Utilities.GetPlayers().Where(p => p.Team == CsTeam.Terrorist))
{ {
if (!Instance.IsPlayerValid(player)) continue; if (!Instance.IsPlayerValid(player)) continue;
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo?.Skill == skillName) var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
Schema.SetSchemaValue<bool>(player!.PlayerPawn.Value!.Handle, "CCSPlayerPawn", "m_bInBombZone", true); if (playerInfo?.Skill != skillName) continue;
var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid) continue;
if (pawn.WeaponServices == null) continue;
var activeWeapon = pawn.WeaponServices.ActiveWeapon.Value;
if (activeWeapon == null || !activeWeapon.IsValid || activeWeapon.DesignerName != "weapon_c4") continue;
pawn.InBombZone = true;
Schema.SetSchemaValue<bool>(pawn.Handle, "CCSPlayerPawn", "m_bInBombZone", true);
if (plantingPlayers.TryGetValue(player.SteamID, out float plantTime))
{
float remaining = plantTime + 3f - currentTime;
playerInfo.PrintHTML = $"{player.GetTranslation("planter_planting", $"<font color='#00FF00'>{Math.Max(0, remaining):0.0}s</font>")}";
player.PrintToCenter("");
}
} }
} }

View file

@ -61,6 +61,8 @@ namespace src.player.skills
foreach (var item in noSpace) foreach (var item in noSpace)
if (item.Value >= Server.TickCount) if (item.Value >= Server.TickCount)
UpdateHUD(item.Key); UpdateHUD(item.Key);
else
SkillUtils.ResetPrintHTML(item.Key);
} }
private static void UpdateHUD(CCSPlayerController player) private static void UpdateHUD(CCSPlayerController player)
@ -75,11 +77,40 @@ namespace src.player.skills
var pawn = player.PlayerPawn.Value; var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid) return false; if (pawn == null || !pawn.IsValid) return false;
Vector s = startPos + new Vector(0, 0, pawn.ViewOffset.Z / 2);
Vector e = endPos + new Vector(0, 0, pawn.ViewOffset.Z / 2);
ulong mask = pawn.Collision.CollisionAttribute.InteractsWith; ulong mask = pawn.Collision.CollisionAttribute.InteractsWith;
ulong contents = pawn.Collision.CollisionGroup; ulong contents = pawn.Collision.CollisionGroup;
CGameTrace trace = TraceRay.TraceShape(startPos, endPos, mask, contents, player); CGameTrace trace = TraceRay.TraceShape(startPos, endPos, mask, contents, player);
return !trace.HitWorld(out _); if (trace.DidHit()) return false;
return IsPositionSafe(player, endPos);
}
private static bool IsPositionSafe(CCSPlayerController player, Vector pos)
{
var playerPawn = player.PlayerPawn.Value;
if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return false;
float footHeight = 0;
float headHeight = 70;
float innerDist = 12;
ulong mask = playerPawn.Collision.CollisionAttribute.InteractsWith;
ulong contents = playerPawn.Collision.CollisionGroup;
Vector s1 = new(pos.X - innerDist, pos.Y - innerDist, pos.Z + footHeight);
Vector e1 = new(pos.X + innerDist, pos.Y + innerDist, pos.Z + headHeight);
CGameTrace t1 = TraceRay.TraceShape(s1, e1, mask, contents, player);
if (t1.DidHit() || t1.AllSolid) return false;
Vector s2 = new(pos.X + innerDist, pos.Y - innerDist, pos.Z + footHeight);
Vector e2 = new(pos.X - innerDist, pos.Y + innerDist, pos.Z + headHeight);
CGameTrace t2 = TraceRay.TraceShape(s2, e2, mask, contents, player);
if (t2.DidHit() || t2.AllSolid) return false;
return true;
} }
private static void TeleportAttackerBehindVictim(CCSPlayerController attacker, CCSPlayerController victim) private static void TeleportAttackerBehindVictim(CCSPlayerController attacker, CCSPlayerController victim)
@ -89,22 +120,29 @@ namespace src.player.skills
if (victimPawn == null || attackerPawn == null || victimPawn.AbsOrigin == null || victimPawn.AbsRotation == null) return; if (victimPawn == null || attackerPawn == null || victimPawn.AbsOrigin == null || victimPawn.AbsRotation == null) return;
QAngle victimAngles = victimPawn.AbsRotation; Vector victimPos = new(victimPawn.AbsOrigin.X, victimPawn.AbsOrigin.Y, victimPawn.AbsOrigin.Z);
Vector victimEyePos = new(victimPawn.AbsOrigin.X, victimPawn.AbsOrigin.Y, victimPawn.AbsOrigin.Z + victimPawn.ViewOffset.Z); QAngle victimAngles = new(victimPawn.AbsRotation.X, victimPawn.AbsRotation.Y, victimPawn.AbsRotation.Z);
int[] angles = [0, 90, -90]; float distance = SkillsInfo.GetValue<float>(skillName, "teleportDistance");
int[] angles = [0, 90, -90];
bool teleported = false; bool teleported = false;
foreach (int extraAngle in angles) foreach (int extraAngle in angles)
{ {
QAngle newAngle = new(victimAngles.X, victimAngles.Y + extraAngle, victimAngles.Z); QAngle targetAngle = new(0, victimAngles.Y + extraAngle, 0);
Vector behindPosition = victimEyePos - SkillUtils.GetForwardVector(newAngle) * SkillsInfo.GetValue<float>(skillName, "teleportDistance"); Vector direction = SkillUtils.GetForwardVector(targetAngle);
if (!CheckTeleport(victim, victimEyePos, behindPosition)) continue; Vector targetPos = victimPos - (direction * distance);
attackerPawn.Teleport(behindPosition, newAngle, new(0, 0, 0));
if (CheckTeleport(victim, victimPos, targetPos))
{
attackerPawn.Teleport(targetPos, targetAngle, Vector.Zero);
teleported = true; teleported = true;
break; break;
} }
}
if (!teleported) if (!teleported)
noSpace.AddOrUpdate(attacker, Server.TickCount + (64 * 2), (k, v) => Server.TickCount + (64 * 2)); noSpace.AddOrUpdate(attacker, Server.TickCount + (64 * 2), (_, _) => Server.TickCount + (64 * 2));
} }
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#4d4d4d", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float teleportDistance = 100f, float chanceFrom = .3f, float chanceTo = .45f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#4d4d4d", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float teleportDistance = 100f, float chanceFrom = .3f, float chanceTo = .45f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)

View file

@ -25,9 +25,10 @@ namespace src.player.skills
var plantedBomb = Utilities.FindAllEntitiesByDesignerName<CPlantedC4>("planted_c4").FirstOrDefault(); var plantedBomb = Utilities.FindAllEntitiesByDesignerName<CPlantedC4>("planted_c4").FirstOrDefault();
if (plantedBomb != null) if (plantedBomb != null)
Server.NextFrame(() => plantedBomb.C4Blow = (float)Server.EngineTime + SkillsInfo.GetValue<int>(skillName, "detonationTime")); Server.NextFrame(() => plantedBomb.C4Blow = Server.CurrentTime + SkillsInfo.GetValue<int>(skillName, "detonationTime"));
player!.PrintToCenterAlert(player.GetTranslation("bombplanted", SkillsInfo.GetValue<int>(skillName, "detonationTime"))); foreach (var p in Utilities.GetPlayers().Where(p => p.IsValid && p.PawnIsAlive))
p.PrintToCenterAlert(p.GetTranslation("bombplanted", SkillsInfo.GetValue<int>(skillName, "detonationTime")));
} }
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#f5b74c", CsTeam onlyTeam = CsTeam.Terrorist, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int detonationTime = 20) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#f5b74c", CsTeam onlyTeam = CsTeam.Terrorist, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int detonationTime = 20) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)

View file

@ -62,7 +62,6 @@ namespace src.player.skills
return; return;
} }
Server.PrintToChatAll("Create Smoke");
SkillUtils.CreateSmokeGrenadeProjectile(pos, QAngle.Zero, Vector.Zero, player.TeamNum); SkillUtils.CreateSmokeGrenadeProjectile(pos, QAngle.Zero, Vector.Zero, player.TeamNum);
}, TimerFlags.REPEAT | TimerFlags.STOP_ON_MAPCHANGE); }, TimerFlags.REPEAT | TimerFlags.STOP_ON_MAPCHANGE);

View file

@ -165,8 +165,7 @@ namespace src.player.skills
weaponToGive = weapon_awp + "_script"; weaponToGive = weapon_awp + "_script";
} }
Server.NextFrame(() => Instance.AddTimer(.15f, () => {
{
if (player != null && player.IsValid && player.PlayerPawn.Value != null && player.PlayerPawn.Value.IsValid) if (player != null && player.IsValid && player.PlayerPawn.Value != null && player.PlayerPawn.Value.IsValid)
{ {
var createdWeapon = player.PlayerPawn.Value?.ItemServices?.As<CCSPlayer_ItemServices>().GiveNamedItem<CEntityInstance>(weaponToGive.Replace("_script", "")); var createdWeapon = player.PlayerPawn.Value?.ItemServices?.As<CCSPlayer_ItemServices>().GiveNamedItem<CEntityInstance>(weaponToGive.Replace("_script", ""));
@ -190,7 +189,7 @@ namespace src.player.skills
DeleteDroppedAWP(player); DeleteDroppedAWP(player);
isProcessing.TryRemove(steamID, out _); isProcessing.TryRemove(steamID, out _);
}); }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
} }
catch { catch {
isProcessing.TryRemove(steamID, out _); isProcessing.TryRemove(steamID, out _);

View file

@ -30,8 +30,7 @@ namespace src.player.skills
{ {
if (bombPlanted) return; if (bombPlanted) return;
var name = entity.DesignerName; var name = entity.DesignerName;
if (!name.EndsWith("_projectile")) if (!name.EndsWith("_projectile")) return;
return;
var grenade = entity.As<CBaseCSGrenadeProjectile>(); var grenade = entity.As<CBaseCSGrenadeProjectile>();
if (grenade.OwnerEntity.Value == null || !grenade.OwnerEntity.Value.IsValid) return; if (grenade.OwnerEntity.Value == null || !grenade.OwnerEntity.Value.IsValid) return;

View file

@ -170,8 +170,9 @@ namespace src.utils
SkillsListCommand = new NormalCommand("supermoc, skille, listamocy, supermoce, skills, listaHabilidades, habilidades, 技能列表, 超能力列表", "@jRandomSkills/admin"), SkillsListCommand = new NormalCommand("supermoc, skille, listamocy, supermoce, skills, listaHabilidades, habilidades, 技能列表, 超能力列表", "@jRandomSkills/admin"),
UseSkillCommand = new NormalCommand("t, useSkill, usarHabilidade, 技能使用, 使用技能", "@jRandomSkills/admin"), UseSkillCommand = new NormalCommand("t, useSkill, usarHabilidade, 技能使用, 使用技能", "@jRandomSkills/admin"),
HealCommand = new NormalCommand("heal, ulecz, curar, tratar, 治疗, 治愈", "@jRandomSkills/admin"), HealCommand = new NormalCommand("heal, ulecz, curar, tratar, 治疗, 治愈", "@jRandomSkills/admin"),
HealthCommand = new NormalCommand("sethealth, health", "@jRandomSkills/admin"), HealthCommand = new NormalCommand("sethealth, set_health, health", "@jRandomSkills/admin"),
PlantedBomb = new NormalCommand("plantedbomb, bomb", "@jRandomSkills/admin"), PlantedBomb = new NormalCommand("plantedbomb, planted_bomb, bomb", "@jRandomSkills/admin"),
BotPlace = new NormalCommand("botplace, bot_place", "@jRandomSkills/admin"),
ConsoleCommand = new NormalCommand("console, sv, 控制台, 服务器", "@jRandomSkills/owner"), ConsoleCommand = new NormalCommand("console, sv, 控制台, 服务器", "@jRandomSkills/owner"),
HudCommand = new NormalCommand("hud, hood", ""), HudCommand = new NormalCommand("hud, hood", ""),
SetStaticSkillCommand = new NormalCommand("ustawstatycznyskill, ustaw_statyczny_skill, setstaticskill, set_static_skill", "@jRandomSkills/admin"), SetStaticSkillCommand = new NormalCommand("ustawstatycznyskill, ustaw_statyczny_skill, setstaticskill, set_static_skill", "@jRandomSkills/admin"),
@ -250,6 +251,7 @@ namespace src.utils
public required NormalCommand HealCommand { get; set; } public required NormalCommand HealCommand { get; set; }
public required NormalCommand HealthCommand { get; set; } public required NormalCommand HealthCommand { get; set; }
public required NormalCommand PlantedBomb { get; set; } public required NormalCommand PlantedBomb { get; set; }
public required NormalCommand BotPlace { get; set; }
public required NormalCommand ConsoleCommand { get; set; } public required NormalCommand ConsoleCommand { get; set; }
public required NormalCommand HudCommand { get; set; } public required NormalCommand HudCommand { get; set; }
public required NormalCommand SetStaticSkillCommand { get; set; } public required NormalCommand SetStaticSkillCommand { get; set; }