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>
<ItemGroup>
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.371" />
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.373" />
</ItemGroup>
</Project>

View file

@ -19,7 +19,7 @@
</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>
<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 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)
{

View file

@ -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);

View file

@ -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;
}
}

View file

@ -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>(CheckTransmit);
Fortnite.skillInThisRound = false;
SkillUtils.ClearHealthBeforeHit();
EntityManager.SuppressKills = true;
try

View file

@ -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<string>(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<float>(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)

View file

@ -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<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)
{
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;

View file

@ -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<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);
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<float>(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<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)

View file

@ -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);

View file

@ -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<string>(skillName, "color"));
}
private static int GetMaxMoney() => ConVar.Find("mp_maxmoney")?.GetPrimitiveValue<int>() ?? 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<int>(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");
}

View file

@ -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<float>(skillName, "reflectPercent"));
int reflected = (int)MathF.Round(SkillUtils.CapToVictimHealth(owner, @event.DmgHealth) * SkillsInfo.GetValue<float>(skillName, "reflectPercent"));
if (reflected < 1) return;
SkillUtils.TakeHealth(victimPawn, reflected, owner, KillfeedIcons.Fist);

View file

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

View file

@ -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

View file

@ -619,6 +619,34 @@ namespace src.utils
.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)
{
if (pawn == null || !pawn.IsValid || pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE)