v1.2.2.b2

## GENERAL
- Updated CSS to version 1.0.369.
- Upgraded the project from .NET 8.0 to .NET 10.0.
- Updated Turkish language translation by @ByDexterTR.
- Added Russian language translation by @213sdfsdgf.
- Fixed an issue with incorrect display of Arabic nicknames.
- Used ForceFullUpdate to resolve the "FATAL ERROR: CopyExistingEntity" crash.
- Disabled stale HandleCommandDrop hook to avoid crashes when a player joins a team (thanks to @vladimir214sd).
- Added new signatures to gamedata.
- Added the ability to configure the number of grenades for every skill that uses grenades as part of its ability (e.g., Miner, AntyFlash, MagneticDecoy, etc.).

## SKILL IMPROVEMENTS
- Re-Zombie:
  -- Fixed weapon switching issues when a player is holding a Zeus and a knife.
  -- Weapons are now removed for bots in zombie mode.
- Ghost:
  -- Blocked the ability to use the Zeus.
- Thorns:
  -- Added a configurable maximum health limit (37 HP) for the damage that can be reflected.
- Second Life / Phoenix / Re-Zombie:
  -- Fixed an issue where players would occasionally fail to respawn if they took too much damage too quickly.
- Ghost / Chicken:
  -- Blocked the ability to use the SG556 (`weapon_sg556`).
- Wallhack:
  -- Fixed a bug that caused temporary enemy highlighting right after death.
- Cypher:
  -- Added camera position persistence.
- God Mode:
  -- Fixed an issue with permanent immortality triggering after reaching exactly 0 HP.
- Weapons Swap:
  -- The ammo count is now also transferred when weapons are swapped.
- Muhammed:
  -- Renamed the skill to "DeathBomb".
- Spectator:
  -- Fixed a bug where a player with the Chicken skill would still display as a ragdoll after death when spectated.
- Friendly Fire:
  -- The skill now works even when the server's mp_friendlyfire setting is set to 0.
- Baseball:
  -- Disabled teammate killing.
This commit is contained in:
Juzlus 2026-06-10 13:47:34 +02:00
parent cba834e8f0
commit 91761f7376
84 changed files with 6894 additions and 1689 deletions

View file

