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:
parent
cba834e8f0
commit
91761f7376
84 changed files with 6894 additions and 1689 deletions
101
jRandomSkills - SRC Files/src/utils/CServerSideClient.cs
Normal file
101
jRandomSkills - SRC Files/src/utils/CServerSideClient.cs
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
// https://discord.com/channels/1160907911501991946/1508172390863994910/1508180670659166348
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Memory;
|
||||
|
||||
namespace jRandomSkills.src.utils
|
||||
{
|
||||
|
||||
#region Native Structs
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe struct CUtlMemory<T> where T : unmanaged
|
||||
{
|
||||
public T* m_pMemory;
|
||||
public int m_nAllocationCount;
|
||||
public int m_nGrowSize;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe struct CUtlVector<T> where T : unmanaged
|
||||
{
|
||||
public int m_Size;
|
||||
public CUtlMemory<T> m_Memory;
|
||||
|
||||
public int Count => m_Size;
|
||||
|
||||
public ref T Element(int index)
|
||||
{
|
||||
if (index < 0 || index >= m_Size)
|
||||
throw new IndexOutOfRangeException();
|
||||
|
||||
return ref m_Memory.m_pMemory[index];
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Network Services
|
||||
|
||||
public class INetworkServerService : NativeObject
|
||||
{
|
||||
private readonly VirtualFunctionWithReturn<nint, nint> GetIGameServerFunc;
|
||||
|
||||
public INetworkServerService() : base(NativeAPI.GetValveInterface(0, "NetworkServerService_001"))
|
||||
{
|
||||
GetIGameServerFunc = new VirtualFunctionWithReturn<nint, nint>(Handle, GameData.GetOffset("INetworkServerService_GetIGameServer"));
|
||||
}
|
||||
|
||||
public INetworkGameServer GetIGameServer()
|
||||
{
|
||||
return new INetworkGameServer(GetIGameServerFunc.Invoke(Handle));
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe class INetworkGameServer(nint ptr) : NativeObject(ptr)
|
||||
{
|
||||
private static readonly int SlotsOffset = GameData.GetOffset("INetworkGameServer_Slots");
|
||||
|
||||
private ref CUtlVector<nint> Slots => ref Unsafe.AsRef<CUtlVector<nint>>((void*)(Handle + SlotsOffset));
|
||||
|
||||
public CServerSideClient? GetClientBySlot(int slot)
|
||||
{
|
||||
if (slot < 0 || slot >= Slots.Count)
|
||||
return null;
|
||||
|
||||
var ptr = Slots.Element(slot);
|
||||
|
||||
if (ptr == nint.Zero)
|
||||
return null;
|
||||
|
||||
return new CServerSideClient(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CServerSideClient
|
||||
|
||||
public unsafe class CServerSideClient(nint ptr) : NativeObject(ptr)
|
||||
{
|
||||
private static readonly int m_nDeltaTick = GameData.GetOffset("CServerSideClient_m_nDeltaTick");
|
||||
|
||||
private ref T Field<T>(int offset) where T : unmanaged
|
||||
{
|
||||
return ref Unsafe.AsRef<T>((void*)(Handle + offset));
|
||||
}
|
||||
|
||||
public int DeltaTick
|
||||
{
|
||||
get => Field<int>(m_nDeltaTick);
|
||||
set => Field<int>(m_nDeltaTick) = value;
|
||||
}
|
||||
|
||||
public void ForceFullUpdate() => DeltaTick = -1;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
|
@ -131,6 +131,7 @@ namespace src.utils
|
|||
new LanguageInfo("PT-BR, PT, BR, AO, CV, GW, MZ, ST, TL", "pt-br"),
|
||||
new LanguageInfo("FR, MC, HT", "fr"),
|
||||
new LanguageInfo("DE, AT, CH, LI, LU, BE", "de"),
|
||||
new LanguageInfo("RU, KZ, BY, KG, TJ, UZ, TM, AM, AZ, GE, MD", "ru"),
|
||||
new LanguageInfo("TR", "tr"),
|
||||
new LanguageInfo("CZ", "cs"),
|
||||
new LanguageInfo("PL", "pl"),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue