v1.2.2.b1

This commit is contained in:
Juzlus 2026-05-24 23:13:56 +02:00
parent 0fb3d63cd8
commit 46195c2663
147 changed files with 3470 additions and 2161 deletions

View file

@ -80,6 +80,8 @@ namespace src.utils
public bool KillerSkillChatInfo { get; set; }
public bool TeamMateSkillChatInfo { get; set; }
public bool SummaryAfterTheRound { get; set; }
public bool EnableBotSkills { get; set; }
public bool EnableBotKickDebug { get; set; }
public bool DebugMode { get; set; }
public string? AlternativeSkillButton { get; set; }
public float SkillTimeBeforeStart { get; set; }
@ -87,7 +89,7 @@ namespace src.utils
public float SkillDescriptionDuration { get; set; }
public bool DisplayAlwaysDescription { get; set; }
public bool DisableSpectateHUD { get; set; }
public bool FlashingHtmlHudFix { get; set; }
public bool EnableFlashingHtmlHudFix { get; set; }
public bool TraceRayBeam { get; set; }
public string DisableHUDOnDeathPermission { get; set; }
public bool DisableSkillsOnRoundEnd { get; set; }
@ -105,13 +107,15 @@ namespace src.utils
KillerSkillChatInfo = true;
TeamMateSkillChatInfo = true;
SummaryAfterTheRound = true;
EnableBotSkills = true;
EnableBotKickDebug = false;
DebugMode = false;
AlternativeSkillButton = null;
SkillTimeBeforeStart = 7;
SkillHudDuration = -1;
SkillDescriptionDuration = 7;
DisplayAlwaysDescription = false;
FlashingHtmlHudFix = true;
EnableFlashingHtmlHudFix = false;
TraceRayBeam = false;
DisableSpectateHUD = false;
DisableHUDOnDeathPermission = "@jRandomSkills/death";

View file

@ -0,0 +1,273 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Entities.Constants;
using CounterStrikeSharp.API.Modules.Utils;
using System.Collections.Concurrent;
using System.Drawing;
using static src.jRandomSkills;
namespace src.utils
{
public static class EntityManager
{
public const uint SystemOwnerIndex = uint.MaxValue;
private static readonly ConcurrentDictionary<uint, EntityData> trackedEntities = [];
private struct EntityData
{
public uint EntityIndex;
public uint PlayerIndex;
public string EntityType;
public DateTime CreatedAt;
}
public static void RegisterEntity(uint entityIndex, uint playerIndex, string entityType)
{
if (entityIndex == 0) return;
trackedEntities[entityIndex] = new EntityData
{
EntityIndex = entityIndex,
PlayerIndex = playerIndex,
EntityType = entityType,
CreatedAt = DateTime.UtcNow
};
}
public static void RegisterExisting(CBaseEntity? entity, uint playerIndex, string entityType)
{
if (entity == null || !entity.IsValid) return;
RegisterEntity(entity.Index, playerIndex, entityType);
}
public static List<uint> GetPlayerEntities(uint playerIndex, string? entityType = null)
{
return [.. trackedEntities
.Where(kvp => kvp.Value.PlayerIndex == playerIndex && (string.IsNullOrEmpty(entityType) || kvp.Value.EntityType == entityType))
.Select(kvp => kvp.Key)];
}
public static int GetTrackedCount(uint playerIndex) => GetPlayerEntities(playerIndex).Count;
public static (int totalTracked, int ownerCount) GetStatistics()
{
return (trackedEntities.Count, trackedEntities.Values.Select(e => e.PlayerIndex).Distinct().Count());
}
public static CParticleSystem? CreateTrackedParticleSystem(uint playerIndex, string particleName, float? autoDestroySeconds = null)
{
try
{
var particle = Utilities.CreateEntityByName<CParticleSystem>("info_particle_system");
if (particle == null || !particle.IsValid) return null;
particle.EffectName = particleName;
particle.StartActive = true;
particle.DispatchSpawn();
RegisterEntity(particle.Index, playerIndex, "particle_system");
ScheduleAutoDestroy(particle.Index, autoDestroySeconds);
return particle;
}
catch (Exception ex)
{
Server.PrintToConsole($"[EntityManager] CreateTrackedParticleSystem: {ex.Message}");
return null;
}
}
public static CDynamicProp? CreateTrackedDynamicProp(uint playerIndex, string designerName = "prop_dynamic")
{
try
{
var prop = Utilities.CreateEntityByName<CDynamicProp>(designerName);
if (prop == null || !prop.IsValid) return null;
RegisterEntity(prop.Index, playerIndex, designerName);
return prop;
}
catch (Exception ex)
{
Server.PrintToConsole($"[EntityManager] CreateTrackedDynamicProp: {ex.Message}");
return null;
}
}
public static CDynamicProp? CreateTrackedPropOverride(uint playerIndex)
{
return CreateTrackedDynamicProp(playerIndex, "prop_dynamic_override");
}
public static CEnvShake? CreateTrackedEnvShake(uint playerIndex)
{
try
{
var shake = Utilities.CreateEntityByName<CEnvShake>("env_shake");
if (shake == null || !shake.IsValid) return null;
shake.DispatchSpawn();
RegisterEntity(shake.Index, playerIndex, "env_shake");
return shake;
}
catch (Exception ex)
{
Server.PrintToConsole($"[EntityManager] CreateTrackedEnvShake: {ex.Message}");
return null;
}
}
public static CChicken? CreateTrackedChicken(uint playerIndex)
{
try
{
var chicken = Utilities.CreateEntityByName<CChicken>("chicken");
if (chicken == null || !chicken.IsValid) return null;
chicken.DispatchSpawn();
RegisterEntity(chicken.Index, playerIndex, "chicken");
return chicken;
}
catch (Exception ex)
{
Server.PrintToConsole($"[EntityManager] CreateTrackedChicken: {ex.Message}");
return null;
}
}
public static CPhysicsPropMultiplayer? CreateTrackedPhysicsProp(uint playerIndex)
{
try
{
var prop = Utilities.CreateEntityByName<CPhysicsPropMultiplayer>("prop_physics_multiplayer");
if (prop == null || !prop.IsValid) return null;
RegisterEntity(prop.Index, playerIndex, "prop_physics_multiplayer");
return prop;
}
catch (Exception ex)
{
Server.PrintToConsole($"[EntityManager] CreateTrackedPhysicsProp: {ex.Message}");
return null;
}
}
public static CTriggerMultiple? CreateTrackedTrigger(uint playerIndex, string name, float radius, Vector pos)
{
if (pos == null) return null;
try
{
var trigger = Utilities.CreateEntityByName<CTriggerMultiple>("trigger_multiple");
if (trigger == null || trigger.AbsOrigin == null) return null;
trigger.Collision.SolidType = SolidType_t.SOLID_CAPSULE;
trigger.Collision.SolidFlags = 0;
trigger.Spawnflags = 1;
trigger.Globalname = $"{name}_{trigger.Index}";
trigger.Collision.SolidFlags = 1;
trigger.AbsOrigin.X = pos.X;
trigger.AbsOrigin.Y = pos.Y;
trigger.AbsOrigin.Z = pos.Z;
trigger.Collision.CapsuleRadius = radius;
trigger.Collision.BoundingRadius = radius;
trigger.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_TRIGGER;
trigger.Collision.EnablePhysics = 1;
trigger.Collision.TriggerBloat = 0;
trigger.Collision.SurroundType = SurroundingBoundsType_t.USE_OBB_COLLISION_BOUNDS;
trigger.Collision.CollisionAttribute.CollisionFunctionMask = 39;
trigger.Collision.CollisionAttribute.CollisionGroup = 2;
trigger.DispatchSpawn();
RegisterEntity(trigger.Index, playerIndex, "trigger_multiple");
return trigger;
}
catch (Exception ex)
{
Server.PrintToConsole($"[EntityManager] CreateTrackedTrigger: {ex.Message}");
return null;
}
}
public static CBeam? CreateTrackedBeam(uint playerIndex, Vector start, Vector end, Color color)
{
try
{
var beam = Utilities.CreateEntityByName<CBeam>("beam");
if (beam == null || !beam.IsValid) return null;
beam.Render = color;
beam.Width = 2.0f;
beam.EndWidth = 2.0f;
beam.Teleport(start);
beam.EndPos.X = end.X;
beam.EndPos.Y = end.Y;
beam.EndPos.Z = end.Z;
beam.DispatchSpawn();
RegisterEntity(beam.Index, playerIndex, "beam");
return beam;
}
catch (Exception ex)
{
Server.PrintToConsole($"[EntityManager] CreateTrackedBeam: {ex.Message}");
return null;
}
}
public static bool DestroyEntity(uint entityIndex)
{
trackedEntities.TryRemove(entityIndex, out _);
try
{
var entity = Utilities.GetEntityFromIndex<CBaseEntity>((int)entityIndex);
if (entity != null && entity.IsValid)
{
entity.AddEntityIOEvent("Kill", entity, delay: 0.1f);
return true;
}
}
catch (Exception ex)
{
Server.PrintToConsole($"[EntityManager] DestroyEntity {entityIndex}: {ex.Message}");
}
return false;
}
public static bool DestroyEntity<T>(uint? entityIndex) where T : CBaseEntity
{
if (entityIndex == null) return false;
return DestroyEntity(entityIndex.Value);
}
public static void DestroyPlayerEntities(uint playerIndex)
{
foreach (var entityIndex in GetPlayerEntities(playerIndex).ToList())
DestroyEntity(entityIndex);
}
public static void DestroyAllTracked()
{
foreach (var entityIndex in trackedEntities.Keys.ToList())
DestroyEntity(entityIndex);
trackedEntities.Clear();
}
public static void Clear()
{
DestroyAllTracked();
}
private static void ScheduleAutoDestroy(uint entityIndex, float? seconds)
{
if (seconds is not > 0) return;
Instance?.AddTimer(seconds.Value, () => DestroyEntity(entityIndex), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
}
}
}

View file

@ -166,7 +166,7 @@ namespace src.utils
private static string GetLangCode(CCSPlayerController? player)
{
if (player == null || !player.IsValid) return defaultLangCode;
if (player == null || !player.IsValid || player.IsBot) return defaultLangCode;
string? fileLangCode = GetLangCodeFromFile(player.SteamID);
if (!string.IsNullOrEmpty(fileLangCode))

View file

@ -0,0 +1,135 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Modules.Utils;
using System.Collections.Concurrent;
using src.player;
using CounterStrikeSharp.API.Core;
namespace src.utils
{
public static class PlayerManager
{
private static readonly ConcurrentDictionary<uint, jSkill_PlayerInfo> playersByIndex = [];
public static void Register(jSkill_PlayerInfo playerInfo)
{
if (playerInfo == null) return;
playersByIndex[playerInfo.PlayerIndex] = playerInfo;
}
public static void UnregisterPlayer(uint playerIndex)
{
playersByIndex.TryRemove(playerIndex, out _);
}
public static jSkill_PlayerInfo? GetPlayerByIndex(uint? playerIndex)
{
if (playerIndex == null) return null;
playersByIndex.TryGetValue((uint)playerIndex, out var playerInfo);
return playerInfo;
}
public static CCSPlayerController? GetPlayerEvent(CCSPlayerController? player)
{
if (player == null || !player.IsValid)
return null;
if (!player.ControllingBot)
return player;
return Utilities.GetPlayers().FirstOrDefault(p =>
p != null &&
p.IsValid &&
p.IsBot &&
p.OriginalControllerOfCurrentPawn.Value != null && p.OriginalControllerOfCurrentPawn.Value == player)
?? player;
}
public static CCSPlayerController? GetPlayerFromEvent(CCSPlayerController? player)
{
if (player == null || !player.IsValid)
return null;
if (!player.IsBot)
return player;
return Utilities.GetPlayers().FirstOrDefault(p =>
p != null &&
p.IsValid &&
!p.IsBot &&
player.OriginalControllerOfCurrentPawn.Value != null && player.OriginalControllerOfCurrentPawn.Value == p)
?? player;
}
public static IEnumerable<jSkill_PlayerInfo> GetAllPlayers()
{
return playersByIndex.Values;
}
public static IEnumerable<jSkill_PlayerInfo> GetAlivePlayers()
{
return playersByIndex.Values.Where(p =>
{
try
{
var controller = Utilities.GetPlayerFromIndex((int)p.PlayerIndex);
return controller != null && controller.IsValid && controller.PawnIsAlive;
}
catch
{
return false;
}
});
}
public static IEnumerable<jSkill_PlayerInfo> GetPlayersByTeam(CsTeam team)
{
return playersByIndex.Values.Where(p =>
{
try
{
var controller = Utilities.GetPlayerFromIndex((int)p.PlayerIndex);
return controller != null && controller.IsValid && controller.Team == team;
}
catch
{
return false;
}
});
}
public static int GetTeamPlayerCount(CsTeam team)
{
return GetPlayersByTeam(team).Count();
}
public static int GetPlayerCountBySkill(Skills skills)
{
return playersByIndex.Values.Count(p => p.Skill == skills);
}
public static bool UpdatePlayerSkill(uint playerIndex, Skills skill, Skills specialSkill = Skills.None)
{
if (playersByIndex.TryGetValue(playerIndex, out var playerInfo))
{
playerInfo.Skill = skill;
playerInfo.SpecialSkill = specialSkill;
return true;
}
return false;
}
public static void Clear()
{
playersByIndex.Clear();
}
public static void SyncWithPlugin(jRandomSkills instance)
{
if (instance?.SkillPlayer == null) return;
foreach (var player in instance.SkillPlayer)
Register(player);
}
}
}

View file

@ -1,4 +1,6 @@
namespace src.utils
using System.Drawing;
namespace src.utils
{
public enum Rarity
{
@ -14,11 +16,11 @@
private static readonly object rarityLock = new();
private static Dictionary<Rarity, float> rarityPercentages = new()
{
{ Rarity.Common, 40f },
{ Rarity.Uncommon, 25f },
{ Rarity.Rare, 20f },
{ Rarity.Epic, 10f },
{ Rarity.Legendary, 5f }
{ Rarity.Common, 70f },
{ Rarity.Uncommon, 14f },
{ Rarity.Rare, 10f },
{ Rarity.Epic, 5f },
{ Rarity.Legendary, 1f }
};
public static IReadOnlyDictionary<Rarity, float> RarityPercentages
@ -60,23 +62,23 @@
return rarityPercentages.TryGetValue(rarity, out var v) ? v : 0f;
}
public static Rarity RollRarity()
public static (double, Rarity) RollRarity()
{
var random = jRandomSkills.Instance?.Random ?? new Random();
double roll = (random.NextDouble()) * 100.0;
double roll = Random.Shared.NextDouble() * 100.0;
double accum = 0.0;
lock (rarityLock)
{
foreach (var r in Enum.GetValues(typeof(Rarity)).Cast<Rarity>())
{
accum += GetRarityPercentage(r);
float chance = rarityPercentages.TryGetValue(r, out var val) ? val : 0f;
accum += chance;
if (roll <= accum)
return r;
return (roll, r);
}
}
return Rarity.Common;
return (roll, Rarity.Common);
}
}
}

View file

@ -17,8 +17,15 @@ namespace src.utils
public static CustomTraceResult? TraceShape(CCSPlayerController player, Vector startPos, Vector endPos, ulong? mask = null, ulong? contents = null)
{
var playerPawn = player.PlayerPawn.Value;
if (playerPawn == null)
if (player == null || !player.IsValid) return null;
var playerPawn = player.PlayerPawn?.Value;
if (playerPawn == null ||
!playerPawn.IsValid ||
playerPawn.Handle == IntPtr.Zero ||
playerPawn.Collision == null ||
playerPawn.LifeState != (byte)LifeState_t.LIFE_ALIVE ||
playerPawn.CBodyComponent?.SceneNode == null)
return null;
var rayTrace = RayTraceInterface.Get();
@ -27,10 +34,22 @@ namespace src.utils
if (mask == null)
{
mask = playerPawn.Collision.CollisionAttribute.InteractsWith | (ulong)InteractionLayers.Hitboxes;
mask &= ~(ulong)InteractionLayers.PlayerClip;
try
{
if (playerPawn.Collision?.CollisionAttribute != null)
{
mask = playerPawn.Collision.CollisionAttribute.InteractsWith | (ulong)InteractionLayers.Hitboxes;
mask &= ~(ulong)InteractionLayers.PlayerClip;
}
else
mask = (ulong)(InteractionLayers.Solid | InteractionLayers.Hitboxes);
}
catch
{
mask = (ulong)(InteractionLayers.Solid | InteractionLayers.Hitboxes);
}
}
contents ??= 0; // playerPawn.Collision.CollisionGroup;
contents ??= 0;
bool drawBeam = Config.LoadedConfig.TraceRayBeam;
@ -41,28 +60,39 @@ namespace src.utils
DrawBeam = drawBeam == true ? 1 : 0,
};
rayTrace.TraceEndShape(startPos, endPos, playerPawn, options, out TraceResult result);
var customResult = new CustomTraceResult(result, startPos, (ulong)mask, (ulong)contents, drawBeam);
Vector mins = new(-0.5f, -0.5f, -0.5f);
Vector maxs = new(0.5f, 0.5f, 0.5f);
if (drawBeam)
Server.PrintToChatAll($"start: {startPos}, end: {result.EndPos}, didHit: {result.DidHit}, hit: {(customResult.HitEntity(out var entity) && !string.IsNullOrEmpty(entity?.DesignerName) ? entity.DesignerName : "None")}, mask: {(InteractionLayers)mask}, contents: {(InteractionLayers)contents}");
TraceResult result = default;
return customResult;
try
{
rayTrace.TraceHullShape(startPos, endPos, mins, maxs, playerPawn, options, out result);
}
catch (Exception ex)
{
Console.WriteLine($"[jRandomSkills] A memory error was caught during RayTrace: {ex.Message}");
return null;
}
return new CustomTraceResult(result, startPos, (ulong)mask, (ulong)contents, drawBeam);
}
public static CustomTraceResult? EyeTrace(CCSPlayerController player)
{
var playerPawn = player.PlayerPawn.Value;
if (playerPawn == null)
if (player == null || !player.IsValid) return null;
var playerPawn = player.PlayerPawn?.Value;
if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null)
return null;
var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID);
var playerInfo = PlayerManager.GetPlayerByIndex(player.Index);
if (playerInfo == null) return null;
float maxDistance = SkillsInfo.GetValue<float>(playerInfo.Skill, "maxDistance");
if (maxDistance == 0) maxDistance = 4096f;
Vector startPos = new(playerPawn.AbsOrigin!.X, playerPawn.AbsOrigin!.Y, playerPawn.AbsOrigin!.Z + playerPawn.ViewOffset.Z);
Vector startPos = new(playerPawn.AbsOrigin.X, playerPawn.AbsOrigin.Y, playerPawn.AbsOrigin.Z + playerPawn.ViewOffset.Z);
Vector endPos = startPos + SkillUtils.GetForwardVector(playerPawn.EyeAngles) * maxDistance;
return TraceShape(player, startPos, endPos);
@ -70,38 +100,57 @@ namespace src.utils
public static CustomTraceResult? TraceHullShape(Vector startPos, Vector endPos, CCSPlayerController player, Vector? mins = null, Vector? maxs = null, ulong? mask = null, ulong? contents = null, QAngle? angle = null)
{
var playerPawn = player.PlayerPawn.Value;
if (playerPawn == null)
if (player == null || !player.IsValid) return null;
var playerPawn = player.PlayerPawn?.Value;
if (playerPawn == null ||
!playerPawn.IsValid ||
playerPawn.Handle == IntPtr.Zero ||
playerPawn.Collision == null ||
playerPawn.LifeState != (byte)LifeState_t.LIFE_ALIVE ||
playerPawn.CBodyComponent?.SceneNode == null)
return null;
var rayTrace = RayTraceInterface.Get();
if (rayTrace == null)
return null;
mask ??= playerPawn.Collision.CollisionAttribute.InteractsWith;
contents ??= 0; // playerPawn.Collision.CollisionGroup;
Vector safeMins = mins ?? playerPawn.Collision.Mins;
Vector safeMaxs = maxs ?? playerPawn.Collision.Maxs;
ulong safeMask = mask ?? playerPawn.Collision.CollisionAttribute.InteractsWith;
ulong safeContents = contents ?? 0;
bool drawBeam = Config.LoadedConfig.TraceRayBeam;
TraceResult result = default;
TraceOptions options = new()
{
InteractsWith = (ulong)mask,
InteractsExclude = (ulong)contents,
InteractsWith = safeMask,
InteractsExclude = safeContents,
DrawBeam = drawBeam == true ? 1 : 0,
};
mins ??= playerPawn.Collision.Mins;
maxs ??= playerPawn.Collision.Maxs;
CEntityInstance? entityToIgnore = (playerPawn.LifeState == (byte)LifeState_t.LIFE_ALIVE)
? playerPawn
: null;
rayTrace.TraceHullShape(startPos, endPos, mins, maxs, playerPawn, options, out TraceResult result);
try
{
rayTrace.TraceHullShape(startPos, endPos, safeMins, safeMaxs, entityToIgnore, options, out result);
}
catch (Exception)
{
return null;
}
if (drawBeam)
{
angle ??= new(0, playerPawn.EyeAngles.Y, 0);
DrawBoxEdges(startPos, endPos, angle, mins, maxs, Color.Green);
DrawBoxEdges(startPos, endPos, angle, safeMins, safeMaxs, Color.Green);
}
return new CustomTraceResult(result, startPos, (ulong)mask, (ulong)contents, drawBeam);
return new CustomTraceResult(result, startPos, safeMask, safeContents, drawBeam);
}
private static void DrawBoxEdges(Vector start, Vector end, QAngle angles, Vector mins, Vector maxs, Color color)
@ -112,7 +161,7 @@ namespace src.utils
Vector visualStart = start - (forward * halfLength);
Vector visualEnd = end + (forward * halfLength);
Vector GetVertex(Vector center, float rx, float ux)
{
return center + (right * rx) + (up * ux);
@ -300,4 +349,4 @@ namespace src.utils
EndsWith
}
}
}
}

