diff --git a/WASDMenuAPI - SRC Files/WASDMenuAPI.csproj b/WASDMenuAPI - SRC Files/WASDMenuAPI.csproj
index ddda590..564cd1d 100644
--- a/WASDMenuAPI - SRC Files/WASDMenuAPI.csproj
+++ b/WASDMenuAPI - SRC Files/WASDMenuAPI.csproj
@@ -7,7 +7,7 @@
-
+
diff --git a/jRandomSkills - SRC Files/jRandomSkills.csproj b/jRandomSkills - SRC Files/jRandomSkills.csproj
index ead9b06..e853387 100644
--- a/jRandomSkills - SRC Files/jRandomSkills.csproj
+++ b/jRandomSkills - SRC Files/jRandomSkills.csproj
@@ -19,7 +19,7 @@
-
+
diff --git a/jRandomSkills - SRC Files/src/jRandomSkills.cs b/jRandomSkills - SRC Files/src/jRandomSkills.cs
index 49e474e..26bdc3d 100644
--- a/jRandomSkills - SRC Files/src/jRandomSkills.cs
+++ b/jRandomSkills - SRC Files/src/jRandomSkills.cs
@@ -31,7 +31,7 @@ namespace src
public override string ModuleName => "[CS2] [ jRandomSkills ]";
public override string ModuleAuthor => "D3X (Original), Juzlus (Modifier), ByDexterTR (Contributor)";
public override string ModuleDescription => "Plugin adds random skills every round for CS2 by D3X. Modified by Juzlus.";
- public override string ModuleVersion => "1.2.3.b8";
+ public override string ModuleVersion => "1.2.3.b9";
public override void Load(bool hotReload)
{
diff --git a/jRandomSkills - SRC Files/src/player/EntityEvents.cs b/jRandomSkills - SRC Files/src/player/EntityEvents.cs
index 825b860..c98cc41 100644
--- a/jRandomSkills - SRC Files/src/player/EntityEvents.cs
+++ b/jRandomSkills - SRC Files/src/player/EntityEvents.cs
@@ -1,4 +1,4 @@
-using CounterStrikeSharp.API;
+using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Core.Attributes;
using CounterStrikeSharp.API.Modules.Memory;
@@ -89,6 +89,7 @@ namespace src.player
lock (setLock)
{
CountDamageResolution(info);
+ SkillUtils.TrackHealthBeforeHit(entity, info);
object[] args = [entity, info];
DispatchOnTakeDamage(entity, info, args);
diff --git a/jRandomSkills - SRC Files/src/player/PlayerEvents.cs b/jRandomSkills - SRC Files/src/player/PlayerEvents.cs
index a92791f..8f5507d 100644
--- a/jRandomSkills - SRC Files/src/player/PlayerEvents.cs
+++ b/jRandomSkills - SRC Files/src/player/PlayerEvents.cs
@@ -798,6 +798,8 @@ namespace src.player
return;
}
+ if (designer == "planted_c4" && player.Team == CsTeam.CounterTerrorist) return;
+
if (designer.Contains("button") || designer.Contains("weapon") || designer.Contains("blocker")) return;
}
}
diff --git a/jRandomSkills - SRC Files/src/player/RoundEvents.cs b/jRandomSkills - SRC Files/src/player/RoundEvents.cs
index e53c1b6..9908d4f 100644
--- a/jRandomSkills - SRC Files/src/player/RoundEvents.cs
+++ b/jRandomSkills - SRC Files/src/player/RoundEvents.cs
@@ -1,4 +1,4 @@
-using CounterStrikeSharp.API;
+using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Core.Attributes;
using CounterStrikeSharp.API.Modules.Admin;
@@ -182,6 +182,7 @@ namespace src.player
Instance.RemoveListener(CheckTransmit);
Fortnite.skillInThisRound = false;
+ SkillUtils.ClearHealthBeforeHit();
EntityManager.SuppressKills = true;
try
diff --git a/jRandomSkills - SRC Files/src/player/skills/Dracula.cs b/jRandomSkills - SRC Files/src/player/skills/Dracula.cs
index 4f082ba..3e6b7d3 100644
--- a/jRandomSkills - SRC Files/src/player/skills/Dracula.cs
+++ b/jRandomSkills - SRC Files/src/player/skills/Dracula.cs
@@ -1,4 +1,4 @@
-using CounterStrikeSharp.API;
+using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Utils;
using src.utils;
@@ -9,7 +9,6 @@ namespace src.player.skills
public class Dracula : ISkill
{
private const Skills skillName = Skills.Dracula;
-
public static void LoadSkill()
{
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color"));
@@ -20,11 +19,11 @@ namespace src.player.skills
var attacker = PlayerManager.GetPlayerEvent(@event.Attacker);
var victim = PlayerManager.GetPlayerEvent(@event.Userid);
- if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return;
+ if (!Instance.IsPlayerValid(attacker) || victim == null || !victim.IsValid || attacker == victim) return;
var playerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index);
+ if (playerInfo?.Skill != skillName) return;
- if (playerInfo?.Skill == skillName && victim!.PawnIsAlive)
- HealAttacker(attacker!, @event.DmgHealth);
+ HealAttacker(attacker!, SkillUtils.CapToVictimHealth(victim, @event.DmgHealth));
}
public static void DisableSkill(CCSPlayerController player)
@@ -46,22 +45,30 @@ namespace src.player.skills
private static void HealAttacker(CCSPlayerController attacker, float damage)
{
- var attackerPawn = attacker.PlayerPawn?.Value;
- if (attackerPawn == null || !attackerPawn.IsValid) return;
-
- if (attackerPawn.LifeState != (byte)LifeState_t.LIFE_ALIVE || attackerPawn.Health <= 0) return;
-
int extraHealth = (int)(damage * SkillsInfo.GetValue(skillName, "healthRegainScale"));
if (extraHealth <= 0) return;
- attackerPawn.Health += extraHealth;
- Utilities.SetStateChanged(attackerPawn, "CBaseEntity", "m_iHealth");
+ uint attackerIndex = attacker.Index;
- if (attackerPawn.MaxHealth < attackerPawn.Health)
+ Server.NextFrame(() =>
{
- attackerPawn.MaxHealth = attackerPawn.Health;
- Utilities.SetStateChanged(attackerPawn, "CBaseEntity", "m_iMaxHealth");
- }
+ var target = Utilities.GetPlayerFromIndex((int)attackerIndex);
+ if (target == null || !target.IsValid) return;
+
+ var attackerPawn = target.PlayerPawn?.Value;
+ if (attackerPawn == null || !attackerPawn.IsValid) return;
+
+ if (attackerPawn.LifeState != (byte)LifeState_t.LIFE_ALIVE || attackerPawn.Health <= 0) return;
+
+ attackerPawn.Health += extraHealth;
+ Utilities.SetStateChanged(attackerPawn, "CBaseEntity", "m_iHealth");
+
+ if (attackerPawn.MaxHealth < attackerPawn.Health)
+ {
+ attackerPawn.MaxHealth = attackerPawn.Health;
+ Utilities.SetStateChanged(attackerPawn, "CBaseEntity", "m_iMaxHealth");
+ }
+ });
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#FA050D", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float? hudDuration = null, float? descriptionHudDuration = null, int maxPerServer = -1, Rarity rarity = Rarity.Common, float healthRegainScale = .3f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, hudDuration, descriptionHudDuration, maxPerServer, rarity)
diff --git a/jRandomSkills - SRC Files/src/player/skills/Iana.cs b/jRandomSkills - SRC Files/src/player/skills/Iana.cs
index f160033..f21f33d 100644
--- a/jRandomSkills - SRC Files/src/player/skills/Iana.cs
+++ b/jRandomSkills - SRC Files/src/player/skills/Iana.cs
@@ -302,13 +302,43 @@ namespace src.player.skills
return shooter != null && shooter.IsValid ? shooter : null;
}
+ private static void AbsorbWithClone(CBaseEntity damagedEntity, CTakeDamageInfo damageInfo)
+ {
+ if (damageInfo.Damage <= 0) return;
+
+ CCSPlayerPawn victimPawn = new(damagedEntity.Handle);
+ if (!victimPawn.IsValid || victimPawn.DesignerName != "player") return;
+
+ var victimController = victimPawn.Controller?.Value;
+ if (victimController == null || !victimController.IsValid) return;
+
+ var victim = PlayerManager.GetPlayerEvent(victimController.As());
+ if (victim == null || !victim.IsValid) return;
+
+ if (PlayerManager.GetPlayerByIndex(victim.Index)?.Skill != skillName) return;
+ if (!playersInfo.TryGetValue(victim.Index, out var playerSkill)) return;
+
+ bool hasClone = playerSkill.CloneProp != null;
+ if (!hasClone && playerSkill.LastHit + 4 <= Server.TickCount) return;
+
+ damageInfo.Damage = 0;
+
+ if (!hasClone) return;
+
+ KillClone(playerSkill);
+ playerSkill.LastHit = Server.TickCount;
+ }
+
public static void OnTakeDamage(CBaseEntity damagedEntity, CTakeDamageInfo damageInfo)
{
if (damagedEntity == null || damagedEntity.Entity == null || damageInfo == null)
return;
- if (string.IsNullOrEmpty(damagedEntity.Entity.Name)) return;
- if (!damagedEntity.Entity.Name.StartsWith("IanaClone_")) return;
+ if (string.IsNullOrEmpty(damagedEntity.Entity.Name) || !damagedEntity.Entity.Name.StartsWith("IanaClone_"))
+ {
+ AbsorbWithClone(damagedEntity, damageInfo);
+ return;
+ }
var nameParams = damagedEntity.Entity.Name.Split('_')[2];
_ = uint.TryParse(nameParams, out uint userIndex);
@@ -357,26 +387,6 @@ namespace src.player.skills
}
}
- public static void PlayerHurt(EventPlayerHurt @event)
- {
- var victim = PlayerManager.GetPlayerEvent(@event.Userid);
- if (victim == null || !victim.IsValid) return;
-
- if (PlayerManager.GetPlayerByIndex(victim.Index)?.Skill != skillName) return;
-
- if (playersInfo.TryGetValue(victim.Index, out var playerSkill))
- {
- if (playerSkill.CloneProp != null)
- {
- KillClone(playerSkill);
- playerSkill.LastHit = Server.TickCount;
- }
-
- if (playerSkill.LastHit + 4 > Server.TickCount)
- SkillUtils.RestoreHealth(victim);
- }
- }
-
private static void BlockWeapon(CCSPlayerController player, bool block)
{
if (player == null || !player.IsValid) return;
diff --git a/jRandomSkills - SRC Files/src/player/skills/Pyro.cs b/jRandomSkills - SRC Files/src/player/skills/Pyro.cs
index 4bdcc77..4621dda 100644
--- a/jRandomSkills - SRC Files/src/player/skills/Pyro.cs
+++ b/jRandomSkills - SRC Files/src/player/skills/Pyro.cs
@@ -1,4 +1,4 @@
-using CounterStrikeSharp.API.Core;
+using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Entities.Constants;
using CounterStrikeSharp.API.Modules.Utils;
using src.utils;
@@ -17,19 +17,46 @@ namespace src.player.skills
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color"));
}
- public static void PlayerHurt(EventPlayerHurt @event)
+ private const string infernoDamage = "inferno";
+
+ private static bool IsInfernoDamage(CTakeDamageInfo damageInfo)
{
- var victim = PlayerManager.GetPlayerEvent(@event.Userid);
- int damage = @event.DmgHealth;
- string weapon = @event.Weapon;
+ var ability = damageInfo.Ability?.Value;
+ if (ability != null && ability.IsValid && ability.DesignerName == infernoDamage) return true;
- if (weapon != "inferno" || !Instance.IsPlayerValid(victim)) return;
- var victimInfo = PlayerManager.GetPlayerByIndex(victim!.Index);
+ var inflictor = damageInfo.Inflictor?.Value;
+ return inflictor != null && inflictor.IsValid && inflictor.DesignerName == infernoDamage;
+ }
- if (victimInfo == null || victimInfo.Skill != skillName) return;
+ public static void OnTakeDamage(CBaseEntity damagedEntity, CTakeDamageInfo damageInfo)
+ {
+ if (damagedEntity == null || !damagedEntity.IsValid || damageInfo == null) return;
+ if (damageInfo.Damage <= 0 || !IsInfernoDamage(damageInfo)) return;
- var pawn = victim!.PlayerPawn.Value;
- SkillUtils.AddHealth(pawn, (int)(damage * SkillsInfo.GetValue(skillName, "regenerationMultiplier")));
+ CCSPlayerPawn victimPawn = new(damagedEntity.Handle);
+ if (!victimPawn.IsValid || victimPawn.DesignerName != "player") return;
+
+ var victimController = victimPawn.Controller?.Value;
+ if (victimController == null || !victimController.IsValid) return;
+
+ var victim = PlayerManager.GetPlayerEvent(victimController.As());
+ if (victim == null || !victim.IsValid) return;
+
+ if (PlayerManager.GetPlayerByIndex(victim.Index)?.Skill != skillName) return;
+
+ float damage = damageInfo.Damage;
+ float net = damage * (SkillsInfo.GetValue(skillName, "regenerationMultiplier") - 1f);
+
+ if (net < 0)
+ {
+ damageInfo.Damage = -net;
+ return;
+ }
+
+ damageInfo.Damage = 0;
+
+ int heal = (int)MathF.Round(net);
+ if (heal > 0) SkillUtils.AddHealth(victimPawn, heal);
}
public static void GrenadeThrown(EventGrenadeThrown @event)
diff --git a/jRandomSkills - SRC Files/src/player/skills/ReturnToSender.cs b/jRandomSkills - SRC Files/src/player/skills/ReturnToSender.cs
index c91e050..c3e82d0 100644
--- a/jRandomSkills - SRC Files/src/player/skills/ReturnToSender.cs
+++ b/jRandomSkills - SRC Files/src/player/skills/ReturnToSender.cs
@@ -1,4 +1,4 @@
-using CounterStrikeSharp.API;
+using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Utils;
using static src.jRandomSkills;
@@ -26,7 +26,6 @@ namespace src.player.skills
{
var attacker = PlayerManager.GetPlayerEvent(@event.Attacker);
var victim = PlayerManager.GetPlayerEvent(@event.Userid);
- int damage = @event.DmgHealth;
if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return;
var attackerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index);
diff --git a/jRandomSkills - SRC Files/src/player/skills/RobinHood.cs b/jRandomSkills - SRC Files/src/player/skills/RobinHood.cs
index b95ca3f..b5f1b4a 100644
--- a/jRandomSkills - SRC Files/src/player/skills/RobinHood.cs
+++ b/jRandomSkills - SRC Files/src/player/skills/RobinHood.cs
@@ -1,5 +1,6 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
+using CounterStrikeSharp.API.Modules.Cvars;
using CounterStrikeSharp.API.Modules.Utils;
using src.utils;
using static src.jRandomSkills;
@@ -15,16 +16,18 @@ namespace src.player.skills
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color"));
}
+ private static int GetMaxMoney() => ConVar.Find("mp_maxmoney")?.GetPrimitiveValue() ?? 16000;
+
public static void PlayerHurt(EventPlayerHurt @event)
{
var victim = PlayerManager.GetPlayerEvent(@event.Userid);
var attacker = PlayerManager.GetPlayerEvent(@event.Attacker);
- var damage = @event.DmgHealth;
- if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return;
+ if (!Instance.IsPlayerValid(attacker) || victim == null || !victim.IsValid || attacker == victim) return;
var attackerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index);
if (attackerInfo?.Skill != skillName) return;
+ int damage = SkillUtils.CapToVictimHealth(victim, @event.DmgHealth);
int moneyToSteal = damage * SkillsInfo.GetValue(skillName, "moneyMultiplier");
StealMoney(victim!, attacker!, moneyToSteal);
}
@@ -35,11 +38,17 @@ namespace src.player.skills
var attackerMoneyServices = attacker?.InGameMoneyServices;
if (victimMoneyServices == null || attackerMoneyServices == null) return;
- var moneyToAdd = victimMoneyServices.Account < money ? victimMoneyServices.Account : money;
- victimMoneyServices.Account = Math.Max(victimMoneyServices.Account - money, 0);
+ int maxMoney = GetMaxMoney();
+ int headroom = Math.Max(maxMoney - attackerMoneyServices.Account, 0);
+
+ int transfer = Math.Min(money, victimMoneyServices.Account);
+ transfer = Math.Min(transfer, headroom);
+ if (transfer <= 0) return;
+
+ victimMoneyServices.Account -= transfer;
Utilities.SetStateChanged(victim!, "CCSPlayerController", "m_pInGameMoneyServices");
- attackerMoneyServices.Account = Math.Min(attackerMoneyServices.Account + moneyToAdd, 16000);
+ attackerMoneyServices.Account += transfer;
Utilities.SetStateChanged(attacker!, "CCSPlayerController", "m_pInGameMoneyServices");
}
diff --git a/jRandomSkills - SRC Files/src/player/skills/Voodoo.cs b/jRandomSkills - SRC Files/src/player/skills/Voodoo.cs
index ddaf66c..d23c820 100644
--- a/jRandomSkills - SRC Files/src/player/skills/Voodoo.cs
+++ b/jRandomSkills - SRC Files/src/player/skills/Voodoo.cs
@@ -1,4 +1,4 @@
-using CounterStrikeSharp.API;
+using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Utils;
using jRandomSkills.src.utils;
@@ -138,7 +138,7 @@ namespace src.player.skills
if (victimPawn == null || !victimPawn.IsValid || victimPawn.Health <= 0) return;
if (victimPawn.LifeState != (byte)LifeState_t.LIFE_ALIVE) return;
- int reflected = (int)MathF.Round(@event.DmgHealth * SkillsInfo.GetValue(skillName, "reflectPercent"));
+ int reflected = (int)MathF.Round(SkillUtils.CapToVictimHealth(owner, @event.DmgHealth) * SkillsInfo.GetValue(skillName, "reflectPercent"));
if (reflected < 1) return;
SkillUtils.TakeHealth(victimPawn, reflected, owner, KillfeedIcons.Fist);
diff --git a/jRandomSkills - SRC Files/src/utils/Config.cs b/jRandomSkills - SRC Files/src/utils/Config.cs
index 4f55eae..8766989 100644
--- a/jRandomSkills - SRC Files/src/utils/Config.cs
+++ b/jRandomSkills - SRC Files/src/utils/Config.cs
@@ -290,8 +290,11 @@ namespace src.utils
public class WeaponPools
{
+ [JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace)]
public required List Rifle { get; set; }
+ [JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace)]
public required List Pistol { get; set; }
+ [JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace)]
public required List Grenade { get; set; }
}
diff --git a/jRandomSkills - SRC Files/src/utils/RayTrace.cs b/jRandomSkills - SRC Files/src/utils/RayTrace.cs
index 5ac6e22..92f314f 100644
--- a/jRandomSkills - SRC Files/src/utils/RayTrace.cs
+++ b/jRandomSkills - SRC Files/src/utils/RayTrace.cs
@@ -7,6 +7,7 @@ using RayTraceAPI;
using System.Drawing;
using System.Numerics;
using TraceOptions = RayTraceAPI.TraceOptions;
+using TraceResult = RayTraceAPI.TraceResult;
using Vector = CounterStrikeSharp.API.Modules.Utils.Vector;
namespace src.utils
diff --git a/jRandomSkills - SRC Files/src/utils/SkillUtils.cs b/jRandomSkills - SRC Files/src/utils/SkillUtils.cs
index a7cde3f..9599df3 100644
--- a/jRandomSkills - SRC Files/src/utils/SkillUtils.cs
+++ b/jRandomSkills - SRC Files/src/utils/SkillUtils.cs
@@ -619,6 +619,34 @@ namespace src.utils
.Cast()];
}
+ private static readonly ConcurrentDictionary healthBeforeHit = [];
+
+ public static void TrackHealthBeforeHit(CBaseEntity? damagedEntity, CTakeDamageInfo? damageInfo)
+ {
+ if (damagedEntity == null || damageInfo == null || damageInfo.Damage <= 0) return;
+
+ CCSPlayerPawn victimPawn = new(damagedEntity.Handle);
+ if (!victimPawn.IsValid || victimPawn.DesignerName != "player") return;
+
+ var victimController = victimPawn.Controller?.Value;
+ if (victimController == null || !victimController.IsValid) return;
+
+ var victim = PlayerManager.GetPlayerEvent(victimController.As());
+ if (victim == null || !victim.IsValid) return;
+
+ healthBeforeHit[victim.Index] = victimPawn.Health;
+ }
+
+ public static int CapToVictimHealth(CCSPlayerController? victim, int dmgHealth)
+ {
+ if (victim == null || !victim.IsValid) return dmgHealth;
+ if (!healthBeforeHit.TryGetValue(victim.Index, out int healthBefore) || healthBefore <= 0) return dmgHealth;
+
+ return dmgHealth > healthBefore ? healthBefore : dmgHealth;
+ }
+
+ public static void ClearHealthBeforeHit() => healthBeforeHit.Clear();
+
public static bool TakeHealth(CCSPlayerPawn? pawn, int damage, CCSPlayerController? damageAttacker = null, KillfeedIcons? killfeedIcon = null)
{
if (pawn == null || !pawn.IsValid || pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE)
diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/WASDMenuAPI.dll b/jRandomSkills - Server Files/plugins/jRandomSkills/WASDMenuAPI.dll
index e69cf33..d0aee34 100644
Binary files a/jRandomSkills - Server Files/plugins/jRandomSkills/WASDMenuAPI.dll and b/jRandomSkills - Server Files/plugins/jRandomSkills/WASDMenuAPI.dll differ
diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/jRandomSkills.dll b/jRandomSkills - Server Files/plugins/jRandomSkills/jRandomSkills.dll
index 595e711..1753ecb 100644
Binary files a/jRandomSkills - Server Files/plugins/jRandomSkills/jRandomSkills.dll and b/jRandomSkills - Server Files/plugins/jRandomSkills/jRandomSkills.dll differ