Merge pull request #56 from ByDexterTR/main

v1.2.3.b9
This commit is contained in:
Juzlus 2026-08-28 02:26:50 +02:00 • committed by GitHub
commit c790229872
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 150 additions and 62 deletions

View file

@ -7,7 +7,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.371" /> <PackageReference Include="CounterStrikeSharp.API" Version="1.0.373" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -19,7 +19,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.371" /> <PackageReference Include="CounterStrikeSharp.API" Version="1.0.373" />
<PackageReference Include="MaxMind.Db" Version="5.1.0"> <PackageReference Include="MaxMind.Db" Version="5.1.0">
</PackageReference> </PackageReference>
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.4" />

View file

@ -31,7 +31,7 @@ namespace src
public override string ModuleName => "[CS2] [ jRandomSkills ]"; public override string ModuleName => "[CS2] [ jRandomSkills ]";
public override string ModuleAuthor => "D3X (Original), Juzlus (Modifier), ByDexterTR (Contributor)"; 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 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) public override void Load(bool hotReload)
{ {

View file

@ -1,4 +1,4 @@
using CounterStrikeSharp.API; using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Core.Attributes; using CounterStrikeSharp.API.Core.Attributes;
using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Memory;
@ -89,6 +89,7 @@ namespace src.player
lock (setLock) lock (setLock)
{ {
CountDamageResolution(info); CountDamageResolution(info);
SkillUtils.TrackHealthBeforeHit(entity, info);
object[] args = [entity, info]; object[] args = [entity, info];
DispatchOnTakeDamage(entity, info, args); DispatchOnTakeDamage(entity, info, args);

View file

@ -798,6 +798,8 @@ namespace src.player
return; return;
} }
if (designer == "planted_c4" && player.Team == CsTeam.CounterTerrorist) return;
if (designer.Contains("button") || designer.Contains("weapon") || designer.Contains("blocker")) return; if (designer.Contains("button") || designer.Contains("weapon") || designer.Contains("blocker")) return;
} }
} }

View file

@ -1,4 +1,4 @@
using CounterStrikeSharp.API; using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Core.Attributes; using CounterStrikeSharp.API.Core.Attributes;
using CounterStrikeSharp.API.Modules.Admin; using CounterStrikeSharp.API.Modules.Admin;
@ -182,6 +182,7 @@ namespace src.player
Instance.RemoveListener<CheckTransmit>(CheckTransmit); Instance.RemoveListener<CheckTransmit>(CheckTransmit);
Fortnite.skillInThisRound = false; Fortnite.skillInThisRound = false;
SkillUtils.ClearHealthBeforeHit();
EntityManager.SuppressKills = true; EntityManager.SuppressKills = true;
try try

View file

@ -1,4 +1,4 @@
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 src.utils; using src.utils;
@ -9,7 +9,6 @@ namespace src.player.skills
public class Dracula : ISkill public class Dracula : ISkill
{ {
private const Skills skillName = Skills.Dracula; private const Skills skillName = Skills.Dracula;
public static void LoadSkill() public static void LoadSkill()
{ {
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color")); SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
@ -20,11 +19,11 @@ namespace src.player.skills
var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); var attacker = PlayerManager.GetPlayerEvent(@event.Attacker);
var victim = PlayerManager.GetPlayerEvent(@event.Userid); 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); var playerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index);
if (playerInfo?.Skill != skillName) return;
if (playerInfo?.Skill == skillName && victim!.PawnIsAlive) HealAttacker(attacker!, SkillUtils.CapToVictimHealth(victim, @event.DmgHealth));
HealAttacker(attacker!, @event.DmgHealth);
} }
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
@ -46,22 +45,30 @@ namespace src.player.skills
private static void HealAttacker(CCSPlayerController attacker, float damage) 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<float>(skillName, "healthRegainScale")); int extraHealth = (int)(damage * SkillsInfo.GetValue<float>(skillName, "healthRegainScale"));
if (extraHealth <= 0) return; if (extraHealth <= 0) return;
attackerPawn.Health += extraHealth; uint attackerIndex = attacker.Index;
Utilities.SetStateChanged(attackerPawn, "CBaseEntity", "m_iHealth");
if (attackerPawn.MaxHealth < attackerPawn.Health) Server.NextFrame(() =>
{ {
attackerPawn.MaxHealth = attackerPawn.Health; var target = Utilities.GetPlayerFromIndex((int)attackerIndex);
Utilities.SetStateChanged(attackerPawn, "CBaseEntity", "m_iMaxHealth"); 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) 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)

View file

@ -302,13 +302,43 @@ namespace src.player.skills
return shooter != null && shooter.IsValid ? shooter : null; 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<CCSPlayerController>());
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) public static void OnTakeDamage(CBaseEntity damagedEntity, CTakeDamageInfo damageInfo)
{ {
if (damagedEntity == null || damagedEntity.Entity == null || damageInfo == null) if (damagedEntity == null || damagedEntity.Entity == null || damageInfo == null)
return; return;
if (string.IsNullOrEmpty(damagedEntity.Entity.Name)) return; if (string.IsNullOrEmpty(damagedEntity.Entity.Name) || !damagedEntity.Entity.Name.StartsWith("IanaClone_"))
if (!damagedEntity.Entity.Name.StartsWith("IanaClone_")) return; {
AbsorbWithClone(damagedEntity, damageInfo);
return;
}
var nameParams = damagedEntity.Entity.Name.Split('_')[2]; var nameParams = damagedEntity.Entity.Name.Split('_')[2];
_ = uint.TryParse(nameParams, out uint userIndex); _ = 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) private static void BlockWeapon(CCSPlayerController player, bool block)
{ {
if (player == null || !player.IsValid) return; if (player == null || !player.IsValid) return;

View file

@ -1,4 +1,4 @@
using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Entities.Constants;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using src.utils; using src.utils;
@ -17,19 +17,46 @@ namespace src.player.skills
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color")); SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(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); var ability = damageInfo.Ability?.Value;
int damage = @event.DmgHealth; if (ability != null && ability.IsValid && ability.DesignerName == infernoDamage) return true;
string weapon = @event.Weapon;
if (weapon != "inferno" || !Instance.IsPlayerValid(victim)) return; var inflictor = damageInfo.Inflictor?.Value;
var victimInfo = PlayerManager.GetPlayerByIndex(victim!.Index); 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; CCSPlayerPawn victimPawn = new(damagedEntity.Handle);
SkillUtils.AddHealth(pawn, (int)(damage * SkillsInfo.GetValue<float>(skillName, "regenerationMultiplier"))); if (!victimPawn.IsValid || victimPawn.DesignerName != "player") return;
var victimController = victimPawn.Controller?.Value;
if (victimController == null || !victimController.IsValid) return;
var victim = PlayerManager.GetPlayerEvent(victimController.As<CCSPlayerController>());
if (victim == null || !victim.IsValid) return;
if (PlayerManager.GetPlayerByIndex(victim.Index)?.Skill != skillName) return;
float damage = damageInfo.Damage;
float net = damage * (SkillsInfo.GetValue<float>(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) public static void GrenadeThrown(EventGrenadeThrown @event)

View file

@ -1,4 +1,4 @@
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 static src.jRandomSkills;
@ -26,7 +26,6 @@ namespace src.player.skills
{ {
var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); var attacker = PlayerManager.GetPlayerEvent(@event.Attacker);
var victim = PlayerManager.GetPlayerEvent(@event.Userid); var victim = PlayerManager.GetPlayerEvent(@event.Userid);
int damage = @event.DmgHealth;
if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return; if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return;
var attackerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index); var attackerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index);

View file

@ -1,5 +1,6 @@
using CounterStrikeSharp.API; using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Cvars;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using src.utils; using src.utils;
using static src.jRandomSkills; using static src.jRandomSkills;
@ -15,16 +16,18 @@ namespace src.player.skills
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color")); SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
} }
private static int GetMaxMoney() => ConVar.Find("mp_maxmoney")?.GetPrimitiveValue<int>() ?? 16000;
public static void PlayerHurt(EventPlayerHurt @event) public static void PlayerHurt(EventPlayerHurt @event)
{ {
var victim = PlayerManager.GetPlayerEvent(@event.Userid); var victim = PlayerManager.GetPlayerEvent(@event.Userid);
var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); var attacker = PlayerManager.GetPlayerEvent(@event.Attacker);
var damage = @event.DmgHealth; if (!Instance.IsPlayerValid(attacker) || victim == null || !victim.IsValid || attacker == victim) return;
if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return;
var attackerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index); var attackerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index);
if (attackerInfo?.Skill != skillName) return; if (attackerInfo?.Skill != skillName) return;
int damage = SkillUtils.CapToVictimHealth(victim, @event.DmgHealth);
int moneyToSteal = damage * SkillsInfo.GetValue<int>(skillName, "moneyMultiplier"); int moneyToSteal = damage * SkillsInfo.GetValue<int>(skillName, "moneyMultiplier");
StealMoney(victim!, attacker!, moneyToSteal); StealMoney(victim!, attacker!, moneyToSteal);
} }
@ -35,11 +38,17 @@ namespace src.player.skills
var attackerMoneyServices = attacker?.InGameMoneyServices; var attackerMoneyServices = attacker?.InGameMoneyServices;
if (victimMoneyServices == null || attackerMoneyServices == null) return; if (victimMoneyServices == null || attackerMoneyServices == null) return;
var moneyToAdd = victimMoneyServices.Account < money ? victimMoneyServices.Account : money; int maxMoney = GetMaxMoney();
victimMoneyServices.Account = Math.Max(victimMoneyServices.Account - money, 0); 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"); Utilities.SetStateChanged(victim!, "CCSPlayerController", "m_pInGameMoneyServices");
attackerMoneyServices.Account = Math.Min(attackerMoneyServices.Account + moneyToAdd, 16000); attackerMoneyServices.Account += transfer;
Utilities.SetStateChanged(attacker!, "CCSPlayerController", "m_pInGameMoneyServices"); Utilities.SetStateChanged(attacker!, "CCSPlayerController", "m_pInGameMoneyServices");
} }