View file

@ -105,11 +105,7 @@ namespace src.utils
public static void SafeKillEntity<T>(uint? index) where T : CBaseEntity
{
if (index == null) return;
var ent = Utilities.GetEntityFromIndex<T>((int)index);
if (ent == null || !ent.IsValid) return;
ent.AddEntityIOEvent("Kill", ent, delay: 0.1f);
EntityManager.DestroyEntity(index.Value);
}
public static bool IsValid<T>(this CHandle<T>? handle) where T : NativeEntity
@ -150,23 +146,9 @@ namespace src.utils
SnapViewAngles.Invoke(pawn, angle);
}
public static CBeam? CreateLine(Vector start, Vector end, Color color)
public static CBeam? CreateLine(Vector start, Vector end, Color color, uint ownerPlayerIndex = EntityManager.SystemOwnerIndex)
{
CBeam beam = Utilities.CreateEntityByName<CBeam>("beam")!;
if (beam == null) return null;
beam.Render = color;
beam.Width = 2.0f;
beam.EndWidth = 2.0f;
beam.Teleport(start);
beam.EndPos.X = end.X;
beam.EndPos.Y = end.Y;
beam.EndPos.Z = end.Z;
beam.DispatchSpawn();
return beam;
return EntityManager.CreateTrackedBeam(ownerPlayerIndex, start, end, color);
}
public static void SetPlayerCollisions(CCSPlayerController? player, bool enable)
@ -176,7 +158,7 @@ namespace src.utils
if (player == null || !player.IsValid) return;
var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid || !player.PawnIsAlive || pawn.CBodyComponent == null) return;
if (pawn == null || !pawn.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE || pawn.CBodyComponent == null) return;
var collision = pawn.Collision;
if (collision == null) return;
@ -264,21 +246,19 @@ namespace src.utils
SmokeGrenadeProjectile_CreateFunc.Invoke(pos.Handle, angle.Handle, vel.Handle, vel.Handle, IntPtr.Zero, 45, teamNum);
}
public static void TakeHealth(CCSPlayerPawn? pawn, int damage)
public static bool TakeHealth(CCSPlayerPawn? pawn, int damage)
{
if (pawn == null || !pawn.IsValid || pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE)
return;
return false;
var player = pawn.Controller.Value;
if (player != null && player.IsValid && player.SteamID != 0)
{
ulong steamId = player.SteamID;
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
if (playerInfo == null) return false;
var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == steamId);
if (playerInfo == null) return;
var jester = Jester.GetJesterInfo(steamId);
if (jester?.Active == true) return;
var jester = Jester.GetJesterInfo(player.Index);
if (jester?.Active == true) return false;
}
int newHealth = (int)(pawn.Health - damage);
@ -286,65 +266,49 @@ namespace src.utils
Utilities.SetStateChanged(pawn, "CBaseEntity", "m_iHealth");
if (pawn.Health <= 0)
{
Server.NextFrame(() =>
{
if (pawn == null || !pawn.IsValid) return;
pawn?.CommitSuicide(false, true);
});
return false;
}
return true;
}
public static void ResetPrintHTML(CCSPlayerController? player)
{
var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID);
if (player == null || !player.IsValid) return;
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
if (playerInfo == null) return;
playerInfo.PrintHTML = null;
}
public static CTriggerMultiple? CreateTrigger(string name, float radius, Vector pos)
public static CTriggerMultiple? CreateTrigger(string name, float radius, Vector pos, uint ownerPlayerIndex = EntityManager.SystemOwnerIndex)
{
if (pos == null) return null;
var trigger = Utilities.CreateEntityByName<CTriggerMultiple>("trigger_multiple");
if (trigger == null || trigger.AbsOrigin == null) return null;
trigger.Collision.SolidType = SolidType_t.SOLID_CAPSULE;
trigger.Collision.SolidFlags = 0;
trigger.Spawnflags = 1;
trigger.Globalname = $"{name}_{trigger.Index}";
trigger.Collision.SolidFlags = 1;
trigger.AbsOrigin.X = pos.X;
trigger.AbsOrigin.Y = pos.Y;
trigger.AbsOrigin.Z = pos.Z;
trigger.Collision.CapsuleRadius = radius;
trigger.Collision.BoundingRadius = radius;
trigger.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_TRIGGER;
trigger.Collision.EnablePhysics = 1;
trigger.Collision.TriggerBloat = 0;
trigger.Collision.SurroundType = SurroundingBoundsType_t.USE_OBB_COLLISION_BOUNDS;
trigger.Collision.CollisionAttribute.CollisionFunctionMask = 39;
trigger.Collision.CollisionAttribute.CollisionGroup = 2;
trigger.DispatchSpawn();
return trigger;
return EntityManager.CreateTrackedTrigger(ownerPlayerIndex, name, radius, pos);
}
public static void AddHealth(CCSPlayerPawn? pawn, int extraHealth, int? maxHealth = null)
public static bool AddHealth(CCSPlayerPawn? pawn, int extraHealth, int? maxHealth = null)
{
if (pawn == null || !pawn.IsValid || pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE)
return;
return false;
maxHealth ??= pawn.MaxHealth;
if (pawn.Health == maxHealth)
return false;
int newHealth = (int)(pawn.Health + extraHealth);
pawn.Health = Math.Min(newHealth, (int)maxHealth);
Utilities.SetStateChanged(pawn, "CBaseEntity", "m_iHealth");
pawn.MaxHealth = (int)maxHealth;
Utilities.SetStateChanged(pawn, "CBaseEntity", "m_iMaxHealth");
return true;
}
public static void RestoreHealth(CCSPlayerController? player)
@ -356,10 +320,28 @@ namespace src.utils
if (pawn == null || !pawn.IsValid || pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE)
return;
pawn.Health = (int)player.PawnHealth;
var p = PlayerManager.GetPlayerFromEvent(player);
if (p == null || !p.IsValid)
return;
pawn.Health = (int)p.PawnHealth;
Utilities.SetStateChanged(pawn, "CBaseEntity", "m_iHealth");
}
public static void SetPlayerInvisibility(CCSPlayerController player, float percentInvisibility)
{
if (player == null || !player.IsValid || player.PlayerPawn == null)
return;
var playerPawn = player.PlayerPawn.Value;
if (playerPawn != null)
{
var color = Color.FromArgb(Math.Max(255 - (int)(255 * percentInvisibility), 0), 255, 255, 255);
playerPawn.Render = color;
Utilities.SetStateChanged(playerPawn, "CBaseModelEntity", "m_clrRender");
}
}
public static string GetDesignerName(CBasePlayerWeapon? weapon)
{
if (weapon == null || !weapon.IsValid) return string.Empty;
@ -406,7 +388,7 @@ namespace src.utils
var manager = GetMenuManager();
if (manager == null) return;
var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
if (playerInfo == null) return;
bool isIlliterate = Illiterate.CheckIlliterateSkill(player);
@ -428,9 +410,29 @@ namespace src.utils
{
if (player == null || !player.IsValid) return;
var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
if (playerInfo == null || !playerInfo.DisplayHUD) return;
if (player.IsBot)
{
var pool = new List<string>();
foreach (var enemy in enemies)
if (!string.IsNullOrEmpty(enemy.Item2))
pool.Add(enemy.Item2);
if (lastElement != null && !string.IsNullOrEmpty(lastElement.Value.Item2))
pool.Add(lastElement.Value.Item2);
if (pool.Count > 0)
{
string randomTarget = pool[Random.Shared.Next(pool.Count)];
jRandomSkills.Instance.SkillAction(playerInfo.Skill.ToString(), "TypeSkill", [player, new[] { randomTarget }]);
}
return;
}
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == playerInfo.Skill);
if (skillData == null) return;
@ -454,8 +456,6 @@ namespace src.utils
? ""
: $"<font class='fontSize-{config.WSADMenuSelectInfoLineSize}' color='{config.WSADMenuSelectInfoLineColor}'>{skill_select_info}</font><br>";
var hudContent = infoLine + skillLine + remainingLine;
string controllsLine =