@ -4,8 +4,10 @@ using CounterStrikeSharp.API.Modules.Cvars;
using CounterStrikeSharp.API.Modules.Entities.Constants;
using CounterStrikeSharp.API.Modules.Memory;
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
using CounterStrikeSharp.API.Modules.Timers;
using CounterStrikeSharp.API.Modules.UserMessages;
using CounterStrikeSharp.API.Modules.Utils;
using jRandomSkills.src.utils;
using src.player;
using src.player.skills;
using System.Collections.Concurrent;
@ -56,7 +58,30 @@ namespace src.utils
SkillData.Skills.Add(new jSkill_SkillInfo(skill, color, display));
}
public static void TryGiveWeapon(CCSPlayerController player, CsItem item, int count = 1)
public static void UpdateGrenadeCount(CCSPlayerController player, CsItem item, int ammo)
{
string? itemString = EnumUtils.GetEnumMemberAttributeValue(item);
if (string.IsNullOrWhiteSpace(itemString)) return;
if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return;
if (player.PlayerPawn.Value.WeaponServices == null) return;
var weapon = player.PlayerPawn.Value.WeaponServices.MyWeapons
.FirstOrDefault(w => w != null && w.IsValid && w.Value != null && w.Value.IsValid && !string.IsNullOrEmpty(w.Value.DesignerName) && w.Value.DesignerName == itemString);
if (weapon == null || !weapon.IsValid || weapon.Value == null || !weapon.Value.IsValid) return;
weapon.Value.Clip1 = ammo;
Utilities.SetStateChanged(weapon.Value, "CBasePlayerWeapon", "m_iClip1");
jRandomSkills.Instance.AddTimer(.1f, () =>
{
if (weapon == null || !weapon.IsValid || weapon.Value == null || !weapon.Value.IsValid) return;
weapon.Value.Clip1 = 1;
}, TimerFlags.STOP_ON_MAPCHANGE);
}
public static void TryGiveWeapon(CCSPlayerController player, CsItem item, int count = 1, bool existValidator = true)
{
string? itemString = EnumUtils.GetEnumMemberAttributeValue(item);
if (string.IsNullOrWhiteSpace(itemString)) return;
@ -66,7 +91,8 @@ namespace src.utils
var exists = player.PlayerPawn.Value.WeaponServices.MyWeapons
.FirstOrDefault(w => w != null && w.IsValid && w.Value != null && w.Value.IsValid && w.Value.DesignerName == itemString);
if (exists == null)
if (exists == null || !existValidator)
for (int i = 0; i < count; i++)
player.GiveNamedItem(item);
}
@ -259,6 +285,9 @@ namespace src.utils
var jester = Jester.GetJesterInfo(player.Index);
if (jester?.Active == true) return false;
if (playerInfo.Skill == Skills.GodMode && GodMode.HaveHodMode(player.Index))
return false;
}
int newHealth = (int)(pawn.Health - damage);
@ -291,9 +320,35 @@ namespace src.utils
return EntityManager.CreateTrackedTrigger(ownerPlayerIndex, name, radius, pos);
}
public static void ForceFullUpdate(CCSPlayerController player)
{
if (player == null || !player.IsValid)
return;
var pawn = player.PlayerPawn?.Value;
if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) return;
QAngle lastAngle = new(pawn.V_angle.X, pawn.V_angle.Y, pawn.V_angle.Z);
INetworkServerService networkServerService = new();
INetworkGameServer networkGameServer = networkServerService.GetIGameServer();
var client = networkGameServer.GetClientBySlot(player.Slot);
if (client == null) return;
client.ForceFullUpdate();
pawn.Look(lastAngle);
}
public static void ForceFullUpdateToAll()
{
foreach (var player in Utilities.GetPlayers())
ForceFullUpdate(player);
}
public static bool AddHealth(CCSPlayerPawn? pawn, int extraHealth, int? maxHealth = 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 || pawn.Health <= 0)
return false;
maxHealth ??= pawn.MaxHealth;
@ -381,6 +436,18 @@ namespace src.utils
return manager.HasMenu(player);
}
private static string GetInvisibleSignature(string id)
{
if (string.IsNullOrEmpty(id)) return "";
var sb = new System.Text.StringBuilder();
foreach (char c in id)
for (int i = 0; i < 8; i++)
sb.Append(((c >> i) & 1) == 1 ? "\u200B" : "\u200C");
return sb.ToString();
}
public static void UpdateMenu(CCSPlayerController? player, ConcurrentBag<(string, string)> items)
{
if (player == null) return;
@ -395,13 +462,19 @@ namespace src.utils
Dictionary<string, Action<CCSPlayerController, IWasdMenuOption>> list = [];
foreach (var item in items)
list.TryAdd(isIlliterate
{
string encodedText = isIlliterate
? System.Net.WebUtility.HtmlEncode(Illiterate.GetRandomText(item.Item1)!)
: System.Net.WebUtility.HtmlEncode(item.Item1), (p, option) =>
: System.Net.WebUtility.HtmlEncode(item.Item1);
string uniqueKey = GetInvisibleSignature(item.Item2) + $"\u202A{encodedText}\u202C";
list.TryAdd(uniqueKey, (p, option) =>
{
jRandomSkills.Instance.SkillAction(playerInfo.Skill.ToString(), "TypeSkill", [p, new[] { item.Item2 }]);
manager.CloseMenu(p);
});
}
manager.UpdateActiveMenu(player, list);
}
@ -445,11 +518,11 @@ namespace src.utils
string infoLine = string.IsNullOrEmpty(your_skill)
? ""
: $"<font class='fontWeight-Bold fontSize-{config.HeaderLineSize}' color='{config.HeaderLineColor}'>{your_skill}:</font><br>";
: $"<font class='fontWeight-Bold fontSize-{config.HeaderLineSize}' color='{config.HeaderLineColor}'>\u202A{your_skill}:\u202C</font><br>";
string skillLine = Illiterate.CheckIlliterateSkill(player)
? $"<font class='fontWeight-Bold fontSize-{config.SkillLineSize}'>{Illiterate.GetRandomText(player.GetSkillName(skillData.Skill))}</font><br>"
: $"<font class='fontWeight-Bold fontSize-{config.SkillLineSize}' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font><br>";
? $"<font class='fontWeight-Bold fontSize-{config.SkillLineSize}'>\u202A{Illiterate.GetRandomText(player.GetSkillName(skillData.Skill))}\u202C</font><br>"
: $"<font class='fontWeight-Bold fontSize-{config.SkillLineSize}' color='{skillData.Color}'>\u202A{player.GetSkillName(skillData.Skill)}\u202C</font><br>";
var skill_select_info = player.GetTranslation($"{playerInfo.Skill.ToString().ToLower()}_select_info");
string remainingLine = string.IsNullOrWhiteSpace(skill_select_info)
@ -470,22 +543,34 @@ namespace src.utils
IWasdMenu menu = manager.CreateMenu(hudContent, itemText, itemHoverText, controllsLine);
foreach (var enemy in enemies)
menu.Add(isIlliterate
{
string encodedEnemyName = isIlliterate
? System.Net.WebUtility.HtmlEncode(Illiterate.GetRandomText(enemy.Item1)!)
: System.Net.WebUtility.HtmlEncode(enemy.Item1), (p, option) =>
: System.Net.WebUtility.HtmlEncode(enemy.Item1);
string uniqueKey = GetInvisibleSignature(enemy.Item2) + $"\u202A{encodedEnemyName}\u202C";
menu.Add(uniqueKey, (p, option) =>
{
jRandomSkills.Instance.SkillAction(playerInfo.Skill.ToString(), "TypeSkill", [p, new[] { enemy.Item2 }]);
manager.CloseMenu(p);
});
}
if (lastElement != null)
menu.Add(isIlliterate
{
string encodedLastElement = isIlliterate
? System.Net.WebUtility.HtmlEncode(Illiterate.GetRandomText(lastElement.Value.Item1)!)
: System.Net.WebUtility.HtmlEncode(lastElement.Value.Item1), (p, option) =>
: System.Net.WebUtility.HtmlEncode(lastElement.Value.Item1);
menu.Add($"\u202A{encodedLastElement}\u202C", (p, option) =>
{
jRandomSkills.Instance.SkillAction(playerInfo.Skill.ToString(), "TypeSkill", [p, new[] { lastElement.Value.Item2 }]);
if (lastElement.Value.Item3)
manager.CloseMenu(p);
});
}
manager.OpenMainMenu(player, menu);
}