View file

@ -1,4 +1,4 @@
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 jRandomSkills.src.utils; using jRandomSkills.src.utils;
@ -138,7 +138,7 @@ namespace src.player.skills
if (victimPawn == null || !victimPawn.IsValid || victimPawn.Health <= 0) return; if (victimPawn == null || !victimPawn.IsValid || victimPawn.Health <= 0) return;
if (victimPawn.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; if (victimPawn.LifeState != (byte)LifeState_t.LIFE_ALIVE) return;
int reflected = (int)MathF.Round(@event.DmgHealth * SkillsInfo.GetValue<float>(skillName, "reflectPercent")); int reflected = (int)MathF.Round(SkillUtils.CapToVictimHealth(owner, @event.DmgHealth) * SkillsInfo.GetValue<float>(skillName, "reflectPercent"));
if (reflected < 1) return; if (reflected < 1) return;
SkillUtils.TakeHealth(victimPawn, reflected, owner, KillfeedIcons.Fist); SkillUtils.TakeHealth(victimPawn, reflected, owner, KillfeedIcons.Fist);

View file

@ -290,8 +290,11 @@ namespace src.utils
public class WeaponPools public class WeaponPools
{ {
[JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace)]
public required List<string> Rifle { get; set; } public required List<string> Rifle { get; set; }
[JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace)]
public required List<string> Pistol { get; set; } public required List<string> Pistol { get; set; }
[JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace)]
public required List<string> Grenade { get; set; } public required List<string> Grenade { get; set; }
} }

View file

@ -7,6 +7,7 @@ using RayTraceAPI;
using System.Drawing; using System.Drawing;
using System.Numerics; using System.Numerics;
using TraceOptions = RayTraceAPI.TraceOptions; using TraceOptions = RayTraceAPI.TraceOptions;
using TraceResult = RayTraceAPI.TraceResult;
using Vector = CounterStrikeSharp.API.Modules.Utils.Vector; using Vector = CounterStrikeSharp.API.Modules.Utils.Vector;
namespace src.utils namespace src.utils

View file

@ -619,6 +619,34 @@ namespace src.utils
.Cast<CCSPlayerController>()]; .Cast<CCSPlayerController>()];
} }
private static readonly ConcurrentDictionary<uint, int> 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<CCSPlayerController>());
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) 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) if (pawn == null || !pawn.IsValid || pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE)