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:
parent
8634665983
commit
a8890bde6a
22 changed files with 669 additions and 149 deletions
|
|
@ -1,7 +1,9 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using src.utils;
|
||||
using System.Collections.Concurrent;
|
||||
using static src.jRandomSkills;
|
||||
using Vector = CounterStrikeSharp.API.Modules.Utils.Vector;
|
||||
|
||||
|
|
@ -11,20 +13,37 @@ namespace src.player.skills
|
|||
{
|
||||
private const Skills skillName = Skills.Muhammed;
|
||||
private static readonly QAngle angle = new(10, -5, 9);
|
||||
private static readonly ConcurrentDictionary<int, byte> nades = [];
|
||||
|
||||
public static void LoadSkill()
|
||||
{
|
||||
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
|
||||
}
|
||||
|
||||
public static void NewRound()
|
||||
{
|
||||
nades.Clear();
|
||||
}
|
||||
|
||||
public static void PlayerDeath(EventPlayerDeath @event)
|
||||
{
|
||||
var player = @event.Userid;
|
||||
if (!IsDeadPlayerValid(player)) return;
|
||||
|
||||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID);
|
||||
if (playerInfo?.Skill == skillName)
|
||||
SpawnExplosion(player!);
|
||||
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);
|
||||
if (playerInfo?.Skill == skillName)
|
||||
SpawnExplosion(player!);
|
||||
});
|
||||
}
|
||||
|
||||
private static void SpawnExplosion(CCSPlayerController player)
|
||||
|
|
@ -32,7 +51,7 @@ namespace src.player.skills
|
|||
var pawn = player.PlayerPawn.Value;
|
||||
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;
|
||||
|
||||
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 randomFile = fileNames[new Random().Next(fileNames.Length)];
|
||||
player.ExecuteClientCommand($"play vo/agents/balkan/{randomFile}.vsnd");
|
||||
|
||||
nades.AddOrUpdate(Server.TickCount, player.TeamNum, (_, _) => player.TeamNum);
|
||||
}
|
||||
|
||||
public static void OnEntitySpawned(CEntityInstance entity)
|
||||
|
|
@ -53,6 +74,8 @@ namespace src.player.skills
|
|||
var heProjectile = entity.As<CBaseCSGrenadeProjectile>();
|
||||
if (heProjectile == null || !heProjectile.IsValid || heProjectile.AbsRotation == null) return;
|
||||
|
||||
int lastTick = Server.TickCount;
|
||||
|
||||
Server.NextFrame(() =>
|
||||
{
|
||||
if (heProjectile == null || !heProjectile.IsValid) return;
|
||||
|
|
@ -63,9 +86,37 @@ namespace src.player.skills
|
|||
heProjectile.Damage = SkillsInfo.GetValue<int>(skillName, "explosionDamage");
|
||||
heProjectile.DmgRadius = SkillsInfo.GetValue<float>(skillName, "explosionRadius");
|
||||
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 IsDeadPlayerValid(CCSPlayerController? player)
|
||||
|
|
@ -73,12 +124,11 @@ namespace src.player.skills
|
|||
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 int ExplosionDamage { get; set; } = explosionDamage;
|
||||
public float DmgReductionForTeamates { get; set; } = dmgReductionForTeamates;
|
||||
public bool ExplosionAfterWorldDeath { get; set; } = explosionAfterWorldDeath;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue