v1.21.1.b8

This commit is contained in:
Juzlus 2026-04-26 10:36:05 +02:00
parent abd3aed8fd
commit 10dbf6629e
77 changed files with 1507 additions and 974 deletions

View file

@ -15,14 +15,19 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.364" /> <PackageReference Include="CounterStrikeSharp.API" Version="1.0.367" />
<PackageReference Include="CS2TraceRay" Version="1.0.9" />
<PackageReference Include="MaxMind.Db" Version="5.0.0"> <PackageReference Include="MaxMind.Db" Version="5.0.0">
</PackageReference> </PackageReference>
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
</ItemGroup> </ItemGroup>
<!-- Relative path to the WASDMenuAPI source code --> <ItemGroup>
<Reference Include="RayTraceApi">
<HintPath>libs/RayTraceApi.dll</HintPath>
</Reference>
</ItemGroup>
<!-- Relative path to the WASDMenuAPI source code -->
<ItemGroup> <ItemGroup>
<ProjectReference Include="../WASDMenuAPI - SRC Files/WASDMenuAPI.csproj" /> <ProjectReference Include="../WASDMenuAPI - SRC Files/WASDMenuAPI.csproj" />
</ItemGroup> </ItemGroup>

Binary file not shown.

View file

@ -17,6 +17,7 @@ namespace src.command
private static bool gamePaused = false; private static bool gamePaused = false;
private static Config.SettingsModel config = Config.LoadedConfig; private static Config.SettingsModel config = Config.LoadedConfig;
private static readonly ConcurrentDictionary<string, CommandInfo.CommandCallback> oldCommands = []; private static readonly ConcurrentDictionary<string, CommandInfo.CommandCallback> oldCommands = [];
private static readonly ConcurrentDictionary<uint, int> nextSkill = [];
private static readonly object setLock = new(); private static readonly object setLock = new();
public static void Load() public static void Load()
@ -47,6 +48,7 @@ namespace src.command
{ SplitCommands(config.NormalCommands.SetStaticSkillCommand.Alias), ("Set static skill", Command_SetStaticSkill) }, { SplitCommands(config.NormalCommands.SetStaticSkillCommand.Alias), ("Set static skill", Command_SetStaticSkill) },
{ SplitCommands(config.NormalCommands.ChangeLanguageCommand.Alias), ("Change language", Command_ChangeLanguage) }, { SplitCommands(config.NormalCommands.ChangeLanguageCommand.Alias), ("Change language", Command_ChangeLanguage) },
{ SplitCommands(config.NormalCommands.ReloadCommand.Alias), ("Reaload configs", Command_Reload) }, { SplitCommands(config.NormalCommands.ReloadCommand.Alias), ("Reaload configs", Command_Reload) },
{ SplitCommands(config.NormalCommands.NextCommand.Alias), ("Next skill", Command_Next) },
{ SplitCommands(config.VotingCommands.ChangeMapCommand.Alias), ("Change map", Command_ChangeMap) }, { SplitCommands(config.VotingCommands.ChangeMapCommand.Alias), ("Change map", Command_ChangeMap) },
{ SplitCommands(config.VotingCommands.StartGameCommand.Alias), ("Start game", Command_StartGame) }, { SplitCommands(config.VotingCommands.StartGameCommand.Alias), ("Start game", Command_StartGame) },
@ -142,7 +144,7 @@ namespace src.command
{ {
Instance.SkillAction(skillPlayer.Skill.ToString(), "DisableSkill", [targetPlayer]); Instance.SkillAction(skillPlayer.Skill.ToString(), "DisableSkill", [targetPlayer]);
skillPlayer.Skill = skill.Skill; skillPlayer.Skill = skill.Skill;
skillPlayer.SpecialSkill = src.player.Skills.None; skillPlayer.SpecialSkill = Skills.None;
Instance.SkillAction(skill.Skill.ToString(), "EnableSkill", [targetPlayer]); Instance.SkillAction(skill.Skill.ToString(), "EnableSkill", [targetPlayer]);
skillPlayer.SkillDescriptionHudExpired = DateTime.Now.AddSeconds(Config.LoadedConfig.SkillDescriptionDuration); skillPlayer.SkillDescriptionHudExpired = DateTime.Now.AddSeconds(Config.LoadedConfig.SkillDescriptionDuration);
@ -337,7 +339,7 @@ namespace src.command
var pawn = player.PlayerPawn.Value; var pawn = player.PlayerPawn.Value;
if (int.TryParse(command.GetArg(1), out int health)) if (int.TryParse(command.GetArg(1), out int health))
SkillUtils.AddHealth(pawn, health - pawn.Health, health); SkillUtils.AddHealth(pawn, health - pawn.Health, health);
player.PrintToChat($" {ChatColors.Green}{player.GetTranslation("set_health")}"); player.PrintToChat($" {ChatColors.Green}{player.GetTranslation("set_health")}");
} }
@ -578,5 +580,48 @@ namespace src.command
} }
} }
} }
[CommandHelper(minArgs: 0, whoCanExecute: CommandUsage.CLIENT_ONLY)]
private static void Command_Next(CCSPlayerController? player, CommandInfo command)
{
if (player == null || !player.IsValid) return;
Debug.WriteToDebug($"Player {player.PlayerName} used the css_next {command.ArgString} command.");
if (!string.IsNullOrEmpty(config.NormalCommands.NextCommand.Permissions) && !AdminManager.PlayerHasPermissions(player, config.NormalCommands.NextCommand.Permissions)) return;
var skillsList = SkillData.Skills.OrderBy(s => s.Skill.ToString()).ToList();
if (skillsList.Count == 0) return;
nextSkill.TryGetValue(player.Index, out int currentIndex);
int nextIndex = (currentIndex + 1) % skillsList.Count;
string arg = command.GetArg(1);
if (!string.IsNullOrEmpty(arg))
{
if (arg == "-1")
nextIndex--;
else
nextIndex = int.Parse(arg);
}
var skill = skillsList[nextIndex];
player.PrintToChat(nextIndex.ToString());
var skillPlayer = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (skillPlayer == null) return;
Instance.SkillAction(skillPlayer.Skill.ToString(), "DisableSkill", [player]);
skillPlayer.Skill = skill.Skill;
skillPlayer.SpecialSkill = Skills.None;
nextSkill[player.Index] = nextIndex;
Instance.SkillAction(skill.Skill.ToString(), "EnableSkill", [player]);
skillPlayer.SkillDescriptionHudExpired = DateTime.Now.AddSeconds(Config.LoadedConfig.SkillDescriptionDuration);
if (skill.Display)
SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skill.Skill)}{ChatColors.Lime}: {player.GetSkillDescription(skill.Skill)}", border: "b");
}
} }
} }

View file

@ -16,15 +16,22 @@
"Shoot_Secondary": { "Shoot_Secondary": {
"signatures": { "signatures": {
"library": "server", "library": "server",
"windows": "48 89 5C 24 ? 57 48 83 EC 20 44 0F BF C2", "windows": "48 89 5C 24 ? 57 48 83 EC 20 48 8B 01 48 8B F9 0F BF DA",
"linux": "55 48 89 E5 41 54 53 48 89 FB 66 83 FE 65" "linux": "55 48 8D 15 ? ? ? ? 48 89 E5 41 54 41 89 F4 53 48 8B 07 48 89 FB 48 8B 80 ? ? ? ? 48 39 D0 0F 85"
} }
}, },
"SnapViewAngles": { "SnapViewAngles": {
"signatures": { "signatures": {
"library": "server", "library": "server",
"windows": "48 89 5C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 55 48 8D 6C 24 ? 48 81 EC ? ? ? ? 48 8B DA 48 8B F1 48 8D 55", "windows": "48 89 5C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 55 48 8D 6C 24 ? 48 81 EC ? ? ? ? 48 8B DA 48 8B F1 48 8D 55",
"linux": "55 48 89 E5 41 57 41 56 41 55 41 54 53 48 89 FB 48 89 F7 48 81 EC ? ? ? ? E8 ? ? ? ? 48 8B 93" "linux": "55 48 89 E5 41 57 49 89 FF 48 89 F7 41 56 41 55 41 54 53 48 81 EC"
}
},
"CCSPlayerController_HandleCommandDrop": {
"signatures": {
"library": "server",
"windows": "48 89 5C 24 ? 57 48 83 EC ? 48 8B FA E8 ? ? ? ? 48 8B D8",
"linux": "55 48 89 E5 41 54 49 89 F4 53 E8 ? ? ? ? 48 85 C0 74 ? 48 89 C3"
} }
} }
} }

View file

@ -28,7 +28,7 @@ namespace src
public override string ModuleName => "[CS2] [ jRandomSkills ]"; public override string ModuleName => "[CS2] [ jRandomSkills ]";
public override string ModuleAuthor => "D3X, Juzlus"; public override string ModuleAuthor => "D3X, Juzlus";
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.1.b7"; public override string ModuleVersion => "1.2.1.b8";
public override void Load(bool hotReload) public override void Load(bool hotReload)
{ {
@ -213,8 +213,9 @@ namespace src
{ "WASDMenuAPI", "./WASDMenuAPI.dll" }, { "WASDMenuAPI", "./WASDMenuAPI.dll" },
{ "MaxMind", "./MaxMind.Db.dll" }, { "MaxMind", "./MaxMind.Db.dll" },
{ "GeoLite2", "./packages/GeoLite2-Country.mmdb" }, { "GeoLite2", "./packages/GeoLite2-Country.mmdb" },
{ "CS2TraceRay", "./../../shared/CS2TraceRay/CS2TraceRay.dll" }, { "RayTraceApi", "./../../shared/RayTraceApi/RayTraceApi.dll" },
{ "CS2TraceRay gamedata", "./../../gamedata/CS2TraceRay.gamedata.json" }, { "RayTraceImpl", "./../../plugins/RayTraceImpl/RayTraceImpl.dll" },
{ "RayTrace MetaMod", "./../../../metamod/RayTrace.vdf" },
{ "jRandomSkills gamedata", "./../../gamedata/jRandomSkills.gamedata.json" } { "jRandomSkills gamedata", "./../../gamedata/jRandomSkills.gamedata.json" }
}; };
@ -263,7 +264,7 @@ namespace src
private static async Task<string?> GetLatestVersion() private static async Task<string?> GetLatestVersion()
{ {
using HttpClient client = new HttpClient(); using HttpClient client = new();
client.DefaultRequestHeaders.UserAgent.Add(new System.Net.Http.Headers.ProductInfoHeaderValue("jRandomSkills", "1.0")); client.DefaultRequestHeaders.UserAgent.Add(new System.Net.Http.Headers.ProductInfoHeaderValue("jRandomSkills", "1.0"));
const string URL = "https://api.github.com/repos/Juzlus/jRandomSkills/releases/latest"; const string URL = "https://api.github.com/repos/Juzlus/jRandomSkills/releases/latest";

View file

@ -29,7 +29,9 @@ public interface ISkill
public static void WeaponEquip(EventItemEquip _) { } public static void WeaponEquip(EventItemEquip _) { }
public static void WeaponPickup(EventItemPickup _) { } public static void WeaponPickup(EventItemPickup _) { }
public static void WeaponReload(EventWeaponReload _) { } public static void WeaponReload(EventWeaponReload _) { }
public static bool WeaponDrop(DynamicHook _, CCSPlayerController __) { return false; }
public static void GrenadeThrown(EventGrenadeThrown _) { } public static void GrenadeThrown(EventGrenadeThrown _) { }
public static void BulletImpact(EventBulletImpact _) { }
public static void BombBeginplant(EventBombBeginplant _) { } public static void BombBeginplant(EventBombBeginplant _) { }
public static void BombAbortplant(EventBombAbortplant _) { } public static void BombAbortplant(EventBombAbortplant _) { }
@ -146,7 +148,6 @@ public enum Skills
RadarHack, RadarHack,
Rambo, Rambo,
RandomWeapon, RandomWeapon,
RCMelon,
ReZombie, ReZombie,
ReactiveArmor, ReactiveArmor,
Regeneration, Regeneration,

View file

@ -2,15 +2,14 @@ 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;
using CounterStrikeSharp.API.Modules.Commands;
using CounterStrikeSharp.API.Modules.Cvars; using CounterStrikeSharp.API.Modules.Cvars;
using CounterStrikeSharp.API.Modules.Events; using CounterStrikeSharp.API.Modules.Events;
using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Memory;
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
using CounterStrikeSharp.API.Modules.UserMessages; using CounterStrikeSharp.API.Modules.UserMessages;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using CS2TraceRay.Class; using RayTraceAPI;
using CS2TraceRay.Enum;
using CS2TraceRay.Struct;
using src.player.skills; using src.player.skills;
using src.utils; using src.utils;
using System.Collections.Concurrent; using System.Collections.Concurrent;
@ -40,6 +39,8 @@ namespace src.player
public static readonly ConcurrentDictionary<ulong, jSkill_SkillInfo> staticSkills = []; public static readonly ConcurrentDictionary<ulong, jSkill_SkillInfo> staticSkills = [];
private static readonly object setLock = new(); private static readonly object setLock = new();
private static readonly MemoryFunctionVoid<CBasePlayerPawn, CBasePlayerWeapon> DropWeaponFunc = new(GameData.GetSignature("CCSPlayerController_HandleCommandDrop"));
public static void Load() public static void Load()
{ {
Instance.RegisterEventHandler<EventPlayerConnectFull>(PlayerConnectFull); Instance.RegisterEventHandler<EventPlayerConnectFull>(PlayerConnectFull);
@ -78,9 +79,13 @@ namespace src.player
Instance.HookUserMessage(208, PlayerMakeSound); Instance.HookUserMessage(208, PlayerMakeSound);
VirtualFunctions.CBaseEntity_TakeDamageOldFunc.Hook(OnTakeDamage, HookMode.Pre); VirtualFunctions.CBaseEntity_TakeDamageOldFunc.Hook(OnTakeDamage, HookMode.Pre);
Instance.RegisterEventHandler<EventBulletImpact>(BulletImpact);
VirtualFunctions.CBaseTrigger_StartTouchFunc.Hook(OnTriggerEnter, HookMode.Post); VirtualFunctions.CBaseTrigger_StartTouchFunc.Hook(OnTriggerEnter, HookMode.Post);
VirtualFunctions.CBaseTrigger_EndTouchFunc.Hook(OnTriggerExit, HookMode.Pre); VirtualFunctions.CBaseTrigger_EndTouchFunc.Hook(OnTriggerExit, HookMode.Pre);
VirtualFunctions.CCSPlayer_ItemServices_CanAcquireFunc.Hook(OnWeaponCanAcquire, HookMode.Pre); VirtualFunctions.CCSPlayer_ItemServices_CanAcquireFunc.Hook(OnWeaponCanAcquire, HookMode.Pre);
DropWeaponFunc.Hook(WeaponDrop, HookMode.Pre);
} }
private static HookResult PlayerMakeSound(UserMessage um) private static HookResult PlayerMakeSound(UserMessage um)
@ -426,7 +431,34 @@ namespace src.player
return block ? HookResult.Stop : HookResult.Continue; return block ? HookResult.Stop : HookResult.Continue;
} }
} }
private static HookResult WeaponDrop(DynamicHook hook)
{
lock (setLock)
{
CCSPlayerController player = hook.GetParam<CCSPlayerController>(0);
if (player == null || !player.IsValid)
return HookResult.Continue;
var activeSkills = Instance.SkillPlayer
.Where(p => !p.IsDrawing)
.Select(p => p.Skill.ToString())
.Distinct();
bool block = false;
foreach (string skillName in activeSkills)
{
bool? result = (bool?)Instance.SkillAction(skillName, "WeaponDrop", [hook, player]);
if (result == true)
{
block = true;
break;
}
}
return block ? HookResult.Stop : HookResult.Continue;
}
}
private static void OnTick() private static void OnTick()
{ {
lock (setLock) lock (setLock)
@ -488,6 +520,8 @@ namespace src.player
var skillPlayer = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); var skillPlayer = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (skillPlayer == null) return HookResult.Continue; if (skillPlayer == null) return HookResult.Continue;
Instance.SkillAction(skillPlayer.Skill.ToString(), "DisableSkill", [player]);
var items = Instance.SkillPlayer.ToList(); var items = Instance.SkillPlayer.ToList();
Instance.SkillPlayer = [.. items.Where(p => p.SteamID != skillPlayer.SteamID)]; Instance.SkillPlayer = [.. items.Where(p => p.SteamID != skillPlayer.SteamID)];
@ -735,13 +769,13 @@ namespace src.player
Vector eyePos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z); Vector eyePos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z);
Vector endPos = eyePos + SkillUtils.GetForwardVector(pawn.EyeAngles) * 80; Vector endPos = eyePos + SkillUtils.GetForwardVector(pawn.EyeAngles) * 80;
ulong mask = pawn.Collision.CollisionAttribute.InteractsWith | (ulong)(Contents.Solid | Contents.Hitbox | Contents.Pickup | Contents.TouchAll | Contents.CarriedObject | Contents.CarriedWeapon | Contents.Debris); ulong mask = (ulong)(InteractionLayers.MASK_WORLD_ONLY | InteractionLayers.Player | InteractionLayers.NPC);
ulong contents = 0; ulong contents = 0;
CGameTrace trace = TraceRay.TraceShape(eyePos, endPos, mask, contents, player); var result = RayTrace.TraceShape(player, eyePos, endPos, mask, contents);
if (trace.DidHit()) if (result.HasValue && result.Value.DidHit)
{ {
var entity = Activator.CreateInstance(typeof(CBaseEntity), trace.HitEntity) as CBaseEntity; var entity = Activator.CreateInstance(typeof(CBaseEntity), result.Value.HitEntity) as CBaseEntity;
if (entity == null || !entity.IsValid) return; if (entity == null || !entity.IsValid) return;
string designer = entity.DesignerName; string designer = entity.DesignerName;
@ -768,12 +802,32 @@ namespace src.player
} }
} }
private static HookResult BulletImpact(EventBulletImpact @event, GameEventInfo info)
{
lock (setLock)
{
var activeSkills = Instance.SkillPlayer
.Where(p => !p.IsDrawing)
.Select(p => p.Skill.ToString())
.Distinct();
foreach (string skillName in activeSkills)
Instance.SkillAction(skillName, "BulletImpact", [@event]);
return HookResult.Continue;
}
}
private static void SetSkill() private static void SetSkill()
{ {
setSkillTimer = null; setSkillTimer = null;
lock (setLock) lock (setLock)
{ {
var validPlayers = Utilities.GetPlayers().Where(p => p.IsValid && !p.IsBot && !p.IsHLTV && p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist).ToList(); var validPlayers = Utilities.GetPlayers()
.Where(p => p != null && p.IsValid && !p.IsBot && !p.IsHLTV)
.Where(p => {
try { return p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist; }
catch { return false; }
}).ToList();
if (Config.LoadedConfig.GameMode == (int)Config.GameModes.TeamSkills) if (Config.LoadedConfig.GameMode == (int)Config.GameModes.TeamSkills)
{ {
@ -797,7 +851,7 @@ namespace src.player
foreach (var player in validPlayers) foreach (var player in validPlayers)
{ {
if (player == null) continue; if (player == null) continue;
var teammates = validPlayers.Where(p => p.Team == player.Team && p != player); var teammates = validPlayers.Where(p => p != null && p.IsValid && p.Team == player.Team && p != player).ToList();
string teammateSkills = ""; string teammateSkills = "";
var skillPlayer = Instance?.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); var skillPlayer = Instance?.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
@ -875,6 +929,8 @@ namespace src.player
Instance?.AddTimer(.2f, () => Instance?.AddTimer(.2f, () =>
{ {
if(player == null || !player.IsValid) return;
if (randomSkill.Display) if (randomSkill.Display)
SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(randomSkill.Skill)}{ChatColors.Lime}: {player.GetSkillDescription(randomSkill.Skill)}", SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(randomSkill.Skill)}{ChatColors.Lime}: {player.GetSkillDescription(randomSkill.Skill)}",
border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t");
@ -901,6 +957,8 @@ namespace src.player
{ {
Instance?.AddTimer(.6f, () => Instance?.AddTimer(.6f, () =>
{ {
if (player == null || !player.IsValid) return;
foreach (var teammate in teammates) foreach (var teammate in teammates)
{ {
var teammateInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == teammate.SteamID); var teammateInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == teammate.SteamID);

View file

@ -121,9 +121,15 @@ namespace src.player.skills
if (enemyPawn == null || enemyPawn.AbsOrigin == null) return; if (enemyPawn == null || enemyPawn.AbsOrigin == null) return;
Vector myEyePos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z); Vector myEyePos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z);
Vector enemyEyePos = new(enemyPawn.AbsOrigin.X, enemyPawn.AbsOrigin.Y, enemyPawn.AbsOrigin.Z + enemyPawn.ViewOffset.Z + SkillsInfo.GetValue<float>(skillName, "offsetZ"));
Vector direction = enemyEyePos - myEyePos; Vector diff = SkillUtils.GetForwardVector(enemyPawn.AbsRotation!) * 5;
Vector enemyHead = new(
enemyPawn.AbsOrigin.X + diff.X,
enemyPawn.AbsOrigin.Y + diff.Y,
enemyPawn.AbsOrigin.Z + enemyPawn.ViewOffset.Z + 2
);
Vector direction = enemyHead - myEyePos;
QAngle angle = VectorToAngle(direction); QAngle angle = VectorToAngle(direction);
pawn.Look(angle); pawn.Look(angle);
@ -145,11 +151,10 @@ namespace src.player.skills
public DateTime Cooldown { get; set; } public DateTime Cooldown { get; set; }
} }
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#fa7b48", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = true, bool needsTeammates = false, string requiredPermission = "", float cooldown = 20f, float duration = .3f, float offsetZ = 0) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#fa7b48", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = true, bool needsTeammates = false, string requiredPermission = "", float cooldown = 20f, float duration = .3f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)
{ {
public float Cooldown { get; set; } = cooldown; public float Cooldown { get; set; } = cooldown;
public float Duration { get; set; } = duration; public float Duration { get; set; } = duration;
public float Offset { get; set; } = offsetZ;
} }
} }
} }

View file

@ -40,7 +40,7 @@ namespace src.player.skills
{ {
if (skillInfo.LastRotations == null || skillInfo.LastPositions == null) continue; if (skillInfo.LastRotations == null || skillInfo.LastPositions == null) continue;
skillInfo.LastPositions.Enqueue(new Vector(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z)); skillInfo.LastPositions.Enqueue(new Vector(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z));
skillInfo.LastRotations.Enqueue(new QAngle(pawn.EyeAngles.X, pawn.EyeAngles.Y, pawn.EyeAngles.Z)); skillInfo.LastRotations.Enqueue(new QAngle(pawn.V_angle.X, pawn.V_angle.Y, 0));
if (skillInfo.LastRotations.Count > SkillsInfo.GetValue<int>(skillName, "secondsInBack")) if (skillInfo.LastRotations.Count > SkillsInfo.GetValue<int>(skillName, "secondsInBack"))
{ {
skillInfo.LastPositions.TryDequeue(out _); skillInfo.LastPositions.TryDequeue(out _);
@ -106,7 +106,10 @@ namespace src.player.skills
Vector? lastPosition = skillInfo.LastPositions.FirstOrDefault(); Vector? lastPosition = skillInfo.LastPositions.FirstOrDefault();
QAngle? lastRotation = skillInfo.LastRotations.FirstOrDefault(); QAngle? lastRotation = skillInfo.LastRotations.FirstOrDefault();
if (lastPosition != null && lastRotation != null) if (lastPosition != null && lastRotation != null)
playerPawn.Teleport(lastPosition, lastRotation, null); {
playerPawn.Teleport(lastPosition, null, null);
playerPawn.Look(lastRotation);
}
} }
} }
} }

View file

@ -11,7 +11,7 @@ namespace src.player.skills
public class Baseball : ISkill public class Baseball : ISkill
{ {
private const Skills skillName = Skills.Baseball; private const Skills skillName = Skills.Baseball;
private static readonly ConcurrentDictionary<CDecoyProjectile, byte> decoys = []; private static readonly ConcurrentDictionary<uint, byte> decoys = [];
public static void LoadSkill() public static void LoadSkill()
{ {
@ -50,7 +50,7 @@ namespace src.player.skills
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo?.Skill != skillName) return; if (playerInfo?.Skill != skillName) return;
decoys.TryAdd(decoy, 0); decoys.TryAdd(decoy.Index, 0);
decoy.Collision.CollisionAttribute.InteractsWith = pawn.Collision.CollisionAttribute.InteractsWith; decoy.Collision.CollisionAttribute.InteractsWith = pawn.Collision.CollisionAttribute.InteractsWith;
decoy.Collision.CollisionGroup = pawn.Collision.CollisionGroup; decoy.Collision.CollisionGroup = pawn.Collision.CollisionGroup;
@ -60,25 +60,33 @@ namespace src.player.skills
{ {
var player = @event.Userid; var player = @event.Userid;
if (player == null || !player.IsValid) return; if (player == null || !player.IsValid) return;
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo?.Skill != skillName) return; if (playerInfo?.Skill != skillName) return;
var decoy = decoys.FirstOrDefault(d => d.Key.Index == @event.Entityid).Key; if (decoys.ContainsKey((uint)@event.Entityid))
if (decoy != null && decoy.IsValid) {
decoy.AcceptInput("Kill"); var decoy = Utilities.GetEntityFromIndex<CDecoyProjectile>(@event.Entityid);
if (decoy != null && decoy.IsValid)
decoy.AcceptInput("Kill");
}
} }
public static void OnTick() public static void OnTick()
{ {
foreach (var decoy in decoys.Keys) foreach (var decoyIndex in decoys.Keys)
{ {
if (!decoy.IsValid) var decoy = Utilities.GetEntityFromIndex<CDecoyProjectile>((int)decoyIndex);
if (decoy == null || !decoy.IsValid)
{ {
decoys.TryRemove(decoy, out _); decoys.TryRemove(decoyIndex, out _);
continue; continue;
} }
decoy.Bounces = 0; decoy.Bounces = 0;
if (Server.TickCount % 8 != 0) continue; if (Server.TickCount % 8 != 0) continue;
var vel = decoy.AbsVelocity; var vel = decoy.AbsVelocity;
float speed = vel.Length(); float speed = vel.Length();
float targetSpeed = Math.Min(speed * SkillsInfo.GetValue<float>(skillName, "speedMultipier"), SkillsInfo.GetValue<float>(skillName, "maxSpeed")); float targetSpeed = Math.Min(speed * SkillsInfo.GetValue<float>(skillName, "speedMultipier"), SkillsInfo.GetValue<float>(skillName, "maxSpeed"));

View file

@ -45,16 +45,8 @@ namespace src.player.skills
if (pawn == null || !pawn.IsValid || pawn.LifeState != (int)LifeState_t.LIFE_ALIVE) return; if (pawn == null || !pawn.IsValid || pawn.LifeState != (int)LifeState_t.LIFE_ALIVE) return;
var currentPosition = pawn.AbsOrigin; QAngle look = new(pawn.V_angle.X, pawn.V_angle.Y + 180, 0);
var currentAngles = pawn.EyeAngles; pawn.Look(look);
QAngle newAngles = new(
currentAngles.X,
currentAngles.Y + 180,
currentAngles.Z
);
pawn.Teleport(currentPosition, newAngles, new Vector(0, 0, 0));
} }
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#00FF00", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float chanceFrom = .2f, float chanceTo = .4f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#00FF00", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float chanceFrom = .2f, float chanceTo = .4f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)

View file

@ -31,7 +31,7 @@ namespace src.player.skills
{ {
var playerPawn = player.PlayerPawn.Value; var playerPawn = player.PlayerPawn.Value;
if (playerPawn == null || !playerPawn.IsValid) return; if (playerPawn == null || !playerPawn.IsValid) return;
if (JumpBan.bannedPlayers.ContainsKey(playerPawn)) return; if (JumpBan.bannedPlayers.ContainsKey(player.Index)) return;
var flags = (PlayerFlags)playerPawn.Flags; var flags = (PlayerFlags)playerPawn.Flags;
var buttons = player.Buttons; var buttons = player.Buttons;

View file

@ -11,7 +11,7 @@ namespace src.player.skills
public class C4Camouflage : ISkill public class C4Camouflage : ISkill
{ {
private const Skills skillName = Skills.C4Camouflage; private const Skills skillName = Skills.C4Camouflage;
private static readonly ConcurrentDictionary<CCSPlayerController, byte> invisiblePlayers = []; private static readonly ConcurrentDictionary<uint, byte> invisiblePlayers = [];
private const string bloodParticle = "particles/blood_impact/blood_impact_high.vpcf"; private const string bloodParticle = "particles/blood_impact/blood_impact_high.vpcf";
public static void LoadSkill() public static void LoadSkill()
@ -44,16 +44,16 @@ namespace src.player.skills
if (playerInfo?.Skill != skillName) return; if (playerInfo?.Skill != skillName) return;
if (weapon == "c4") if (weapon == "c4")
invisiblePlayers.TryAdd(player, 0); invisiblePlayers.TryAdd(player.Index, 0);
else else
invisiblePlayers.TryRemove(player, out _); invisiblePlayers.TryRemove(player.Index, out _);
} }
public static void OnTick() public static void OnTick()
{ {
foreach (var player in Utilities.GetPlayers()) foreach (var player in Utilities.GetPlayers())
if (!player.PawnIsAlive) if (!player.PawnIsAlive)
invisiblePlayers.TryRemove(player, out _); invisiblePlayers.TryRemove(player.Index, out _);
} }
public static void CheckTransmit([CastFrom(typeof(nint))] CCheckTransmitInfoList infoList) public static void CheckTransmit([CastFrom(typeof(nint))] CCheckTransmitInfoList infoList)
@ -72,10 +72,15 @@ namespace src.player.skills
if (targetInfo?.Skill == skillName) isObservingC4Camouflage = true; if (targetInfo?.Skill == skillName) isObservingC4Camouflage = true;
} }
foreach (var _player in invisiblePlayers.Keys) foreach (var playerIndex in invisiblePlayers.Keys)
if (player.SteamID != _player.SteamID && !isObservingC4Camouflage) {
var playerController = Utilities.GetPlayerFromIndex((int)playerIndex);
if (playerController == null || !playerController.IsValid || playerController.SteamID == player.SteamID)
continue;
if (!isObservingC4Camouflage)
{ {
var playerPawn = _player.PlayerPawn.Value; var playerPawn = playerController.PlayerPawn.Value;
if (playerPawn == null || !playerPawn.IsValid) continue; if (playerPawn == null || !playerPawn.IsValid) continue;
var entity = Utilities.GetEntityFromIndex<CBaseEntity>((int)playerPawn.Index); var entity = Utilities.GetEntityFromIndex<CBaseEntity>((int)playerPawn.Index);
@ -89,6 +94,7 @@ namespace src.player.skills
if (bombEntity == null || !bombEntity.IsValid) continue; if (bombEntity == null || !bombEntity.IsValid) continue;
info.TransmitEntities.Remove(bombEntity.Index); info.TransmitEntities.Remove(bombEntity.Index);
} }
}
} }
} }
@ -105,19 +111,19 @@ namespace src.player.skills
var activeWeapon = playerPawn.WeaponServices.ActiveWeapon.Value; var activeWeapon = playerPawn.WeaponServices.ActiveWeapon.Value;
if (activeWeapon.DesignerName != "weapon_c4") return; if (activeWeapon.DesignerName != "weapon_c4") return;
invisiblePlayers.TryAdd(player, 0); invisiblePlayers.TryAdd(player.Index, 0);
} }
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
{ {
invisiblePlayers.TryRemove(player, out _); invisiblePlayers.TryRemove(player.Index, out _);
} }
public static void PlayerHurt(EventPlayerHurt @event) public static void PlayerHurt(EventPlayerHurt @event)
{ {
var player = @event.Userid; var player = @event.Userid;
if (player == null || !player.IsValid) return; if (player == null || !player.IsValid) return;
if (!invisiblePlayers.ContainsKey(player)) return; if (!invisiblePlayers.ContainsKey(player.Index)) return;
var playerPawn = player.PlayerPawn.Value; var playerPawn = player.PlayerPawn.Value;
if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return; if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return;

View file

@ -1,10 +1,10 @@
using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using static src.jRandomSkills;
using System.Collections.Concurrent;
using src.utils; using src.utils;
using CounterStrikeSharp.API; using System.Collections.Concurrent;
using static src.jRandomSkills;
namespace src.player.skills namespace src.player.skills
{ {
@ -13,6 +13,7 @@ namespace src.player.skills
private const Skills skillName = Skills.CarefulBullets; private const Skills skillName = Skills.CarefulBullets;
private static readonly ConcurrentDictionary<ulong, byte> targetPlayers = []; private static readonly ConcurrentDictionary<ulong, byte> targetPlayers = [];
private static readonly ConcurrentDictionary<ulong, bool> lastShot = []; private static readonly ConcurrentDictionary<ulong, bool> lastShot = [];
private static readonly ConcurrentDictionary<ulong, int> hitPlayer = [];
private static readonly object setLock = new(); private static readonly object setLock = new();
public static void LoadSkill() public static void LoadSkill()
@ -26,6 +27,7 @@ namespace src.player.skills
{ {
targetPlayers.Clear(); targetPlayers.Clear();
lastShot.Clear(); lastShot.Clear();
hitPlayer.Clear();
} }
foreach (var player in Utilities.GetPlayers()) foreach (var player in Utilities.GetPlayers())
{ {
@ -100,48 +102,70 @@ namespace src.player.skills
player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_incorrect_enemy_index")}");
} }
public static void BulletImpact(EventBulletImpact @event)
{
var player = @event.Userid;
if (player == null || !player.IsValid) return;
var playerPawn = player.PlayerPawn.Value;
if (playerPawn == null || !playerPawn.IsValid) return;
if (!targetPlayers.ContainsKey(player.SteamID) || !player.PawnIsAlive)
return;
ulong steamID = player.SteamID;
Server.NextFrame(() =>
{
if (player == null || !player.IsValid) return;
if (playerPawn == null || !playerPawn.IsValid) return;
bool ishitPlayer = hitPlayer.TryGetValue(steamID, out int tick) && tick + 10 >= Server.TickCount;
if (!lastShot.ContainsKey(steamID))
{
lastShot.TryAdd(steamID, ishitPlayer);
Instance.AddTickTimer(1, () =>
{
if (lastShot.TryRemove(steamID, out bool didHit) && !didHit)
SkillUtils.TakeHealth(playerPawn, SkillsInfo.GetValue<int>(skillName, "damageAfterMiss"));
lastShot.TryRemove(steamID, out _);
});
}
else if (ishitPlayer)
lastShot.TryUpdate(steamID, true, false);
});
}
public static void OnTakeDamage(DynamicHook h) public static void OnTakeDamage(DynamicHook h)
{ {
CEntityInstance param = h.GetParam<CEntityInstance>(0); CEntityInstance param = h.GetParam<CEntityInstance>(0);
CTakeDamageInfo param2 = h.GetParam<CTakeDamageInfo>(1); CTakeDamageInfo param2 = h.GetParam<CTakeDamageInfo>(1);
if (param?.Entity == null || param2?.Attacker?.Value == null) if (param == null || param.Entity == null || param2 == null || param2.Attacker == null || param2.Attacker.Value == null)
return; return;
CCSPlayerPawn attackerPawn = new(param2.Attacker.Value.Handle); CCSPlayerPawn attackerPawn = new(param2.Attacker.Value.Handle);
CCSPlayerPawn victimPawn = new(param.Handle);
if (attackerPawn.DesignerName != "player") if (attackerPawn.DesignerName != "player" || victimPawn.DesignerName != "player")
return; return;
if (attackerPawn == null || attackerPawn.Controller?.Value == null) if (attackerPawn == null || attackerPawn.Controller?.Value == null || victimPawn == null || victimPawn.Controller?.Value == null)
return; return;
CCSPlayerController attacker = attackerPawn.Controller.Value.As<CCSPlayerController>(); CCSPlayerController attacker = attackerPawn.Controller.Value.As<CCSPlayerController>();
if (!targetPlayers.ContainsKey(attacker.SteamID)) return;
if (!targetPlayers.ContainsKey(attacker.SteamID) || !attacker.PawnIsAlive) hitPlayer.AddOrUpdate(attacker.SteamID, Server.TickCount, (_, _) => Server.TickCount);
return;
bool hitPlayer = param.DesignerName == "player";
if (!lastShot.ContainsKey(attacker.SteamID))
{
lastShot.TryAdd(attacker.SteamID, hitPlayer);
Instance.AddTickTimer(1, () =>
{
if (lastShot.TryRemove(attacker.SteamID, out bool didHit) && !didHit)
SkillUtils.TakeHealth(attackerPawn, SkillsInfo.GetValue<int>(skillName, "damageAfterMiss"));
lastShot.TryRemove(attacker.SteamID, out _);
});
}
else if (hitPlayer)
lastShot.TryUpdate(attacker.SteamID, true, false);
} }
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
{ {
targetPlayers.TryRemove(player.SteamID, out _); targetPlayers.TryRemove(player.SteamID, out _);
lastShot.TryRemove(player.SteamID, out _); lastShot.TryRemove(player.SteamID, out _);
hitPlayer.TryRemove(player.SteamID, out _);
SkillUtils.CloseMenu(player); SkillUtils.CloseMenu(player);
} }

View file

@ -21,9 +21,9 @@ namespace src.player.skills
"weapon_xm1014", "weapon_mag7", "weapon_sawedoff", "weapon_m249", "weapon_xm1014", "weapon_mag7", "weapon_sawedoff", "weapon_m249",
"weapon_negev" "weapon_negev"
]; ];
private static readonly ConcurrentDictionary<CCSPlayerController, CBaseModelEntity> chickens = []; private static readonly ConcurrentDictionary<uint, uint> chickens = [];
private static readonly string defaultCTModel = "characters/models/ctm_sas/ctm_sas.vmdl"; private static readonly string defaultCTModel = "agents/models/ctm_sas/ctm_sas.vmdl";
private static readonly string defaultTModel = "characters/models/tm_phoenix/tm_phoenix.vmdl"; private static readonly string defaultTModel = "agents/models/tm_phoenix/tm_phoenix.vmdl";
private static readonly ConcurrentDictionary<ulong, string> originalModels = []; private static readonly ConcurrentDictionary<ulong, string> originalModels = [];
public static void LoadSkill() public static void LoadSkill()
@ -35,9 +35,14 @@ namespace src.player.skills
{ {
foreach (var player in Utilities.GetPlayers()) foreach (var player in Utilities.GetPlayers())
SetWeaponAttack(player, false); SetWeaponAttack(player, false);
foreach (var valuePair in chickens) foreach (var valuePair in chickens)
if (valuePair.Value != null && valuePair.Value.IsValid) {
valuePair.Value.AcceptInput("Kill"); var chicken = Utilities.GetEntityFromIndex<CBaseModelEntity>((int)valuePair.Value);
if (chicken != null && chicken.IsValid)
chicken.AcceptInput("Kill");
}
chickens.Clear(); chickens.Clear();
originalModels.Clear(); originalModels.Clear();
} }
@ -96,11 +101,12 @@ namespace src.player.skills
SetWeaponAttack(player, false); SetWeaponAttack(player, false);
} }
if (chickens.TryGetValue(player, out var chicken)) if (chickens.TryRemove(player.Index, out var chickenIndex))
{ {
var chicken = Utilities.GetEntityFromIndex<CBaseModelEntity>((int)chickenIndex);
if (chicken != null && chicken.IsValid) if (chicken != null && chicken.IsValid)
chicken.AcceptInput("Kill"); chicken.AcceptInput("Kill");
chickens.TryRemove(player, out _);
} }
if (originalModels.TryGetValue(player.SteamID, out var model)) if (originalModels.TryGetValue(player.SteamID, out var model))
@ -110,6 +116,9 @@ namespace src.player.skills
Server.NextFrame(() => Server.NextFrame(() =>
{ {
if (player == null || !player.IsValid) return;
if (pawn == null || !pawn.IsValid) return;
if (string.IsNullOrEmpty(model)) if (string.IsNullOrEmpty(model))
model = player.Team == CsTeam.Terrorist ? defaultTModel : defaultCTModel; model = player.Team == CsTeam.Terrorist ? defaultTModel : defaultCTModel;
@ -157,19 +166,27 @@ namespace src.player.skills
chickenModel.CBodyComponent.SceneNode.GetSkeletonInstance().Scale = 1; chickenModel.CBodyComponent.SceneNode.GetSkeletonInstance().Scale = 1;
Utilities.SetStateChanged(chickenModel, "CBaseEntity", "m_CBodyComponent"); Utilities.SetStateChanged(chickenModel, "CBaseEntity", "m_CBodyComponent");
Server.NextFrame(() => chickenModel.AcceptInput("SetScale", chickenModel, chickenModel, "1"));
Server.NextFrame(() => {
if (chickenModel == null || !chickenModel.IsValid) return;
chickenModel.AcceptInput("SetScale", chickenModel, chickenModel, "1");
});
chickenModel.AcceptInput("SetParent", playerPawn, playerPawn, "!activator"); chickenModel.AcceptInput("SetParent", playerPawn, playerPawn, "!activator");
chickens.TryAdd(player, chickenModel); chickens.TryAdd(player.Index, chickenModel.Index);
} }
public static void OnTick() public static void OnTick()
{ {
foreach (var valuePair in chickens) foreach (var valuePair in chickens)
{ {
var player = valuePair.Key; var playerIndex = valuePair.Key;
var chicken = valuePair.Value; var chickenIndex = valuePair.Value;
var player = Utilities.GetPlayerFromIndex((int)playerIndex);
if (player == null || !player.IsValid) continue; if (player == null || !player.IsValid) continue;
var chicken = Utilities.GetEntityFromIndex<CBaseModelEntity>((int)chickenIndex);
if (chicken == null || !chicken.IsValid) continue; if (chicken == null || !chicken.IsValid) continue;
var pawn = player.PlayerPawn.Value; var pawn = player.PlayerPawn.Value;

View file

@ -3,8 +3,7 @@ using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
using CounterStrikeSharp.API.Modules.Timers; using CounterStrikeSharp.API.Modules.Timers;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using CS2TraceRay.Class; using RayTraceAPI;
using CS2TraceRay.Struct;
using src.utils; using src.utils;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Drawing; using System.Drawing;
@ -17,7 +16,7 @@ namespace src.player.skills
public class Cypher : ISkill public class Cypher : ISkill
{ {
private const Skills skillName = Skills.Cypher; private const Skills skillName = Skills.Cypher;
private static readonly ConcurrentDictionary<CCSPlayerController, PlayerSkill> playersInfo = []; private static readonly ConcurrentDictionary<uint, PlayerSkill> playersInfo = [];
private static readonly object setLock = new(); private static readonly object setLock = new();
private const string cameraPropModel = "models/props/de_train/hr_train_s2/train_electronics/train_electronics_security_camera_01.vmdl"; private const string cameraPropModel = "models/props/de_train/hr_train_s2/train_electronics/train_electronics_security_camera_01.vmdl";
@ -42,16 +41,16 @@ namespace src.player.skills
{ {
var playerPawn = player.PlayerPawn.Value; var playerPawn = player.PlayerPawn.Value;
if (playerPawn?.CBodyComponent == null) return; if (playerPawn?.CBodyComponent == null) return;
if (playersInfo.TryGetValue(player, out var playerSkill)) if (playersInfo.TryGetValue(player.Index, out var playerSkill))
ChangeCamera(playerSkill); ChangeCamera(playerSkill);
} }
public static void EnableSkill(CCSPlayerController player) public static void EnableSkill(CCSPlayerController player)
{ {
if (player.PlayerPawn.Value == null || player.PlayerPawn.Value.CameraServices == null) return; if (player.PlayerPawn.Value == null || player.PlayerPawn.Value.CameraServices == null) return;
playersInfo.TryAdd(player, new PlayerSkill playersInfo.TryAdd(player.Index, new PlayerSkill
{ {
Player = player, Player = player.Index,
CameraProp = null, CameraProp = null,
CameraView = null, CameraView = null,
CameraActive = false, CameraActive = false,
@ -64,29 +63,36 @@ namespace src.player.skills
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
{ {
if (playersInfo.TryGetValue(player, out var playerSkill)) if (playersInfo.TryGetValue(player.Index, out var playerSkill))
{ {
ChangeCamera(playerSkill, true); ChangeCamera(playerSkill, true);
KillCamera(playerSkill); KillCamera(playerSkill);
} }
playersInfo.TryRemove(player, out _); playersInfo.TryRemove(player.Index, out _);
} }
private static void KillCamera(PlayerSkill playerSkill) private static void KillCamera(PlayerSkill playerSkill)
{ {
if (playerSkill.CameraView != null && playerSkill.CameraView.IsValid) if (playerSkill.CameraView != null && playerSkill.CameraView != 0)
{ {
playerSkill.CameraView.AcceptInput("Kill"); var cameraView = Utilities.GetEntityFromIndex<CDynamicProp>((int)playerSkill.CameraView);
if (cameraView != null && cameraView.IsValid)
cameraView.AcceptInput("Kill");
playerSkill.CameraView = null; playerSkill.CameraView = null;
playerSkill.CameraActive = false;
} }
if (playerSkill.CameraProp != null && playerSkill.CameraProp.IsValid) if (playerSkill.CameraProp != null && playerSkill.CameraProp != 0)
{ {
playerSkill.CameraProp.EmitSound("SolidMetal.BulletImpact"); var cameraProp = Utilities.GetEntityFromIndex<CDynamicProp>((int)playerSkill.CameraProp);
playerSkill.CameraProp.AcceptInput("Kill"); if (cameraProp != null && cameraProp.IsValid)
{
cameraProp.EmitSound("SolidMetal.BulletImpact");
cameraProp.AcceptInput("Kill");
}
playerSkill.CameraProp = null; playerSkill.CameraProp = null;
} }
playerSkill.CameraActive = false;
playerSkill.NextCamera = Server.TickCount + SkillsInfo.GetValue<float>(skillName, "Cooldown") * 64; playerSkill.NextCamera = Server.TickCount + SkillsInfo.GetValue<float>(skillName, "Cooldown") * 64;
} }
@ -94,65 +100,88 @@ namespace src.player.skills
{ {
foreach (var playerSkill in playersInfo.Values) foreach (var playerSkill in playersInfo.Values)
{ {
if (playerSkill.CameraActive && playerSkill.CameraView != null && playerSkill.CameraView.IsValid) if (playerSkill.CameraActive && playerSkill.CameraView != null && playerSkill.CameraView != 0)
{ {
var pawn = playerSkill.Player.PlayerPawn.Value; var enemy = Utilities.GetPlayerFromIndex((int)playerSkill.Player);
if (pawn == null || !pawn.IsValid) continue; if (enemy == null || !enemy.IsValid || enemy.PlayerPawn == null) continue;
if (pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE) var enemyPawn = enemy.PlayerPawn.Value;
if (enemyPawn == null || !enemyPawn.IsValid) continue;
if (enemyPawn.LifeState != (byte)LifeState_t.LIFE_ALIVE)
{ {
DisableSkill(playerSkill.Player); DisableSkill(enemy);
continue; continue;
} }
playerSkill.CameraView.Teleport(null, pawn.V_angle);
var cameraView = Utilities.GetEntityFromIndex<CDynamicProp>((int)playerSkill.CameraView);
if (cameraView == null || !cameraView.IsValid) continue;
cameraView.Teleport(null, enemyPawn.V_angle);
} }
UpdateHUD(playerSkill); UpdateHUD(playerSkill);
} }
} }
private static void ChangeCamera(PlayerSkill player, bool forceToDefault = false) private static void ChangeCamera(PlayerSkill playerInfo, bool forceToDefault = false)
{ {
player.CameraActive = forceToDefault ? false : !player.CameraActive; var player = Utilities.GetPlayerFromIndex((int)playerInfo.Player);
if (player.CameraProp == null && !forceToDefault) if (player == null || !player.IsValid) return;
playerInfo.CameraActive = forceToDefault ? false : !playerInfo.CameraActive;
if (playerInfo.CameraProp == null && !forceToDefault)
{ {
if (player.NextCamera > Server.TickCount) return; if (playerInfo.NextCamera > Server.TickCount) return;
player.CameraProp = CreateCameraProp(player.Player);
if (player.CameraProp == null) var newProp = CreateCameraProp(player);
playerInfo.CameraProp = newProp?.Index ?? null;
if (playerInfo.CameraProp == null)
{ {
player.NoSpace = Server.TickCount + (64 * 2); playerInfo.NoSpace = Server.TickCount + (64 * 2);
return; return;
} }
player.CameraView = CreateCameraView(player.Player); else
if (player.CameraView == null) return; playerInfo.CameraView = CreateCameraView(newProp)?.Index ?? null;
if (playerInfo.CameraView == null) return;
} }
var pawn = player.Player.PlayerPawn.Value; var pawn = player.PlayerPawn.Value;
if (player.PlayerCameraRaw == 0) if (playerInfo.PlayerCameraRaw == 0)
return; return;
BlockWeapon(player.Player, player.CameraActive); BlockWeapon(player, playerInfo.CameraActive);
Server.NextWorldUpdate(() => Server.NextWorldUpdate(() =>
{ {
if (pawn != null && pawn.LifeState == (byte)LifeState_t.LIFE_ALIVE) if (pawn != null && pawn.LifeState == (byte)LifeState_t.LIFE_ALIVE)
{ {
if (player.CameraActive && player.CameraProp != null) if (playerInfo.CameraActive && playerInfo.CameraProp != null)
{ {
if ( pawn.AbsRotation != null) if (pawn.AbsRotation != null)
player.LastAngle = new QAngle(pawn.AbsRotation.X, pawn.AbsRotation.Y, pawn.AbsRotation.Z); playerInfo.LastAngle = new QAngle(pawn.V_angle.X, pawn.V_angle.Y, 0);
pawn.Teleport(null, player.CameraProp.AbsRotation);
var cameraProp = Utilities.GetEntityFromIndex<CDynamicProp>((int)playerInfo.CameraProp);
if (cameraProp == null || !cameraProp.IsValid) return;
pawn.Teleport(null, cameraProp.AbsRotation);
} }
else if (!forceToDefault) else if (!forceToDefault)
pawn.Teleport(null, player.LastAngle); {
pawn.Look(playerInfo.LastAngle);
}
} }
if (player.CameraActive && player.CameraView != null) if (playerInfo.CameraActive && playerInfo.CameraView != null)
{ {
pawn!.CameraServices!.ViewEntity.Raw = player.CameraView.EntityHandle.Raw; var cameraView = Utilities.GetEntityFromIndex<CDynamicProp>((int)playerInfo.CameraView);
SkillUtils.ApplyScreenColor(player.Player, 0, 0, 255, 20, 100, 1020); if (cameraView == null || !cameraView.IsValid) return;
ulong? playerSteamID = player.Player?.SteamID; pawn!.CameraServices!.ViewEntity.Raw = cameraView.EntityHandle.Raw;
if (playerSteamID == null) return; SkillUtils.ApplyScreenColor(player, 0, 0, 255, 20, 100, 1020);
ulong playerSteamID = player.SteamID;
Timer? cameraTimer = null; Timer? cameraTimer = null;
cameraTimer = jRandomSkills.Instance.AddTimer(2f, () => cameraTimer = jRandomSkills.Instance.AddTimer(2f, () =>
@ -164,7 +193,7 @@ namespace src.player.skills
return; return;
} }
if (!playersInfo.TryGetValue(target, out var playerSkill) || playerSkill.CameraActive == false) if (!playersInfo.TryGetValue(target.Index, out var playerSkill) || playerSkill.CameraActive == false)
{ {
cameraTimer?.Kill(); cameraTimer?.Kill();
return; return;
@ -174,7 +203,7 @@ namespace src.player.skills
}, TimerFlags.STOP_ON_MAPCHANGE | TimerFlags.REPEAT); }, TimerFlags.STOP_ON_MAPCHANGE | TimerFlags.REPEAT);
} }
else else
pawn!.CameraServices!.ViewEntity.Raw = player.PlayerCameraRaw; pawn!.CameraServices!.ViewEntity.Raw = playerInfo.PlayerCameraRaw;
Utilities.SetStateChanged(pawn, "CBasePlayerPawn", "m_pCameraServices"); Utilities.SetStateChanged(pawn, "CBasePlayerPawn", "m_pCameraServices");
}); });
@ -182,6 +211,18 @@ namespace src.player.skills
private static CDynamicProp? CreateCameraProp(CCSPlayerController player) private static CDynamicProp? CreateCameraProp(CCSPlayerController player)
{ {
var playerPawn = player.PlayerPawn.Value;
if (playerPawn == null || !playerPawn.IsValid) return null;
Vector? cameraVector = GetNewCameraPosition(player);
if (cameraVector == null) return null;
Vector diffVector = SkillUtils.GetForwardVector(playerPawn.V_angle) * 10;
Vector finalPos = new(cameraVector.X + diffVector.X, cameraVector.Y + diffVector.Y, cameraVector.Z);
if (!CheckCameraPosition(finalPos, player))
return null;
var camera = Utilities.CreateEntityByName<CDynamicProp>("prop_dynamic_override"); var camera = Utilities.CreateEntityByName<CDynamicProp>("prop_dynamic_override");
if (camera == null || !camera.IsValid) return null; if (camera == null || !camera.IsValid) return null;
@ -189,47 +230,32 @@ namespace src.player.skills
camera.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags = (uint)(camera.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags & ~(1 << 2)); camera.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags = (uint)(camera.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags & ~(1 << 2));
camera.Entity!.Name = camera.Globalname = $"CypherCamera_{Server.TickCount}_{player.SteamID}"; camera.Entity!.Name = camera.Globalname = $"CypherCamera_{Server.TickCount}_{player.SteamID}";
var playerPawn = player.PlayerPawn.Value; if (camera == null || !camera.IsValid) return null;
if (playerPawn == null || !playerPawn.IsValid) return null; camera.SetModel(cameraPropModel);
camera.Teleport(cameraVector, new QAngle(0, playerPawn.V_angle.Y + 180, 0));
Vector? cameraVector = GetNewCameraPosition(player); camera.DispatchSpawn();
Vector diffVector = SkillUtils.GetForwardVector(playerPawn.V_angle) * 10;
if (cameraVector == null) return null;
cameraVector = new Vector(cameraVector.X + diffVector.X, cameraVector.Y + diffVector.Y, cameraVector.Z);
if (!CheckCameraPosition(cameraVector, player))
return null;
Server.NextFrame(() =>
{
camera.SetModel(cameraPropModel);
camera.Teleport(cameraVector, new QAngle(0, playerPawn.V_angle.Y + 180, 0));
camera.DispatchSpawn();
});
return camera; return camera;
} }
private static CDynamicProp? CreateCameraView(CCSPlayerController player) private static CDynamicProp? CreateCameraView(CDynamicProp? cameraProp)
{ {
if (cameraProp == null || !cameraProp.IsValid || cameraProp.AbsRotation == null || cameraProp.AbsOrigin == null)
return null;
Vector diffVector = SkillUtils.GetForwardVector(cameraProp.AbsRotation) * 25;
Vector finalPos = cameraProp.AbsOrigin + diffVector;
var camera = Utilities.CreateEntityByName<CDynamicProp>("prop_dynamic"); var camera = Utilities.CreateEntityByName<CDynamicProp>("prop_dynamic");
if (camera == null || !camera.IsValid) return null; if (camera == null || !camera.IsValid) return null;
var playerPawn = player.PlayerPawn.Value;
if (playerPawn == null || !playerPawn.IsValid) return null;
Vector? cameraVector = GetNewCameraPosition(player);
Vector diffVector = SkillUtils.GetForwardVector(playerPawn.V_angle) * 25;
if (cameraVector == null) return null;
cameraVector = new Vector(cameraVector.X - diffVector.X, cameraVector.Y - diffVector.Y, cameraVector.Z);
if (cameraVector == null) return null;
Server.NextFrame(() => Server.NextFrame(() =>
{ {
if (camera == null || !camera.IsValid) return;
camera.SetModel(cameraViewModel); camera.SetModel(cameraViewModel);
camera.Render = Color.FromArgb(0, 255, 255, 255); camera.Render = Color.FromArgb(0, 255, 255, 255);
camera.Teleport(cameraVector, playerPawn.EyeAngles);
camera.Teleport(finalPos, cameraProp.AbsRotation);
camera.DispatchSpawn(); camera.DispatchSpawn();
}); });
@ -254,7 +280,7 @@ namespace src.player.skills
var player = Utilities.GetPlayerFromSteamId(steamID); var player = Utilities.GetPlayerFromSteamId(steamID);
if (player == null) return; if (player == null) return;
if (playersInfo.TryGetValue(player, out var playerSkill)) if (playersInfo.TryGetValue(player.Index, out var playerSkill))
{ {
ChangeCamera(playerSkill, true); ChangeCamera(playerSkill, true);
KillCamera(playerSkill); KillCamera(playerSkill);
@ -286,18 +312,13 @@ namespace src.player.skills
Vector eyePos = new(playerPawn.AbsOrigin.X, playerPawn.AbsOrigin.Y, playerPawn.AbsOrigin.Z + playerPawn.ViewOffset.Z); Vector eyePos = new(playerPawn.AbsOrigin.X, playerPawn.AbsOrigin.Y, playerPawn.AbsOrigin.Z + playerPawn.ViewOffset.Z);
Vector endPos = eyePos + SkillUtils.GetForwardVector(playerPawn.V_angle) * 4096f; Vector endPos = eyePos + SkillUtils.GetForwardVector(playerPawn.V_angle) * 4096f;
ulong solid = 0x1; ulong mask = (ulong)(InteractionLayers.Solid | InteractionLayers.Window | InteractionLayers.PassBullets);
ulong window = 0x1000; var result = RayTrace.TraceShape(player, eyePos, endPos, mask);
ulong passBullets = 0x2000;
ulong mask = solid | window | passBullets; if (result.HasValue && result.Value.HitWorld(out _))
ulong contents = playerPawn.Collision.CollisionGroup;
CGameTrace trace = TraceRay.TraceShape(eyePos, endPos, mask, contents, player);
if (trace.HitWorld(out _))
{ {
Vector3 hitPost = trace.EndPos; Vector3 hitPost = result.Value.EndPos;
Vector3 normal = trace.Normal; Vector3 normal = result.Value.Normal;
float offset = 8; float offset = 8;
Vector finalPos = new( Vector finalPos = new(
@ -320,15 +341,10 @@ namespace src.player.skills
Vector endPos = cameraVector + SkillUtils.GetForwardVector(new QAngle(0, playerPawn.V_angle.Y + 180, 0)) * -5; Vector endPos = cameraVector + SkillUtils.GetForwardVector(new QAngle(0, playerPawn.V_angle.Y + 180, 0)) * -5;
cameraVector += SkillUtils.GetForwardVector(new QAngle(0, playerPawn.V_angle.Y + 180, 0)) * 5; cameraVector += SkillUtils.GetForwardVector(new QAngle(0, playerPawn.V_angle.Y + 180, 0)) * 5;
ulong solid = 0x1; ulong mask = (ulong)(InteractionLayers.Solid | InteractionLayers.Window | InteractionLayers.PassBullets);
ulong window = 0x1000; var result = RayTrace.TraceShape(player, cameraVector, endPos, mask);
ulong passBullets = 0x2000;
ulong mask = solid | window | passBullets; if (result.HasValue && result.Value.HitWorld(out _))
ulong contents = playerPawn.Collision.CollisionGroup;
CGameTrace trace = TraceRay.TraceShape(cameraVector, endPos, mask, contents, player);
if (trace.HitWorld(out _))
return true; return true;
return false; return false;
@ -336,28 +352,30 @@ namespace src.player.skills
private static void UpdateHUD(PlayerSkill playerSkill) private static void UpdateHUD(PlayerSkill playerSkill)
{ {
if (playerSkill == null || playerSkill.Player == null) return; if (playerSkill == null) return;
float cooldown = 0; var player = Utilities.GetPlayerFromIndex((int)playerSkill.Player);
float time = (playerSkill.NextCamera - Server.TickCount) / 64; if (player == null || !player.IsValid) return;
cooldown = (int)Math.Ceiling(Math.Max(time, 0));
var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == playerSkill?.Player?.SteamID); var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player.SteamID);
if (playerInfo == null) return; if (playerInfo == null) return;
float ticksLeft = playerSkill.NextCamera - Server.TickCount;
int secondsLeft = (int)Math.Ceiling(Math.Max(ticksLeft / 64.0f, 0));
if (playerSkill.NoSpace >= Server.TickCount) if (playerSkill.NoSpace >= Server.TickCount)
playerInfo.PrintHTML = $"<font color='#FF0000'>{playerSkill.Player.GetTranslation("cypher_nospace")}</font>"; playerInfo.PrintHTML = $"<font color='#FF0000'>{player.GetTranslation("cypher_nospace")}</font>";
else if (cooldown == 0) else if (secondsLeft > 0 && playerSkill.CameraProp == null)
playerInfo.PrintHTML = $"{player.GetTranslation("hud_info", $"<font color='#FF0000'>{secondsLeft}</font>")}";
else
playerInfo.PrintHTML = null; playerInfo.PrintHTML = null;
else if (playerSkill?.CameraProp == null)
playerInfo.PrintHTML = $"{playerSkill?.Player.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}";
} }
public class PlayerSkill public class PlayerSkill
{ {
public required CCSPlayerController Player { get; set; } public required uint Player { get; set; }
public CDynamicProp? CameraProp { get; set; } public uint? CameraProp { get; set; }
public CDynamicProp? CameraView { get; set; } public uint? CameraView { get; set; }
public uint PlayerCameraRaw { get; set; } public uint PlayerCameraRaw { get; set; }
public bool CameraActive { get; set; } public bool CameraActive { get; set; }
public float NextCamera { get; set; } public float NextCamera { get; set; }

View file

@ -11,7 +11,7 @@ namespace src.player.skills
public class Deaf : ISkill public class Deaf : ISkill
{ {
private const Skills skillName = Skills.Deaf; private const Skills skillName = Skills.Deaf;
private static readonly ConcurrentDictionary<CCSPlayerController, byte> deafPlayers = []; private static readonly ConcurrentDictionary<uint, byte> deafPlayers = [];
public static void LoadSkill() public static void LoadSkill()
{ {
@ -20,8 +20,13 @@ namespace src.player.skills
public static void NewRound() public static void NewRound()
{ {
foreach (var player in deafPlayers.Keys) foreach (var playerIndex in deafPlayers.Keys)
{
var player = Utilities.GetPlayerFromIndex((int)playerIndex);
if (player == null || !player.IsValid) continue;
DisableSkill(player); DisableSkill(player);
}
deafPlayers.Clear(); deafPlayers.Clear();
foreach (var player in Utilities.GetPlayers()) foreach (var player in Utilities.GetPlayers())
SkillUtils.CloseMenu(player); SkillUtils.CloseMenu(player);
@ -29,8 +34,12 @@ namespace src.player.skills
public static void PlayerMakeSound(UserMessage um) public static void PlayerMakeSound(UserMessage um)
{ {
foreach (var player in deafPlayers.Keys) foreach (var playerIndex in deafPlayers.Keys)
{
var player = Utilities.GetPlayerFromIndex((int)playerIndex);
if (player == null || !player.IsValid) continue;
um.Recipients.Remove(player); um.Recipients.Remove(player);
}
} }
public static void OnTick() public static void OnTick()
@ -44,7 +53,7 @@ namespace src.player.skills
if (playerInfo == null || playerInfo.Skill != skillName) continue; if (playerInfo == null || playerInfo.Skill != skillName) continue;
var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray();
ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => (e.PlayerName, e.Index.ToString()))); ConcurrentBag<(string, string)> menuItems = [.. enemies.Select(e => (e.PlayerName, e.Index.ToString()))];
SkillUtils.UpdateMenu(player, menuItems); SkillUtils.UpdateMenu(player, menuItems);
} }
} }
@ -70,7 +79,7 @@ namespace src.player.skills
return; return;
} }
deafPlayers.TryAdd(enemy, 0); deafPlayers.TryAdd(enemy.Index, 0);
playerInfo.SkillUsed = true; playerInfo.SkillUsed = true;
player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("deaf_player_info", enemy.PlayerName)); player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("deaf_player_info", enemy.PlayerName));
enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("deaf_enemy_info")); enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("deaf_enemy_info"));
@ -95,7 +104,7 @@ namespace src.player.skills
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
{ {
SkillUtils.CloseMenu(player); SkillUtils.CloseMenu(player);
deafPlayers.TryRemove(player, out _); deafPlayers.TryRemove(player.Index, out _);
} }
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#dae01f", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "") : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#dae01f", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "") : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)

View file

@ -9,7 +9,7 @@ namespace src.player.skills
public class Distancer : ISkill public class Distancer : ISkill
{ {
private const Skills skillName = Skills.Distancer; private const Skills skillName = Skills.Distancer;
private static readonly ConcurrentDictionary<CCSPlayerController, byte> distancerPlayers = []; private static readonly ConcurrentDictionary<uint, byte> distancerPlayers = [];
private static readonly object setLock = new(); private static readonly object setLock = new();
public static void LoadSkill() public static void LoadSkill()
@ -26,8 +26,11 @@ namespace src.player.skills
public static void OnTick() public static void OnTick()
{ {
if (SkillUtils.IsFreezeTime()) return; if (SkillUtils.IsFreezeTime()) return;
foreach (var player in distancerPlayers.Keys) foreach (var playerIndex in distancerPlayers.Keys)
{ {
var player = Utilities.GetPlayerFromIndex((int)playerIndex);
if (player == null || !player.IsValid) continue;
var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID);
if (playerInfo == null) continue; if (playerInfo == null) continue;
@ -56,12 +59,12 @@ namespace src.player.skills
public static void EnableSkill(CCSPlayerController player) public static void EnableSkill(CCSPlayerController player)
{ {
distancerPlayers.TryAdd(player, 0); distancerPlayers.TryAdd(player.Index, 0);
} }
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
{ {
distancerPlayers.TryRemove(player, out _); distancerPlayers.TryRemove(player.Index, out _);
SkillUtils.ResetPrintHTML(player); SkillUtils.ResetPrintHTML(player);
} }

View file

@ -1,9 +1,10 @@
using CounterStrikeSharp.API; using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Entities;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using static src.jRandomSkills;
using System.Collections.Concurrent;
using src.utils; using src.utils;
using System.Collections.Concurrent;
using static src.jRandomSkills;
namespace src.player.skills namespace src.player.skills
{ {
@ -120,12 +121,18 @@ namespace src.player.skills
bool ctSkill = Event.counterterroristSkills.Any(s => s.Name == enemySkill.ToString()); bool ctSkill = Event.counterterroristSkills.Any(s => s.Name == enemySkill.ToString());
bool ttSkill = Event.terroristSkills.Any(s => s.Name == enemySkill.ToString()); bool ttSkill = Event.terroristSkills.Any(s => s.Name == enemySkill.ToString());
ulong steamID = player.SteamID;
string enemyName = enemy.PlayerName;
if ((player.Team == CsTeam.Terrorist && ctSkill) || (player.Team == CsTeam.CounterTerrorist && ttSkill)) if ((player.Team == CsTeam.Terrorist && ctSkill) || (player.Team == CsTeam.CounterTerrorist && ttSkill))
{ {
Instance.AddTimer(.1f, () => Instance.AddTimer(.1f, () =>
{ {
var player = Utilities.GetPlayerFromSteamId(steamID);
if (player == null || !player.IsValid) return;
Instance.SkillAction(skillName.ToString(), "EnableSkill", [player]); Instance.SkillAction(skillName.ToString(), "EnableSkill", [player]);
player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("thief_incorrect_skill", enemy.PlayerName)); player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("thief_incorrect_skill", enemyName));
}); });
return; return;
} }
@ -139,6 +146,9 @@ namespace src.player.skills
if (SkillsInfo.GetValue<bool>(enemySkill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime()) if (SkillsInfo.GetValue<bool>(enemySkill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime())
Instance?.AddTimer(Math.Max((float)(Event.GetFreezeTimeEnd() - DateTime.Now).TotalSeconds, 0), () => { Instance?.AddTimer(Math.Max((float)(Event.GetFreezeTimeEnd() - DateTime.Now).TotalSeconds, 0), () => {
var player = Utilities.GetPlayerFromSteamId(steamID);
if (player == null || !player.IsValid) return;
if (Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID && p.Skill == enemySkill) == null) return; if (Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID && p.Skill == enemySkill) == null) return;
Instance?.SkillAction(enemySkill.ToString(), "EnableSkill", [player]); Instance?.SkillAction(enemySkill.ToString(), "EnableSkill", [player]);
}); });

View file

@ -1,6 +1,5 @@
using CounterStrikeSharp.API; using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using src.utils; using src.utils;
using static src.jRandomSkills; using static src.jRandomSkills;
@ -24,8 +23,10 @@ namespace src.player.skills
{ {
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo == null) return; if (playerInfo == null) return;
float newChance = (float)Instance.Random.NextDouble() * (SkillsInfo.GetValue<float>(skillName, "ChanceTo") - SkillsInfo.GetValue<float>(skillName, "ChanceFrom")) + SkillsInfo.GetValue<float>(skillName, "ChanceFrom"); float newChance = (float)Instance.Random.NextDouble() * (SkillsInfo.GetValue<float>(skillName, "ChanceTo") - SkillsInfo.GetValue<float>(skillName, "ChanceFrom")) + SkillsInfo.GetValue<float>(skillName, "ChanceFrom");
playerInfo.SkillChance = newChance; playerInfo.SkillChance = newChance;
SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, newChance)}", SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, newChance)}",
border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t");
} }
@ -59,29 +60,20 @@ namespace src.player.skills
private static bool NearlyEquals(float a, float b, float epsilon = 0.001f) => Math.Abs(a -b) < epsilon; private static bool NearlyEquals(float a, float b, float epsilon = 0.001f) => Math.Abs(a -b) < epsilon;
public static void OnTakeDamage(DynamicHook h) public static void BulletImpact(EventBulletImpact @event)
{ {
if (lastTick == Server.TickCount) return; if (lastTick == Server.TickCount) return;
CEntityInstance param = h.GetParam<CEntityInstance>(0); var player = @event.Userid;
CTakeDamageInfo param2 = h.GetParam<CTakeDamageInfo>(1); if (player == null || !player.IsValid) return;
if (param == null || param.Entity == null || param2 == null || param2.Attacker == null || param2.Attacker.Value == null) var pos = new Vector(@event.X, @event.Y, @event.Z);
return;
CCSPlayerPawn attackerPawn = new(param2.Attacker.Value.Handle); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (attackerPawn.DesignerName != "player")
return;
if (attackerPawn == null || attackerPawn.Controller?.Value == null)
return;
CCSPlayerController attacker = attackerPawn.Controller.Value.As<CCSPlayerController>();
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker.SteamID);
if (playerInfo == null || playerInfo.Skill != skillName) return; if (playerInfo == null || playerInfo.Skill != skillName) return;
if (Instance.Random.NextDouble() <= playerInfo.SkillChance) if (Instance.Random.NextDouble() <= playerInfo.SkillChance)
SpawnExplosion(param2.DamagePosition); SpawnExplosion(pos);
} }
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#9c0000", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float damage = 25f, float damageRadius = 210f, float chanceFrom = .15f, float chanceTo = .3f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#9c0000", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float damage = 25f, float damageRadius = 210f, float chanceFrom = .15f, float chanceTo = .3f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)

View file

@ -11,7 +11,7 @@ namespace src.player.skills
public class FalconEye : ISkill public class FalconEye : ISkill
{ {
private const Skills skillName = Skills.FalconEye; private const Skills skillName = Skills.FalconEye;
private static readonly ConcurrentDictionary<ulong, (uint, CDynamicProp)> cameras = []; private static readonly ConcurrentDictionary<ulong, (uint, uint)> cameras = [];
public static void LoadSkill() public static void LoadSkill()
{ {
@ -20,9 +20,14 @@ namespace src.player.skills
public static void NewRound() public static void NewRound()
{ {
foreach (var camera in cameras) foreach (var cameraIndex in cameras.Values)
if (camera.Value.Item2 != null && camera.Value.Item2.IsValid) {
camera.Value.Item2.AcceptInput("Kill"); var camera = Utilities.GetEntityFromIndex<CDynamicProp>((int)cameraIndex.Item2);
if (camera == null || !camera.IsValid) continue;
camera.AcceptInput("Kill");
}
cameras.Clear(); cameras.Clear();
} }
@ -56,18 +61,23 @@ namespace src.player.skills
public static void OnTick() public static void OnTick()
{ {
foreach (var player in Utilities.GetPlayers()) foreach (var player in Utilities.GetPlayers())
if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2.IsValid) if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2 != 0)
{ {
var pawn = player.PlayerPawn.Value; var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) continue; if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) continue;
if (pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE) if (pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE)
{ {
ChangeCamera(player, true); ChangeCamera(player, true);
continue; continue;
} }
Vector pos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + SkillsInfo.GetValue<float>(skillName, "distance")); Vector pos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + SkillsInfo.GetValue<float>(skillName, "distance"));
QAngle angle = new(90, 0, -pawn.V_angle.Y); QAngle angle = new(90, 0, -pawn.V_angle.Y);
cameraInfo.Item2.Teleport(pos, angle);
var camera = Utilities.GetEntityFromIndex<CDynamicProp>((int)cameraInfo.Item2);
if (camera == null || !camera.IsValid) continue;
camera.Teleport(pos, angle);
} }
} }
@ -77,10 +87,15 @@ namespace src.player.skills
uint newCameraRaw; uint newCameraRaw;
var pawn = player.PlayerPawn.Value; var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid || pawn.CameraServices == null) return; if (pawn == null || !pawn.IsValid || pawn.CameraServices == null) return;
if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2.IsValid)
if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2 != 0)
{ {
orginalCameraRaw = cameraInfo.Item1; orginalCameraRaw = cameraInfo.Item1;
newCameraRaw = cameraInfo.Item2.EntityHandle.Raw;
var camera = Utilities.GetEntityFromIndex<CDynamicProp>((int)cameraInfo.Item2);
if (camera == null || !camera.IsValid) return;
newCameraRaw = camera.EntityHandle.Raw;
} }
else else
{ {
@ -108,13 +123,14 @@ namespace src.player.skills
Server.NextFrame(() => Server.NextFrame(() =>
{ {
if (camera == null || !camera.IsValid) return;
camera.SetModel("models/actors/ghost_speaker.vmdl"); camera.SetModel("models/actors/ghost_speaker.vmdl");
camera.Render = Color.FromArgb(0, 255, 255, 255); camera.Render = Color.FromArgb(0, 255, 255, 255);
camera.Teleport(pos, new QAngle(90, 0, 0)); camera.Teleport(pos, new QAngle(90, 0, 0));
camera.DispatchSpawn(); camera.DispatchSpawn();
}); });
cameras.AddOrUpdate(player.SteamID, (pawn.CameraServices!.ViewEntity.Raw, camera), (k, v) => (pawn.CameraServices!.ViewEntity.Raw, camera)); cameras.AddOrUpdate(player.SteamID, (pawn.CameraServices!.ViewEntity.Raw, camera.Index), (k, v) => (pawn.CameraServices!.ViewEntity.Raw, camera.Index));
return camera.EntityHandle.Raw; return camera.EntityHandle.Raw;
} }

View file

@ -112,6 +112,7 @@ namespace src.player.skills
barricades.TryAdd(box.Index, SkillsInfo.GetValue<int>(skillName, "barricadeHealth")); barricades.TryAdd(box.Index, SkillsInfo.GetValue<int>(skillName, "barricadeHealth"));
Server.NextFrame(() => Server.NextFrame(() =>
{ {
if (box == null || !box.IsValid) return;
box.SetModel(SkillsInfo.GetValue<string>(skillName, "propModel")); box.SetModel(SkillsInfo.GetValue<string>(skillName, "propModel"));
box.Teleport(pos, angle, null); box.Teleport(pos, angle, null);
}); });

View file

@ -1,10 +1,9 @@
using CounterStrikeSharp.API; using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Entities.Constants;
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using src.utils; using src.utils;
using static src.jRandomSkills; using static src.jRandomSkills;
using Vector = CounterStrikeSharp.API.Modules.Utils.Vector;
namespace src.player.skills namespace src.player.skills
{ {
@ -14,8 +13,8 @@ namespace src.player.skills
private static int bombHealth = 1000; private static int bombHealth = 1000;
private static int maxBombHealth = 1000; private static int maxBombHealth = 1000;
private static CPlantedC4? plantedC4; private static int lastTick = 0;
private static CTriggerMultiple? triggerC4; private static Vector? plantedC4;
public static void LoadSkill() public static void LoadSkill()
{ {
@ -27,80 +26,42 @@ namespace src.player.skills
bombHealth = SkillsInfo.GetValue<int>(skillName, "maxBombHealth"); bombHealth = SkillsInfo.GetValue<int>(skillName, "maxBombHealth");
maxBombHealth = SkillsInfo.GetValue<int>(skillName, "maxBombHealth"); maxBombHealth = SkillsInfo.GetValue<int>(skillName, "maxBombHealth");
plantedC4 = null; plantedC4 = null;
triggerC4 = null;
} }
public static void BombPlanted(EventBombPlanted _) public static void BombPlanted(EventBombPlanted _)
{ {
var plantedBomb = Utilities.FindAllEntitiesByDesignerName<CPlantedC4>("planted_c4").FirstOrDefault(); var plantedBomb = Utilities.FindAllEntitiesByDesignerName<CPlantedC4>("planted_c4").FirstOrDefault();
if (plantedBomb == null) return; if (plantedBomb == null || !plantedBomb.IsValid || plantedBomb.AbsOrigin == null) return;
plantedC4 = plantedBomb; plantedC4 = new(plantedBomb.AbsOrigin.X, plantedBomb.AbsOrigin.Y, plantedBomb.AbsOrigin.Z);
CreateTrigger();
}
private static void CreateTrigger()
{
var trigger = Utilities.CreateEntityByName<CTriggerMultiple>("trigger_multiple");
if (trigger == null || plantedC4 == null || trigger.AbsOrigin == null || plantedC4.AbsOrigin == null) return;
trigger.Collision.SolidType = SolidType_t.SOLID_CAPSULE;
trigger.Collision.SolidFlags = 0;
trigger.Spawnflags = 1;
trigger.Globalname = $"planted_bomb_prop_{trigger.Index}";
trigger.Collision.SolidFlags = 1;
trigger.AbsOrigin.X = plantedC4.AbsOrigin.X;
trigger.AbsOrigin.Y = plantedC4.AbsOrigin.Y;
trigger.AbsOrigin.Z = plantedC4.AbsOrigin.Z;
trigger.Collision.CapsuleRadius = 10;
trigger.Collision.BoundingRadius = 10;
trigger.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_TRIGGER;
trigger.Collision.EnablePhysics = 1;
trigger.Collision.TriggerBloat = 0;
trigger.Collision.SurroundType = SurroundingBoundsType_t.USE_OBB_COLLISION_BOUNDS;
trigger.Collision.CollisionAttribute.CollisionFunctionMask = 39;
trigger.Collision.CollisionAttribute.CollisionGroup = 2;
trigger.DispatchSpawn();
triggerC4 = trigger;
} }
private static void RemoveBomb() private static void RemoveBomb()
{ {
if (plantedC4 != null && plantedC4.IsValid) plantedC4 = null;
plantedC4.AcceptInput("Kill"); var plantedBomb = Utilities.FindAllEntitiesByDesignerName<CPlantedC4>("planted_c4").FirstOrDefault();
if (triggerC4 != null && triggerC4.IsValid) if (plantedBomb != null && plantedBomb.IsValid)
triggerC4.AcceptInput("Kill"); plantedBomb.AcceptInput("Kill");
SkillUtils.TerminateRound(CsTeam.CounterTerrorist); SkillUtils.TerminateRound(CsTeam.CounterTerrorist);
} }
public static void OnTakeDamage(DynamicHook h) public static void BulletImpact(EventBulletImpact @event)
{ {
CEntityInstance param = h.GetParam<CEntityInstance>(0); if (lastTick == Server.TickCount) return;
CTakeDamageInfo param2 = h.GetParam<CTakeDamageInfo>(1);
if (param == null || param.Entity == null || param2 == null || param2.Attacker == null || param2.Attacker.Value == null) var player = @event.Userid;
return; if (player == null || !player.IsValid || plantedC4 == null) return;
CCSPlayerPawn attackerPawn = new(param2.Attacker.Value.Handle); var pos = new Vector(@event.X, @event.Y, @event.Z);
if (attackerPawn.DesignerName != "player" || param.DesignerName != "trigger_multiple") var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
return;
CTriggerMultiple trigger = new(param.Handle);
if (attackerPawn == null || attackerPawn.Controller?.Value == null || trigger == null || !trigger.Globalname.StartsWith("planted_bomb_prop_"))
return;
CCSPlayerController attacker = attackerPawn.Controller.Value.As<CCSPlayerController>();
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker.SteamID);
if (playerInfo == null || playerInfo.Skill != skillName) return; if (playerInfo == null || playerInfo.Skill != skillName) return;
bombHealth -= (int)param2.TotalledDamage; if (SkillUtils.Distance(plantedC4, pos) >= 8)
return;
lastTick = Server.TickCount;
bombHealth -= Instance.Random.Next(25, 42);
if (bombHealth <= 0) if (bombHealth <= 0)
{ {
RemoveBomb(); RemoveBomb();

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;
@ -34,6 +35,10 @@ namespace src.player.skills
var pawn = victim.PlayerPawn.Value; var pawn = victim.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid) return; if (pawn == null || !pawn.IsValid) return;
if (damage == 0)
damage = Instance.Random.Next(4, 6);
SkillUtils.AddHealth(pawn, damage + (int)(damage * SkillsInfo.GetValue<float>(skillName, "healthMultiplier")), pawn.MaxHealth); SkillUtils.AddHealth(pawn, damage + (int)(damage * SkillsInfo.GetValue<float>(skillName, "healthMultiplier")), pawn.MaxHealth);
} }

View file

@ -28,6 +28,8 @@ namespace src.player.skills
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo?.Skill != skillName) return; if (playerInfo?.Skill != skillName) return;
ulong steamID = player.SteamID;
if (playerInfo.SkillUsed) if (playerInfo.SkillUsed)
{ {
player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("areareaper_used_info")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("areareaper_used_info")}");
@ -56,7 +58,10 @@ namespace src.player.skills
if (SkillsInfo.GetValue<bool>(skill.Skill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime()) if (SkillsInfo.GetValue<bool>(skill.Skill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime())
Instance?.AddTimer(Math.Max((float)(Event.GetFreezeTimeEnd() - DateTime.Now).TotalSeconds, 0), () => { Instance?.AddTimer(Math.Max((float)(Event.GetFreezeTimeEnd() - DateTime.Now).TotalSeconds, 0), () => {
if (Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID && p.Skill == skill.Skill) == null) return; var player = Utilities.GetPlayerFromSteamId(steamID);
if (player == null || !player.IsValid) return;
if (Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == steamID && p.Skill == skill.Skill) == null) return;
Instance?.SkillAction(skill.Skill.ToString(), "EnableSkill", [player]); Instance?.SkillAction(skill.Skill.ToString(), "EnableSkill", [player]);
}); });
else else

View file

@ -24,7 +24,7 @@ namespace src.player.skills
"weapon_g3sg1", "weapon_nova", "weapon_xm1014", "weapon_mag7", "weapon_g3sg1", "weapon_nova", "weapon_xm1014", "weapon_mag7",
"weapon_sawedoff", "weapon_m249", "weapon_negev" "weapon_sawedoff", "weapon_m249", "weapon_negev"
]; ];
private static readonly ConcurrentDictionary<CCSPlayerController, byte> invisiblePlayers = []; private static readonly ConcurrentDictionary<uint, byte> invisiblePlayers = [];
private const string bloodParticle = "particles/blood_impact/blood_impact_high.vpcf"; private const string bloodParticle = "particles/blood_impact/blood_impact_high.vpcf";
public static void LoadSkill() public static void LoadSkill()
@ -76,22 +76,31 @@ namespace src.player.skills
if (targetInfo?.Skill == skillName) isObservingGhost = true; if (targetInfo?.Skill == skillName) isObservingGhost = true;
} }
foreach (var _player in invisiblePlayers.Keys) foreach (var playerIndex in invisiblePlayers.Keys)
if (player.SteamID != _player.SteamID && !isObservingGhost) {
var playerController = Utilities.GetPlayerFromIndex((int)playerIndex);
if (playerController == null || !playerController.IsValid || playerController.SteamID == player.SteamID)
continue;
if (!isObservingGhost)
{ {
var playerPawn = _player.PlayerPawn.Value; var playerPawn = playerController.PlayerPawn.Value;
if (playerPawn == null || !playerPawn.IsValid) continue; if (playerPawn == null || !playerPawn.IsValid) continue;
var entity = Utilities.GetEntityFromIndex<CBaseEntity>((int)playerPawn.Index); var entity = Utilities.GetEntityFromIndex<CBaseEntity>((int)playerPawn.Index);
if (entity == null || !entity.IsValid) continue; if (entity == null || !entity.IsValid) continue;
info.TransmitEntities.Remove(entity.Index); info.TransmitEntities.Remove(entity.Index);
var bombIndex = GetBombIndex(_player); var bombIndex = GetBombIndex(playerController);
if (bombIndex == null) continue; if (bombIndex == null) continue;
var bombEntity = Utilities.GetEntityFromIndex<CBaseEntity>((int)bombIndex); var bombEntity = Utilities.GetEntityFromIndex<CBaseEntity>((int)bombIndex);
if (bombEntity == null || !bombEntity.IsValid) continue; if (bombEntity == null || !bombEntity.IsValid) continue;
info.TransmitEntities.Remove(bombEntity.Index); info.TransmitEntities.Remove(bombEntity.Index);
} }
}
} }
} }
@ -99,14 +108,14 @@ namespace src.player.skills
{ {
Event.EnableTransmit(); Event.EnableTransmit();
SetWeaponAttack(player, true); SetWeaponAttack(player, true);
invisiblePlayers.TryAdd(player, 0); invisiblePlayers.TryAdd(player.Index, 0);
} }
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
{ {
SkillUtils.ResetPrintHTML(player); SkillUtils.ResetPrintHTML(player);
SetWeaponAttack(player, false); SetWeaponAttack(player, false);
invisiblePlayers.TryRemove(player, out _); invisiblePlayers.TryRemove(player.Index, out _);
} }
public static void OnTick() public static void OnTick()
@ -116,8 +125,9 @@ namespace src.player.skills
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo?.Skill == skillName) if (playerInfo?.Skill == skillName)
UpdateHUD(player); UpdateHUD(player);
if (!player.PawnIsAlive) if (!player.PawnIsAlive)
invisiblePlayers.TryRemove(player, out _); invisiblePlayers.TryRemove(player.Index, out _);
} }
} }
@ -125,7 +135,7 @@ namespace src.player.skills
{ {
var player = @event.Userid; var player = @event.Userid;
if (player == null || !player.IsValid) return; if (player == null || !player.IsValid) return;
if (!invisiblePlayers.ContainsKey(player)) return; if (!invisiblePlayers.ContainsKey(player.Index)) return;
var playerPawn = player.PlayerPawn.Value; var playerPawn = player.PlayerPawn.Value;
if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return; if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return;

View file

@ -1,9 +1,10 @@
using CounterStrikeSharp.API; using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Entities;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using static src.jRandomSkills;
using System.Collections.Concurrent;
using src.utils; using src.utils;
using System.Collections.Concurrent;
using static src.jRandomSkills;
namespace src.player.skills namespace src.player.skills
{ {
@ -49,6 +50,10 @@ namespace src.player.skills
{ {
SkillPlayerInfo.TryRemove(player.SteamID, out _); SkillPlayerInfo.TryRemove(player.SteamID, out _);
SkillUtils.ResetPrintHTML(player); SkillUtils.ResetPrintHTML(player);
var playerPawn = player.PlayerPawn.Value;
if (playerPawn != null && playerPawn.IsValid)
playerPawn.TakesDamage = true;
} }
private static void UpdateHUD(CCSPlayerController player, PlayerSkillInfo skillInfo) private static void UpdateHUD(CCSPlayerController player, PlayerSkillInfo skillInfo)
@ -77,7 +82,9 @@ namespace src.player.skills
var playerPawn = player.PlayerPawn.Value; var playerPawn = player.PlayerPawn.Value;
if (playerPawn?.CBodyComponent == null) return; if (playerPawn?.CBodyComponent == null) return;
if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) ulong steamID = player.SteamID;
if (SkillPlayerInfo.TryGetValue(steamID, out var skillInfo))
{ {
if (!player.IsValid || !player.PawnIsAlive || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return; if (!player.IsValid || !player.PawnIsAlive || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return;
if (skillInfo.CanUse) if (skillInfo.CanUse)
@ -89,8 +96,11 @@ namespace src.player.skills
player.PlayerPawn.Value.TakesDamage = false; player.PlayerPawn.Value.TakesDamage = false;
Instance.AddTimer(SkillsInfo.GetValue<float>(skillName, "duration"), () => { Instance.AddTimer(SkillsInfo.GetValue<float>(skillName, "duration"), () => {
if (player.IsValid && player.PawnIsAlive)
var player = Utilities.GetPlayerFromSteamId(steamID);
if (player != null && player.IsValid && player.PawnIsAlive)
{ {
if (player.PlayerPawn == null || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return;
player.PlayerPawn.Value.TakesDamage = true; player.PlayerPawn.Value.TakesDamage = true;
player.PrintToChat($" {ChatColors.Red} {player.GetTranslation("godmode_off")}"); player.PrintToChat($" {ChatColors.Red} {player.GetTranslation("godmode_off")}");
} }

View file

@ -65,6 +65,7 @@ namespace src.player.skills
Server.NextFrame(() => Server.NextFrame(() =>
{ {
if (entity == null || !entity.IsValid) return;
var smoke = entity.As<CSmokeGrenadeProjectile>(); var smoke = entity.As<CSmokeGrenadeProjectile>();
smoke.SmokeColor.X = 0; smoke.SmokeColor.X = 0;
smoke.SmokeColor.Y = 255; smoke.SmokeColor.Y = 255;

View file

@ -24,6 +24,7 @@ namespace src.player.skills
Server.NextFrame(() => Server.NextFrame(() =>
{ {
if (@event == null || !@event.IsValid) return;
var hegrenade = @event.As<CHEGrenadeProjectile>(); var hegrenade = @event.As<CHEGrenadeProjectile>();
if (hegrenade == null || !hegrenade.IsValid) return; if (hegrenade == null || !hegrenade.IsValid) return;

View file

@ -3,8 +3,6 @@ using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
using CounterStrikeSharp.API.Modules.Timers; using CounterStrikeSharp.API.Modules.Timers;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using CS2TraceRay.Class;
using CS2TraceRay.Struct;
using src.utils; using src.utils;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using Timer = CounterStrikeSharp.API.Modules.Timers.Timer; using Timer = CounterStrikeSharp.API.Modules.Timers.Timer;
@ -15,7 +13,7 @@ namespace src.player.skills
public class Iana : ISkill public class Iana : ISkill
{ {
private const Skills skillName = Skills.Iana; private const Skills skillName = Skills.Iana;
private static readonly ConcurrentDictionary<CCSPlayerController, PlayerSkill> playersInfo = []; private static readonly ConcurrentDictionary<uint, PlayerSkill> playersInfo = [];
private static readonly object setLock = new(); private static readonly object setLock = new();
public static void LoadSkill() public static void LoadSkill()
@ -35,7 +33,7 @@ namespace src.player.skills
{ {
var player = @event.Userid; var player = @event.Userid;
if (player == null) return; if (player == null) return;
if (playersInfo.TryGetValue(player, out var playerSkill)) if (playersInfo.TryGetValue(player.Index, out var playerSkill))
if (playerSkill.CloneProp != null) if (playerSkill.CloneProp != null)
BlockWeapon(player, true); BlockWeapon(player, true);
} }
@ -44,7 +42,7 @@ namespace src.player.skills
{ {
var player = @event.Userid; var player = @event.Userid;
if (player == null) return; if (player == null) return;
if (playersInfo.TryGetValue(player, out var playerSkill)) if (playersInfo.TryGetValue(player.Index, out var playerSkill))
if (playerSkill.CloneProp != null) if (playerSkill.CloneProp != null)
BlockWeapon(player, true); BlockWeapon(player, true);
} }
@ -54,9 +52,12 @@ namespace src.player.skills
var playerPawn = player.PlayerPawn.Value; var playerPawn = player.PlayerPawn.Value;
if (playerPawn?.CBodyComponent == null) return; if (playerPawn?.CBodyComponent == null) return;
if (playersInfo.TryGetValue(player, out var playerSkill)) if (playersInfo.TryGetValue(player.Index, out var playerSkill))
if (playerSkill.CloneProp == null && playerSkill.NextUse <= Server.TickCount) if (playerSkill.CloneProp == null && playerSkill.NextUse <= Server.TickCount)
{
UpdateWeapons(player, playerSkill);
CreateClone(playerSkill); CreateClone(playerSkill);
}
else if (playerSkill.CloneProp != null) else if (playerSkill.CloneProp != null)
KillClone(playerSkill); KillClone(playerSkill);
} }
@ -64,9 +65,9 @@ namespace src.player.skills
public static void EnableSkill(CCSPlayerController player) public static void EnableSkill(CCSPlayerController player)
{ {
if (player.PlayerPawn.Value == null || player.PlayerPawn.Value.CameraServices == null) return; if (player.PlayerPawn.Value == null || player.PlayerPawn.Value.CameraServices == null) return;
playersInfo.TryAdd(player, new PlayerSkill playersInfo.TryAdd(player.Index, new PlayerSkill
{ {
Player = player, PlayerIndex = player.Index,
CloneProp = null, CloneProp = null,
NextUse = 0, NextUse = 0,
UseTime = 0, UseTime = 0,
@ -75,32 +76,54 @@ namespace src.player.skills
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
{ {
if (playersInfo.TryGetValue(player, out var playerSkill)) if (playersInfo.TryGetValue(player.Index, out var playerSkill))
KillClone(playerSkill); KillClone(playerSkill);
playersInfo.TryRemove(player, out _); playersInfo.TryRemove(player.Index, out _);
}
private static void UpdateWeapons(CCSPlayerController player, PlayerSkill playerSkill)
{
if (player == null || !player.IsValid) return;
var playerPawn = player.PlayerPawn.Value;
if (playerPawn == null || !playerPawn.IsValid || playerPawn.WeaponServices == null) return;
playerSkill.Weapons.Clear();
foreach (var weapon in playerPawn.WeaponServices.MyWeapons)
if (weapon != null && weapon.IsValid && weapon.Value != null && weapon.Value.IsValid)
playerSkill.Weapons.Add(weapon.Value.AttributeManager.Item.ItemID);
} }
private static void KillClone(PlayerSkill playerSkill) private static void KillClone(PlayerSkill playerSkill)
{ {
playerSkill.Player.EmitSound("SolidMetal.BulletImpact"); var player = Utilities.GetPlayerFromIndex((int)playerSkill.PlayerIndex);
if (playerSkill.CloneProp != null && playerSkill.CloneProp.IsValid && playerSkill.CloneProp.AbsOrigin != null && playerSkill.CloneProp.AbsRotation != null) if (player == null || !player.IsValid) return;
player.EmitSound("SolidMetal.BulletImpact");
CDynamicProp? cloneProp = null;
if (playerSkill.CloneProp != null)
cloneProp = Utilities.GetEntityFromIndex<CDynamicProp>((int)playerSkill.CloneProp);
if (cloneProp != null && cloneProp.IsValid && cloneProp.AbsOrigin != null && cloneProp.AbsRotation != null)
{ {
var playerPawn = playerSkill.Player.PlayerPawn.Value; var playerPawn = player.PlayerPawn.Value;
if (playerPawn != null && playerPawn.IsValid) if (playerPawn != null && playerPawn.IsValid)
{ {
Vector pos = new(playerSkill.CloneProp.AbsOrigin.X, playerSkill.CloneProp.AbsOrigin.Y, playerSkill.CloneProp.AbsOrigin.Z); Vector pos = new(cloneProp.AbsOrigin.X, cloneProp.AbsOrigin.Y, cloneProp.AbsOrigin.Z);
QAngle angle = new(playerSkill.CloneProp.AbsRotation.X, playerSkill.CloneProp.AbsRotation.Y, playerSkill.CloneProp.AbsRotation.Z);
Server.NextFrame(() => Server.NextFrame(() =>
{ {
playerPawn.Teleport(pos, angle); if (playerPawn == null || !playerPawn.IsValid) return;
playerPawn.Teleport(pos);
}); });
} }
playerSkill.CloneProp.AcceptInput("Kill"); cloneProp.AcceptInput("Kill");
playerSkill.CloneProp = null; playerSkill.CloneProp = null;
} }
SkillUtils.ApplyScreenColor(playerSkill.Player, 0, 0, 0, 0, 10, 0, 2); SkillUtils.ApplyScreenColor(player, 0, 0, 0, 0, 10, 0, 2);
BlockWeapon(playerSkill.Player, false); BlockWeapon(player, false);
playerSkill.NextUse = Server.TickCount + SkillsInfo.GetValue<float>(skillName, "Cooldown") * 64; playerSkill.NextUse = Server.TickCount + SkillsInfo.GetValue<float>(skillName, "Cooldown") * 64;
playerSkill.UseTime = 0; playerSkill.UseTime = 0;
} }
@ -113,20 +136,32 @@ namespace src.player.skills
private static CDynamicProp? CreateClone(PlayerSkill playerSkill) private static CDynamicProp? CreateClone(PlayerSkill playerSkill)
{ {
var player = playerSkill.Player; var player = Utilities.GetPlayerFromIndex((int)playerSkill.PlayerIndex);
if (player == null) return null; if (player == null || !player.IsValid) return null;
var playerPawn = player.PlayerPawn.Value; var playerPawn = player.PlayerPawn.Value;
if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null || playerPawn.AbsRotation == null) return null; if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null || playerPawn.AbsRotation == null) return null;
Vector pos = playerPawn.AbsOrigin + SkillUtils.GetForwardVector(playerPawn.AbsRotation) * 50; if (!((PlayerFlags)playerPawn.Flags).HasFlag(PlayerFlags.FL_ONGROUND))
Vector pos2 = playerPawn.AbsOrigin + SkillUtils.GetForwardVector(playerPawn.AbsRotation) * (50 + 25);
if (!CheckPosition(player, pos2) || !((PlayerFlags)playerPawn.Flags).HasFlag(PlayerFlags.FL_ONGROUND))
{ {
playerSkill.InfoTime = Server.TickCount; playerSkill.InfoTime = Server.TickCount;
return null; return null;
} }
QAngle angle = new(0, playerPawn.EyeAngles.Y, 0);
Vector pos = playerPawn.AbsOrigin + SkillUtils.GetForwardVector(angle) * 50;
pos.Z += 2;
if (!CheckPosition(player, pos))
{
pos.Z += 10;
if (!CheckPosition(player, pos))
{
playerSkill.InfoTime = Server.TickCount;
return null;
}
}
var clone = Utilities.CreateEntityByName<CDynamicProp>("prop_dynamic"); var clone = Utilities.CreateEntityByName<CDynamicProp>("prop_dynamic");
if (clone == null || !clone.IsValid) return null; if (clone == null || !clone.IsValid) return null;
@ -137,16 +172,21 @@ namespace src.player.skills
Server.NextFrame(() => Server.NextFrame(() =>
{ {
if (player == null || !player.IsValid) return;
if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null || playerPawn.AbsRotation == null) return;
if (clone == null || !clone.IsValid) return;
clone.SetModel(playerPawn!.CBodyComponent!.SceneNode!.GetSkeletonInstance().ModelState.ModelName); clone.SetModel(playerPawn!.CBodyComponent!.SceneNode!.GetSkeletonInstance().ModelState.ModelName);
clone.Teleport(playerPawn.AbsOrigin, new QAngle(0, playerPawn.V_angle.Y, 0)); clone.Teleport(playerPawn.AbsOrigin, new QAngle(0, playerPawn.V_angle.Y, 0));
playerPawn.Teleport(pos); playerPawn.Teleport(pos);
SkillUtils.ApplyScreenColor(player, r: 255, g: 255, b: 0, a: 20, duration: 100, holdTime: 1020); SkillUtils.ApplyScreenColor(player, r: 255, g: 255, b: 0, a: 20, duration: 100, holdTime: 1020);
BlockWeapon(playerSkill.Player, true); BlockWeapon(player, true);
playerSkill.UseTime = Server.TickCount; playerSkill.UseTime = Server.TickCount;
playerSkill.NextUse = Server.TickCount + 64000; playerSkill.NextUse = Server.TickCount + 64000;
playerSkill.CloneProp = clone; playerSkill.CloneProp = clone.Index;
jRandomSkills.Instance.AddTimer(SkillsInfo.GetValue<float>(skillName, "Duration"), () => jRandomSkills.Instance.AddTimer(SkillsInfo.GetValue<float>(skillName, "Duration"), () =>
{ {
@ -167,7 +207,7 @@ namespace src.player.skills
return; return;
} }
if (!playersInfo.TryGetValue(target, out var playerSkill) || playerSkill.CloneProp == null) if (!playersInfo.TryGetValue(target.Index, out var playerSkill) || playerSkill.CloneProp == null)
{ {
cloneTimer?.Kill(); cloneTimer?.Kill();
return; return;
@ -183,16 +223,14 @@ namespace src.player.skills
private unsafe static bool CheckPosition(CCSPlayerController player, Vector endPos) private unsafe static bool CheckPosition(CCSPlayerController player, Vector endPos)
{ {
var playerPawn = player.PlayerPawn.Value; var playerPawn = player.PlayerPawn.Value;
if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return false;
Vector eyePos = new(playerPawn.AbsOrigin.X, playerPawn.AbsOrigin.Y, playerPawn.AbsOrigin.Z + 25); Vector start = new(playerPawn!.AbsOrigin!.X, playerPawn!.AbsOrigin!.Y, endPos.Z);
endPos.Z += 25; var result = RayTrace.TraceHullShape(start, endPos, player);
ulong mask = playerPawn.Collision.CollisionAttribute.InteractsWith; if (!result.HasValue)
ulong contents = playerPawn.Collision.CollisionGroup; return false;
CGameTrace trace = TraceRay.TraceShape(eyePos, endPos, mask, contents, player);
return !result.Value.DidHit;
return !trace.DidHit();
} }
private static float CalculateDamage(CCSPlayerController player, string weaponName, float damage, bool isHeadshot) private static float CalculateDamage(CCSPlayerController player, string weaponName, float damage, bool isHeadshot)
@ -240,12 +278,16 @@ namespace src.player.skills
float dealDamage = param2.Damage; float dealDamage = param2.Damage;
if (playersInfo.TryGetValue(player, out var playerSkill)) if (playersInfo.TryGetValue(player.Index, out var playerSkill))
{ {
if (playerSkill.CloneProp != null && playerSkill.CloneProp.IsValid && playerSkill.CloneProp.AbsOrigin != null) CDynamicProp? cloneProp = null;
if (playerSkill.CloneProp != null)
cloneProp = Utilities.GetEntityFromIndex<CDynamicProp>((int)playerSkill.CloneProp);
if (cloneProp != null && cloneProp.IsValid && cloneProp.AbsOrigin != null)
{ {
Vector pos = param2.DamagePosition; Vector pos = param2.DamagePosition;
Vector posCl = playerSkill.CloneProp.AbsOrigin; Vector posCl = cloneProp.AbsOrigin;
bool isHead = false; bool isHead = false;
float viewOffset = 63.27f; float viewOffset = 63.27f;
@ -273,7 +315,7 @@ namespace src.player.skills
var victim = @event.Userid!; var victim = @event.Userid!;
if (!jRandomSkills.Instance.IsPlayerValid(victim)) return; if (!jRandomSkills.Instance.IsPlayerValid(victim)) return;
if (playersInfo.TryGetValue(victim, out var playerSkill) && playerSkill.CloneProp != null) if (playersInfo.TryGetValue(victim.Index, out var playerSkill) && playerSkill.CloneProp != null)
{ {
KillClone(playerSkill); KillClone(playerSkill);
SkillUtils.RestoreHealth(victim); SkillUtils.RestoreHealth(victim);
@ -299,7 +341,10 @@ namespace src.player.skills
private static void UpdateHUD(PlayerSkill playerSkill) private static void UpdateHUD(PlayerSkill playerSkill)
{ {
if (playerSkill == null || playerSkill.Player == null) return; if (playerSkill == null) return;
var player = Utilities.GetPlayerFromIndex((int)playerSkill.PlayerIndex);
if (player == null || !player.IsValid) return;
float cooldown = 0; float cooldown = 0;
float time1 = (playerSkill.NextUse - Server.TickCount) / 64; float time1 = (playerSkill.NextUse - Server.TickCount) / 64;
@ -309,26 +354,57 @@ namespace src.player.skills
float time2 = SkillsInfo.GetValue<float>(skillName, "Duration") - (Server.TickCount - playerSkill.UseTime) / 64; float time2 = SkillsInfo.GetValue<float>(skillName, "Duration") - (Server.TickCount - playerSkill.UseTime) / 64;
duration = (int)Math.Ceiling(Math.Max(time2, 0)); duration = (int)Math.Ceiling(Math.Max(time2, 0));
var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == playerSkill?.Player?.SteamID); var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player.SteamID);
if (playerInfo == null) return; if (playerInfo == null) return;
if (playerSkill.InfoTime + (64 * 2) > Server.TickCount) if (playerSkill.InfoTime + (64 * 2) > Server.TickCount)
playerInfo.PrintHTML = $"{playerSkill?.Player.GetTranslation("shade_nospace")}"; playerInfo.PrintHTML = $"{player.GetTranslation("shade_nospace")}";
else if (cooldown == 0 && duration == 0) else if (cooldown == 0 && duration == 0)
playerInfo.PrintHTML = null; playerInfo.PrintHTML = null;
else if (duration > 0) else if (duration > 0)
playerInfo.PrintHTML = $"{playerSkill?.Player.GetTranslation("hud_info", $"<font color='#00FF00'>{duration}</font>")}"; playerInfo.PrintHTML = $"{player.GetTranslation("hud_info", $"<font color='#00FF00'>{duration}</font>")}";
else if (cooldown > 0) else if (cooldown > 0)
playerInfo.PrintHTML = $"{playerSkill?.Player.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}"; playerInfo.PrintHTML = $"{player.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}";
}
public static bool OnWeaponCanAcquire(DynamicHook hook, CCSPlayerController player, CEconItemView econItem, CCSWeaponBaseVData vdata)
{
string weaponName = vdata.Name;
if (string.IsNullOrEmpty(weaponName)) return false;
var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo?.Skill != skillName) return false;
if (playersInfo.TryGetValue(player.Index, out var playerSkill))
if (playerSkill.CloneProp == null || playerSkill.Weapons.Contains(econItem.ItemID))
return false;
hook.SetReturn(AcquireResult.InvalidItem);
return true;
}
public static bool WeaponDrop(DynamicHook hook, CCSPlayerController player)
{
if (player == null || !player.IsValid) return false;
if (playersInfo.TryGetValue(player.Index, out var playerSkill))
if (playerSkill.CloneProp != null)
{
hook.SetReturn(1);
return true;
}
return false;
} }
public class PlayerSkill public class PlayerSkill
{ {
public required CCSPlayerController Player { get; set; } public required uint PlayerIndex { get; set; }
public CDynamicProp? CloneProp { get; set; } public uint? CloneProp { get; set; }
public float NextUse { get; set; } public float NextUse { get; set; }
public float UseTime { get; set; } public float UseTime { get; set; }
public int InfoTime { get; set; } public int InfoTime { get; set; }
public List<ulong> Weapons { get; set; } = [];
} }
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#d0d930", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = true, bool needsTeammates = false, string requiredPermission = "", float cooldown = 30, float duration = 10) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#d0d930", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = true, bool needsTeammates = false, string requiredPermission = "", float cooldown = 30, float duration = 10) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)

View file

@ -9,7 +9,7 @@ namespace src.player.skills
{ {
private const Skills skillName = Skills.Illiterate; private const Skills skillName = Skills.Illiterate;
private static bool isActive = false; private static bool isActive = false;
private static int offset = jRandomSkills.Instance.Random.Next(2, 26); private static int offset = jRandomSkills.Instance.Random.Next(1, 26);
public static void LoadSkill() public static void LoadSkill()
{ {
@ -54,8 +54,12 @@ namespace src.player.skills
public static string? GetRandomText(string? input) public static string? GetRandomText(string? input)
{ {
if (string.IsNullOrEmpty(input)) return null; if (string.IsNullOrEmpty(input)) return null;
if (Server.TickCount % 64 == 0)
offset = jRandomSkills.Instance.Random.Next(2, 26); if (Server.TickCount % 64 == 0 || offset == 0)
{
offset = jRandomSkills.Instance.Random.Next(1, 26);
if (offset == 13) offset = 14;
}
return new string([.. input.Select(c => return new string([.. input.Select(c =>
{ {
@ -63,15 +67,14 @@ namespace src.player.skills
if (!char.IsLetter(c)) return c; if (!char.IsLetter(c)) return c;
char baseChar = char.IsUpper(c) ? 'A' : 'a'; char baseChar = char.IsUpper(c) ? 'A' : 'a';
return (char)(baseChar + (c - baseChar + offset) % 26); int shifted = (c - baseChar + offset) % 26;
return (char)(baseChar + shifted);
})]); })]);
} }
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#1466F5", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = true, bool needsTeammates = false, string requiredPermission = "", float maximumFuel = 150f, float fuelConsumption = .64f, float refuelling = .1f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#1466F5", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = true, bool needsTeammates = false, string requiredPermission = "", float maximumFuel = 150f, float fuelConsumption = .64f, float refuelling = .1f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)
{ {
public float MaximumFuel { get; set; } = maximumFuel;
public float FuelConsumption { get; set; } = fuelConsumption;
public float Refuelling { get; set; } = refuelling;
} }
} }
} }

View file

@ -11,8 +11,8 @@ namespace src.player.skills
public class Impostor : ISkill public class Impostor : ISkill
{ {
private const Skills skillName = Skills.Impostor; private const Skills skillName = Skills.Impostor;
private static readonly string defaultCTModel = "characters/models/ctm_sas/ctm_sas.vmdl"; private static readonly string defaultCTModel = "agents//models/ctm_sas/ctm_sas.vmdl";
private static readonly string defaultTModel = "characters/models/tm_phoenix/tm_phoenix.vmdl"; private static readonly string defaultTModel = "agents/models/tm_phoenix/tm_phoenix.vmdl";
private static readonly ConcurrentDictionary<ulong, string> originalModels = []; private static readonly ConcurrentDictionary<ulong, string> originalModels = [];
public static void LoadSkill() public static void LoadSkill()
@ -63,6 +63,7 @@ namespace src.player.skills
Server.NextFrame(() => Server.NextFrame(() =>
{ {
if (pawn == null || !pawn.IsValid) return;
pawn.SetModel(model); pawn.SetModel(model);
var originalRender = pawn.Render; var originalRender = pawn.Render;

View file

@ -5,6 +5,7 @@ using CounterStrikeSharp.API.Modules.Utils;
using src.utils; using src.utils;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using static src.jRandomSkills; using static src.jRandomSkills;
using Timer = CounterStrikeSharp.API.Modules.Timers.Timer;
namespace src.player.skills namespace src.player.skills
{ {
@ -12,8 +13,8 @@ namespace src.player.skills
{ {
private const Skills skillName = Skills.Jackal; private const Skills skillName = Skills.Jackal;
private static readonly ConcurrentDictionary<ulong, byte> playersInAction = []; private static readonly ConcurrentDictionary<ulong, byte> playersInAction = [];
private static readonly ConcurrentDictionary<CCSPlayerController, CParticleSystem?> playersStep = []; private static readonly ConcurrentDictionary<uint, uint?> playersStep = [];
private static readonly string particleName = "particles/ui/hud/ui_map_def_utility_trail.vpcf"; private static readonly ConcurrentDictionary<ulong, Timer?> activeTimers = [];
public static void LoadSkill() public static void LoadSkill()
{ {
@ -23,9 +24,15 @@ namespace src.player.skills
public static void NewRound() public static void NewRound()
{ {
foreach (var step in playersStep.Values) foreach (var particleIndex in playersStep.Values)
if (step != null && step.IsValid) {
step.AcceptInput("Kill"); if (particleIndex == null) continue;
var particle = Utilities.GetEntityFromIndex<CParticleSystem>((int)particleIndex);
if (particle != null && particle.IsValid)
particle.AcceptInput("Kill");
}
playersStep.Clear(); playersStep.Clear();
playersInAction.Clear(); playersInAction.Clear();
} }
@ -51,11 +58,15 @@ namespace src.player.skills
foreach (var param in playersStep) foreach (var param in playersStep)
{ {
var enemy = param.Key; var enemyIndex = param.Key;
var step = param.Value; var particleIndex = param.Value;
if (step == null || !step.IsValid) continue;
var entity = Utilities.GetEntityFromIndex<CBaseEntity>((int)step.Index); if (particleIndex == null) continue;
var enemy = Utilities.GetPlayerFromIndex((int)enemyIndex);
if (enemy == null || !enemy.IsValid) continue;
var entity = Utilities.GetEntityFromIndex<CBaseEntity>((int)particleIndex);
if (entity == null || !entity.IsValid) continue; if (entity == null || !entity.IsValid) continue;
if (!hasSkill || enemy.Team == player.Team) if (!hasSkill || enemy.Team == player.Team)
@ -69,13 +80,17 @@ namespace src.player.skills
if (player == null) return; if (player == null) return;
var playerPawn = player.PlayerPawn.Value; var playerPawn = player.PlayerPawn.Value;
ulong steamID = player.SteamID;
if (activeTimers.TryRemove(steamID, out var oldTimer))
oldTimer?.Kill();
if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null || playerPawn.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null || playerPawn.LifeState != (byte)LifeState_t.LIFE_ALIVE) return;
if (!playersStep.ContainsKey(player)) return; if (!playersStep.ContainsKey(player.Index)) return;
CParticleSystem particle = Utilities.CreateEntityByName<CParticleSystem>("info_particle_system")!; CParticleSystem particle = Utilities.CreateEntityByName<CParticleSystem>("info_particle_system")!;
if (particle == null) return; if (particle == null) return;
particle.EffectName = particleName; particle.EffectName = SkillsInfo.GetValue<string>(skillName, "particleName");
particle.StartActive = true; particle.StartActive = true;
particle.Teleport(playerPawn.AbsOrigin); particle.Teleport(playerPawn.AbsOrigin);
@ -84,12 +99,18 @@ namespace src.player.skills
particle.AcceptInput("SetParent", playerPawn, particle, "!activator"); particle.AcceptInput("SetParent", playerPawn, particle, "!activator");
particle.AcceptInput("Start"); particle.AcceptInput("Start");
playersStep.AddOrUpdate(player, particle, (k, v) => particle); uint particleId = particle.Index;
Instance.AddTimer(2.5f, () => { playersStep.AddOrUpdate(player.Index, particle.Index, (k, v) => particle.Index);
activeTimers[player.SteamID] = Instance.AddTimer(2.5f, () => {
var particle = Utilities.GetEntityFromIndex<CParticleSystem>((int)particleId);
if (particle != null && particle.IsValid) if (particle != null && particle.IsValid)
particle.AcceptInput("Kill"); particle.AcceptInput("Kill");
CreatePlayerTrail(player);
var player = Utilities.GetPlayerFromSteamId(steamID);
if (player != null && player.IsValid && playersStep.ContainsKey(player.Index))
CreatePlayerTrail(player);
}); });
} }
@ -99,23 +120,30 @@ namespace src.player.skills
playersInAction.TryAdd(player.SteamID, 0); playersInAction.TryAdd(player.SteamID, 0);
foreach (var _player in Utilities.GetPlayers().Where(p => p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.PawnIsAlive && p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist)) foreach (var _player in Utilities.GetPlayers().Where(p => p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.PawnIsAlive && p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist))
{ {
if (!playersStep.ContainsKey(_player)) if (!playersStep.ContainsKey(_player.Index))
playersStep.TryAdd(_player, null); playersStep.TryAdd(_player.Index, null);
CreatePlayerTrail(_player); CreatePlayerTrail(_player);
} }
} }
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
{ {
playersStep.TryRemove(player, out _);
playersInAction.TryRemove(player.SteamID, out _); playersInAction.TryRemove(player.SteamID, out _);
if (playersStep.TryRemove(player.Index, out var particleIndex) && particleIndex != null)
{
var particle = Utilities.GetEntityFromIndex<CParticleSystem>((int)particleIndex);
if (particle != null && particle.IsValid)
particle.AcceptInput("Kill");
}
if (playersInAction.IsEmpty) if (playersInAction.IsEmpty)
NewRound(); NewRound();
} }
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#f542ef", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", string particleName = "particles/ui/hud/ui_map_def_utility_trail.vpcf") : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#f542ef", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", string particleName = "particles/ui/hud/ui_map_def_utility_trail.vpcf") : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)
{ {
string ParticleName { get; set; } = particleName; public string ParticleName { get; set; } = particleName;
} }
} }
} }

View file

@ -10,7 +10,7 @@ namespace src.player.skills
public class Jammer : ISkill public class Jammer : ISkill
{ {
private const Skills skillName = Skills.Jammer; private const Skills skillName = Skills.Jammer;
private static readonly ConcurrentDictionary<CCSPlayerController, byte> jammedPlayers = []; private static readonly ConcurrentDictionary<uint, byte> jammedPlayers = [];
private static readonly object setLock = new(); private static readonly object setLock = new();
public static void LoadSkill() public static void LoadSkill()
@ -22,8 +22,12 @@ namespace src.player.skills
{ {
lock (setLock) lock (setLock)
{ {
foreach (var player in jammedPlayers.Keys) foreach (var playerIndex in jammedPlayers.Keys)
{
var player = Utilities.GetPlayerFromIndex((int)playerIndex);
if (player == null || !player.IsValid) continue;
SetCrosshair(player, true); SetCrosshair(player, true);
}
jammedPlayers.Clear(); jammedPlayers.Clear();
} }
foreach (var player in Utilities.GetPlayers()) foreach (var player in Utilities.GetPlayers())
@ -67,7 +71,7 @@ namespace src.player.skills
return; return;
} }
jammedPlayers.TryAdd(enemy, 0); jammedPlayers.TryAdd(enemy.Index, 0);
SetCrosshair(enemy, false); SetCrosshair(enemy, false);
playerInfo.SkillUsed = true; playerInfo.SkillUsed = true;
player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("jammer_player_info", enemy.PlayerName)); player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("jammer_player_info", enemy.PlayerName));
@ -103,7 +107,7 @@ namespace src.player.skills
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
{ {
SetCrosshair(player, true); SetCrosshair(player, true);
jammedPlayers.TryRemove(player, out _); jammedPlayers.TryRemove(player.Index, out _);
SkillUtils.CloseMenu(player); SkillUtils.CloseMenu(player);
} }

View file

@ -1,5 +1,6 @@
using CounterStrikeSharp.API; using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Entities;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using src.utils; using src.utils;
using System.Collections.Concurrent; using System.Collections.Concurrent;
@ -12,7 +13,7 @@ namespace src.player.skills
public class Jester : ISkill public class Jester : ISkill
{ {
private const Skills skillName = Skills.Jester; private const Skills skillName = Skills.Jester;
private static readonly ConcurrentBag<JesterInfo> jesters = []; private static readonly ConcurrentDictionary<ulong, JesterInfo> jesters = [];
public static void LoadSkill() public static void LoadSkill()
{ {
@ -23,7 +24,7 @@ namespace src.player.skills
{ {
Server.NextWorldUpdate(() => Server.NextWorldUpdate(() =>
{ {
foreach (var jester in jesters.ToList()) foreach (var jester in jesters.Values)
{ {
if (jester.Timer != null) if (jester.Timer != null)
{ {
@ -71,7 +72,8 @@ namespace src.player.skills
var player = @event.Userid; var player = @event.Userid;
if (player == null || !player.IsValid) return; if (player == null || !player.IsValid) return;
var jester = GetJesterInfo(player.SteamID); ulong steamId = player.SteamID;
var jester = GetJesterInfo(steamId);
if (jester == null) return; if (jester == null) return;
if (jester.Timer != null) if (jester.Timer != null)
@ -81,8 +83,7 @@ namespace src.player.skills
} }
jester.Timer = Instance.AddTimer(1, () => { jester.Timer = Instance.AddTimer(1, () => {
if (player != null && player.IsValid) ChangeMode(steamId, false);
ChangeMode(player.SteamID, false);
}); });
} }
@ -91,7 +92,8 @@ namespace src.player.skills
var player = @event.Userid; var player = @event.Userid;
if (player == null || !player.IsValid) return; if (player == null || !player.IsValid) return;
var jester = GetJesterInfo(player.SteamID); ulong steamId = player.SteamID;
var jester = GetJesterInfo(steamId);
if (jester == null) return; if (jester == null) return;
if (jester.Timer != null) if (jester.Timer != null)
@ -102,7 +104,7 @@ namespace src.player.skills
jester.Timer = Instance.AddTimer(1, () => { jester.Timer = Instance.AddTimer(1, () => {
if (player != null && player.IsValid) if (player != null && player.IsValid)
ChangeMode(player.SteamID, false); ChangeMode(steamId, false);
}); });
} }
@ -133,20 +135,18 @@ namespace src.player.skills
var maxTime = SkillsInfo.GetValue<float>(skillName, "maxTime"); var maxTime = SkillsInfo.GetValue<float>(skillName, "maxTime");
float wait = (float)Instance.Random.NextDouble() * (maxTime - minTime) + minTime; float wait = (float)Instance.Random.NextDouble() * (maxTime - minTime) + minTime;
jesters.Add(new JesterInfo { ulong steamId = player.SteamID;
SteamId = player.SteamID,
jesters.TryAdd(steamId, new JesterInfo {
SteamId = steamId,
Active = false, Active = false,
Timer = Instance.AddTimer(wait, () => ChangeMode(player.SteamID)) Timer = Instance.AddTimer(wait, () => ChangeMode(steamId))
}); });
} }
private static void ChangeMode(ulong steamId, bool? forceActive = null) private static void ChangeMode(ulong steamId, bool? forceActive = null)
{ {
var player = Utilities.GetPlayerFromSteamId(steamId); if (!jesters.TryGetValue(steamId, out var jester)) return;
if (player == null || !player.IsValid || !player.PawnIsAlive) return;
var jester = GetJesterInfo(player.SteamID);
if (jester == null) return;
if (jester.Timer != null) if (jester.Timer != null)
{ {
@ -154,6 +154,13 @@ namespace src.player.skills
jester.Timer = null; jester.Timer = null;
} }
var player = Utilities.GetPlayerFromSteamId(steamId);
if (player == null || !player.IsValid || !player.PawnIsAlive)
{
jesters.TryRemove(steamId, out _);
return;
}
bool previousState = jester.Active; bool previousState = jester.Active;
jester.Active = forceActive ?? !jester.Active; jester.Active = forceActive ?? !jester.Active;
@ -167,7 +174,7 @@ namespace src.player.skills
var maxTime = SkillsInfo.GetValue<float>(skillName, "maxTime"); var maxTime = SkillsInfo.GetValue<float>(skillName, "maxTime");
float wait = (float)Instance.Random.NextDouble() * (maxTime - minTime) + minTime; float wait = (float)Instance.Random.NextDouble() * (maxTime - minTime) + minTime;
jester.Timer = Instance.AddTimer(wait, () => ChangeMode(player.SteamID)); jester.Timer = Instance.AddTimer(wait, () => ChangeMode(steamId));
} }
private static void SetPlayerColor(CCSPlayerController? player, bool forceDisable = false) private static void SetPlayerColor(CCSPlayerController? player, bool forceDisable = false)
@ -208,7 +215,12 @@ namespace src.player.skills
playerInfo.PrintHTML = $"{player.GetTranslation("jester_mode")}: <font color='{(jester.Active ? "#00ff00" : "#ff0000")}'>{player.GetTranslation(jester.Active ? "jester_on" : "jester_off")}</font>"; playerInfo.PrintHTML = $"{player.GetTranslation("jester_mode")}: <font color='{(jester.Active ? "#00ff00" : "#ff0000")}'>{player.GetTranslation(jester.Active ? "jester_on" : "jester_off")}</font>";
} }
public static JesterInfo? GetJesterInfo(ulong steamID) => jesters.FirstOrDefault(j => j.SteamId == steamID); public static JesterInfo? GetJesterInfo(ulong steamID)
{
if (jesters.TryGetValue(steamID, value: out var info))
return info;
return null;
}
public class JesterInfo() public class JesterInfo()
{ {

View file

@ -10,7 +10,7 @@ namespace src.player.skills
public class JumpBan : ISkill public class JumpBan : ISkill
{ {
private const Skills skillName = Skills.JumpBan; private const Skills skillName = Skills.JumpBan;
public static readonly ConcurrentDictionary<CCSPlayerPawn, int> bannedPlayers = []; public static readonly ConcurrentDictionary<uint, int> bannedPlayers = [];
public static void LoadSkill() public static void LoadSkill()
{ {
@ -28,19 +28,25 @@ namespace src.player.skills
{ {
var player = @event.Userid; var player = @event.Userid;
if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return; if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return;
if (!bannedPlayers.TryGetValue(player.PlayerPawn.Value, out _)) return; if (!bannedPlayers.TryGetValue(player.Index, out _)) return;
bannedPlayers.AddOrUpdate(player.PlayerPawn.Value, Server.TickCount + 10, (k, v) => Server.TickCount + 10); bannedPlayers.AddOrUpdate(player.Index, Server.TickCount + 10, (k, v) => Server.TickCount + 10);
} }
public static void OnTick() public static void OnTick()
{ {
foreach (var item in bannedPlayers) foreach (var item in bannedPlayers)
{ {
var pawn = item.Key; var playerIndex = item.Key;
var time = item.Value; var time = item.Value;
var player = Utilities.GetPlayerFromIndex((int)playerIndex);
if (player == null || !player.IsValid || player.PlayerPawn == null) continue;
var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid) continue;
if (time > Server.TickCount) if (time > Server.TickCount)
if (pawn != null && pawn.IsValid) pawn.AbsVelocity.Z = -100;
pawn.AbsVelocity.Z = -100;
} }
if (Server.TickCount % 32 != 0) return; if (Server.TickCount % 32 != 0) return;
@ -52,7 +58,7 @@ namespace src.player.skills
if (playerInfo == null || playerInfo.Skill != skillName) continue; if (playerInfo == null || playerInfo.Skill != skillName) continue;
var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray();
ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => (e.PlayerName, e.Index.ToString()))); ConcurrentBag<(string, string)> menuItems = [.. enemies.Select(e => (e.PlayerName, e.Index.ToString()))];
SkillUtils.UpdateMenu(player, menuItems); SkillUtils.UpdateMenu(player, menuItems);
} }
} }
@ -78,7 +84,7 @@ namespace src.player.skills
return; return;
} }
bannedPlayers.AddOrUpdate(enemy.PlayerPawn.Value, 0, (k, v) => 0); bannedPlayers.AddOrUpdate(enemy.Index, 0, (k, v) => 0);
playerInfo.SkillUsed = true; playerInfo.SkillUsed = true;
player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("jumpban_player_info", enemy.PlayerName)); player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("jumpban_player_info", enemy.PlayerName));
enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("jumpban_enemy_info")); enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("jumpban_enemy_info"));
@ -103,7 +109,7 @@ namespace src.player.skills
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
{ {
if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return; if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return;
bannedPlayers.TryRemove(player.PlayerPawn.Value, out _); bannedPlayers.TryRemove(player.Index, out _);
SkillUtils.CloseMenu(player); SkillUtils.CloseMenu(player);
} }

View file

@ -2,14 +2,9 @@
using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using CS2TraceRay.Class;
using CS2TraceRay.Enum;
using CS2TraceRay.Struct;
using src.utils; using src.utils;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Drawing;
using static src.jRandomSkills; using static src.jRandomSkills;
using Vector = CounterStrikeSharp.API.Modules.Utils.Vector;
namespace src.player.skills namespace src.player.skills
{ {
@ -22,8 +17,6 @@ namespace src.player.skills
private static readonly ConcurrentDictionary<ulong, byte> playersInAction = []; private static readonly ConcurrentDictionary<ulong, byte> playersInAction = [];
private static readonly MemoryFunctionVoid<IntPtr, short> Shoot_Secondary = new(GameData.GetSignature("Shoot_Secondary")); private static readonly MemoryFunctionVoid<IntPtr, short> Shoot_Secondary = new(GameData.GetSignature("Shoot_Secondary"));
private static int i = 0;
public static void LoadSkill() public static void LoadSkill()
{ {
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color")); SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
@ -95,40 +88,22 @@ namespace src.player.skills
private unsafe static void KnifeHit(CCSPlayerController player, bool heavyHit) private unsafe static void KnifeHit(CCSPlayerController player, bool heavyHit)
{ {
var pawn = player!.PlayerPawn.Value; var pawn = player!.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) return; if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null)
return;
Vector eyePos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z); var result = RayTrace.EyeTrace(player);
Vector endPos = eyePos + SkillUtils.GetForwardVector(pawn.EyeAngles) * SkillsInfo.GetValue<float>(skillName, "maxDistance"); if (result == null || !result.HasValue)
return;
ulong hitboxes = 0x2; if (!result.Value.HitPlayer(out CCSPlayerController? target) || target == null)
ulong mask = pawn.Collision.CollisionAttribute.InteractsWith | hitboxes; return;
ulong contents = pawn.Collision.CollisionGroup;
CGameTrace trace = TraceRay.TraceShape(eyePos, endPos, mask, contents, player);
if (Config.LoadedConfig.CS2TraceRayDebug) if (target.Handle == player.Handle || result.Value.Distance() <= 70)
{ return;
SkillUtils.CreateLine(eyePos, endPos, Color.FromArgb(255, 255, 255, 0));
SkillUtils.CreateLine(new Vector(trace.StartPos.X, trace.StartPos.Y, trace.StartPos.Z), new Vector(trace.EndPos.X, trace.EndPos.Y, trace.EndPos.Z), Color.FromArgb(255, 255, 0, 0)); if (target.PlayerPawn.Value == null || !target.PlayerPawn.Value.IsValid)
SkillUtils.CreateLine(new Vector(trace.StartPos.X, trace.StartPos.Y, trace.StartPos.Z), new Vector(trace.Position.X, trace.Position.Y, trace.Position.Z), Color.FromArgb(255, 0, 0, 255));
if (trace.DidHit())
{
var val = Activator.CreateInstance(typeof(CBaseEntity), trace.HitEntity) as CBaseEntity;
player.PrintToChat($"Hit: {trace.DidHit()}, Entity: {(val == null ? "null" : val.DesignerName)}, Solid: {trace.AllSolid}, Contents: {(Contents)trace.Contents}, Hitbox: {trace.HitboxData[0].HitGroup}");
}
else
player.PrintToChat($"Hit: {trace.DidHit()}, Object: {trace.HitEntity}, Solid: {trace.AllSolid}, Contents: {(Contents)trace.Contents}, Hitbox: {trace.HitboxData[0].HitGroup}");
}
CEntityInstance entityInstance = new(trace.HitEntity);
if (string.IsNullOrEmpty(entityInstance.DesignerName))
return; return;
CBaseEntity entity = entityInstance.As<CBaseEntity>();
if (!trace.HitPlayer(out CCSPlayerController? target) || target == null)
return;
if (target.Handle == player.Handle || target.PlayerPawn.Value == null || !target.PlayerPawn.Value.IsValid || trace.Distance() <= 70) return;
if (!SkillsInfo.GetValue<bool>(skillName, "friendlyFire") && player.Team == target.Team) return; if (!SkillsInfo.GetValue<bool>(skillName, "friendlyFire") && player.Team == target.Team) return;
target.PlayerPawn.Value.EmitSound("Player.DamageBody.Onlooker"); target.PlayerPawn.Value.EmitSound("Player.DamageBody.Onlooker");

View file

@ -1,13 +1,8 @@
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 CS2TraceRay.Class;
using CS2TraceRay.Enum;
using CS2TraceRay.Struct;
using src.utils; using src.utils;
using System.Drawing;
using static src.jRandomSkills; using static src.jRandomSkills;
using Vector = CounterStrikeSharp.API.Modules.Utils.Vector;
namespace src.player.skills namespace src.player.skills
{ {
@ -34,30 +29,11 @@ namespace src.player.skills
var activeWeapon = pawn.WeaponServices.ActiveWeapon.Value; var activeWeapon = pawn.WeaponServices.ActiveWeapon.Value;
if (activeWeapon == null || !activeWeapon.IsValid || activeWeapon.DesignerName != "weapon_taser") return; if (activeWeapon == null || !activeWeapon.IsValid || activeWeapon.DesignerName != "weapon_taser") return;
Vector eyePos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z); var result = RayTrace.EyeTrace(player);
Vector endPos = eyePos + SkillUtils.GetForwardVector(pawn.EyeAngles) * SkillsInfo.GetValue<float>(skillName, "maxDistance"); if (result == null || !result.HasValue)
return;
ulong hitboxes = 0x2; if (!result.Value.HitPlayer(out CCSPlayerController? target) || target == null)
ulong mask = pawn.Collision.CollisionAttribute.InteractsWith | hitboxes;
ulong contents = pawn.Collision.CollisionGroup;
CGameTrace trace = TraceRay.TraceShape(eyePos, endPos, mask, contents, player);
if (Config.LoadedConfig.CS2TraceRayDebug)
{
SkillUtils.CreateLine(eyePos, endPos, Color.FromArgb(255, 255, 255, 0));
SkillUtils.CreateLine(new Vector(trace.StartPos.X, trace.StartPos.Y, trace.StartPos.Z), new Vector(trace.EndPos.X, trace.EndPos.Y, trace.EndPos.Z), Color.FromArgb(255, 255, 0, 0));
SkillUtils.CreateLine(new Vector(trace.StartPos.X, trace.StartPos.Y, trace.StartPos.Z), new Vector(trace.Position.X, trace.Position.Y, trace.Position.Z), Color.FromArgb(255, 0, 0, 255));
if (trace.DidHit())
{
var val = Activator.CreateInstance(typeof(CBaseEntity), trace.HitEntity) as CBaseEntity;
player.PrintToChat($"Hit: {trace.DidHit()}, Entity: {(val == null ? "null" : val.DesignerName)}, Solid: {trace.AllSolid}, Contents: {(Contents)trace.Contents}, Hitbox: {trace.HitboxData[0].HitGroup}");
}
else
player.PrintToChat($"Hit: {trace.DidHit()}, Object: {trace.HitEntity}, Solid: {trace.AllSolid}, Contents: {(Contents)trace.Contents}, Hitbox: {trace.HitboxData[0].HitGroup}");
}
if (!trace.HitPlayer(out CCSPlayerController? target) || target == null)
return; return;
if (target.Handle == player.Handle) return; if (target.Handle == player.Handle) return;

View file

@ -10,7 +10,7 @@ namespace src.player.skills
public class Magnifier : ISkill public class Magnifier : ISkill
{ {
private const Skills skillName = Skills.Magnifier; private const Skills skillName = Skills.Magnifier;
private static readonly ConcurrentDictionary<CCSPlayerController, uint> playersFOV = []; private static readonly ConcurrentDictionary<uint, uint> playersFOV = [];
public static void LoadSkill() public static void LoadSkill()
{ {
@ -19,8 +19,13 @@ namespace src.player.skills
public static void NewRound() public static void NewRound()
{ {
foreach (var player in playersFOV.Keys) foreach (var playerIndex in playersFOV.Keys)
{
var player = Utilities.GetPlayerFromIndex((int)playerIndex);
if (player == null || player.IsValid) continue;
DisableSkill(player); DisableSkill(player);
}
playersFOV.Clear(); playersFOV.Clear();
foreach (var player in Utilities.GetPlayers()) foreach (var player in Utilities.GetPlayers())
SkillUtils.CloseMenu(player); SkillUtils.CloseMenu(player);
@ -70,8 +75,8 @@ namespace src.player.skills
return; return;
} }
if (!playersFOV.ContainsKey(enemy)) if (!playersFOV.ContainsKey(enemy.Index))
playersFOV.TryAdd(enemy, enemy.DesiredFOV); playersFOV.TryAdd(enemy.Index, enemy.DesiredFOV);
enemy.DesiredFOV = SkillsInfo.GetValue<uint>(skillName, "customFOV"); enemy.DesiredFOV = SkillsInfo.GetValue<uint>(skillName, "customFOV");
Utilities.SetStateChanged(enemy, "CBasePlayerController", "m_iDesiredFOV"); Utilities.SetStateChanged(enemy, "CBasePlayerController", "m_iDesiredFOV");
@ -98,12 +103,12 @@ namespace src.player.skills
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
{ {
if (playersFOV.TryGetValue(player, out uint fov)) if (playersFOV.TryGetValue(player.Index, out uint fov))
{ {
player.DesiredFOV = fov; player.DesiredFOV = fov;
Utilities.SetStateChanged(player, "CBasePlayerController", "m_iDesiredFOV"); Utilities.SetStateChanged(player, "CBasePlayerController", "m_iDesiredFOV");
} }
playersFOV.TryRemove(player, out _); playersFOV.TryRemove(player.Index, out _);
SkillUtils.CloseMenu(player); SkillUtils.CloseMenu(player);
} }

View file

@ -13,7 +13,7 @@ namespace src.player.skills
{ {
private const Skills skillName = Skills.Ninja; private const Skills skillName = Skills.Ninja;
private static readonly ConcurrentDictionary<nint, float> invisibilityChanged = []; private static readonly ConcurrentDictionary<nint, float> invisibilityChanged = [];
private static readonly ConcurrentDictionary<CCSPlayerController, byte> invisiblePlayers = []; private static readonly ConcurrentDictionary<uint, byte> invisiblePlayers = [];
private const string bloodParticle = "particles/blood_impact/blood_impact_high.vpcf"; private const string bloodParticle = "particles/blood_impact/blood_impact_high.vpcf";
private static readonly object setLock = new(); private static readonly object setLock = new();
@ -68,22 +68,28 @@ namespace src.player.skills
if (targetInfo?.Skill == skillName) isObservingNinja = true; if (targetInfo?.Skill == skillName) isObservingNinja = true;
} }
foreach (var _player in invisiblePlayers.Keys) foreach (var playerIndex in invisiblePlayers.Keys)
if (player.SteamID != _player.SteamID && !isObservingNinja) {
var playerController = Utilities.GetPlayerFromIndex((int)playerIndex);
if (playerController == null || !playerController.IsValid || playerController.SteamID == player.SteamID)
continue;
if (!isObservingNinja)
{ {
var playerPawn = _player.PlayerPawn.Value; var playerPawn = playerController.PlayerPawn.Value;
if (playerPawn == null || !playerPawn.IsValid) continue; if (playerPawn == null || !playerPawn.IsValid) continue;
var entity = Utilities.GetEntityFromIndex<CBaseEntity>((int)playerPawn.Index); var entity = Utilities.GetEntityFromIndex<CBaseEntity>((int)playerPawn.Index);
if (entity == null || !entity.IsValid) continue; if (entity == null || !entity.IsValid) continue;
info.TransmitEntities.Remove(entity.Index); info.TransmitEntities.Remove(entity.Index);
var bombIndex = GetBombIndex(_player); var bombIndex = GetBombIndex(playerController);
if (bombIndex == null) continue; if (bombIndex == null) continue;
var bombEntity = Utilities.GetEntityFromIndex<CBaseEntity>((int)bombIndex); var bombEntity = Utilities.GetEntityFromIndex<CBaseEntity>((int)bombIndex);
if (bombEntity == null || !bombEntity.IsValid) continue; if (bombEntity == null || !bombEntity.IsValid) continue;
info.TransmitEntities.Remove(bombEntity.Index); info.TransmitEntities.Remove(bombEntity.Index);
} }
}
} }
} }
@ -95,7 +101,7 @@ namespace src.player.skills
if (playerInfo?.Skill == skillName) if (playerInfo?.Skill == skillName)
UpdateNinja(player); UpdateNinja(player);
if (!player.PawnIsAlive) if (!player.PawnIsAlive)
invisiblePlayers.TryRemove(player, out _); invisiblePlayers.TryRemove(player.Index, out _);
} }
} }
@ -107,7 +113,7 @@ namespace src.player.skills
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
{ {
SetPlayerVisibility(player, 0); SetPlayerVisibility(player, 0);
invisiblePlayers.TryRemove(player, out _); invisiblePlayers.TryRemove(player.Index, out _);
} }
private static void UpdateNinja(CCSPlayerController? player) private static void UpdateNinja(CCSPlayerController? player)
@ -136,14 +142,14 @@ namespace src.player.skills
if (percentInvisibility == oldInvisibility) if (percentInvisibility == oldInvisibility)
return; return;
invisibilityChanged.TryAdd(player.Handle, percentInvisibility); invisibilityChanged.AddOrUpdate(player.Handle, percentInvisibility, (_, _) => percentInvisibility);
if (percentInvisibility > .9) if (percentInvisibility > .9)
invisiblePlayers.TryAdd(player, 0); invisiblePlayers.TryAdd(player.Index, 0);
else else
{ {
SetPlayerVisibility(player, percentInvisibility); SetPlayerVisibility(player, percentInvisibility);
invisiblePlayers.TryRemove(player, out _); invisiblePlayers.TryRemove(player.Index, out _);
} }
} }
@ -162,7 +168,7 @@ namespace src.player.skills
{ {
var player = @event.Userid; var player = @event.Userid;
if (player == null || !player.IsValid) return; if (player == null || !player.IsValid) return;
if (!invisiblePlayers.ContainsKey(player)) return; if (!invisiblePlayers.ContainsKey(player.Index)) return;
var playerPawn = player.PlayerPawn.Value; var playerPawn = player.PlayerPawn.Value;
if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return; if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return;

View file

@ -41,8 +41,14 @@ namespace src.player.skills
{ {
var pawn = player.PlayerPawn.Value; var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid || pawn.CameraServices == null) continue; if (pawn == null || !pawn.IsValid || pawn.CameraServices == null) continue;
pawn.AimPunchTickBase = 0;
pawn.AimPunchTickFraction = 0f; if (pawn.AimPunchServices != null)
{
pawn.AimPunchServices.PredictableBaseTick = 0;
pawn.AimPunchServices.PredictableBaseTickInterpAmount = 0;
pawn.AimPunchServices.UnpredictableBaseTick = 0;
}
pawn.CameraServices.CsViewPunchAngleTick = 0; pawn.CameraServices.CsViewPunchAngleTick = 0;
pawn.CameraServices.CsViewPunchAngleTickRatio = 0f; pawn.CameraServices.CsViewPunchAngleTickRatio = 0f;
} }

View file

@ -1,9 +1,8 @@
using CounterStrikeSharp.API; using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Entities;
using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Memory;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using CS2TraceRay.Class;
using CS2TraceRay.Struct;
using src.utils; using src.utils;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using static src.jRandomSkills; using static src.jRandomSkills;
@ -93,7 +92,9 @@ namespace src.player.skills
var playerPawn = player.PlayerPawn.Value; var playerPawn = player.PlayerPawn.Value;
if (playerPawn?.CBodyComponent == null) return; if (playerPawn?.CBodyComponent == null) return;
if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) ulong steamId = player.SteamID;
if (SkillPlayerInfo.TryGetValue(steamId, out var skillInfo))
{ {
if (skillInfo.IsFlying) if (skillInfo.IsFlying)
{ {
@ -109,11 +110,18 @@ namespace src.player.skills
skillInfo.IsFlying = true; skillInfo.IsFlying = true;
skillInfo.Cooldown = DateTime.Now; skillInfo.Cooldown = DateTime.Now;
skillInfo.LastPosition = playerPawn.AbsOrigin == null ? null : new Vector(playerPawn.AbsOrigin.X, playerPawn.AbsOrigin.Y, playerPawn.AbsOrigin.Z); skillInfo.LastPosition = playerPawn.AbsOrigin == null ? null : new Vector(playerPawn.AbsOrigin.X, playerPawn.AbsOrigin.Y, playerPawn.AbsOrigin.Z);
SetNoclip(player, true); SetNoclip(player, true);
skillInfo.Timer?.Kill(); skillInfo.Timer?.Kill();
skillInfo.Timer = Instance.AddTimer(duration, () => skillInfo.Timer = Instance.AddTimer(duration, () =>
{ {
var player = Utilities.GetPlayerFromSteamId(steamId);
if (player == null || !player.IsValid) return;
var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == steamId);
if (playerInfo == null) return;
StopFlying(player, skillInfo); StopFlying(player, skillInfo);
}); });
} }
@ -174,54 +182,39 @@ namespace src.player.skills
ulong mask = playerPawn.Collision.CollisionAttribute.InteractsWith; ulong mask = playerPawn.Collision.CollisionAttribute.InteractsWith;
ulong contents = playerPawn.Collision.CollisionGroup; ulong contents = playerPawn.Collision.CollisionGroup;
bool hasGround = false; bool hasGround = false;
Vector stuckVector = new(currentPos.X, currentPos.Y, currentPos.Z);
foreach (Vector targetPos in checkOffsets) foreach (Vector targetPos in checkOffsets)
{ {
Vector start = new(targetPos.X, targetPos.Y, targetPos.Z + 70); Vector start = new(targetPos.X, targetPos.Y, targetPos.Z + 70);
Vector end = new(targetPos.X, targetPos.Y, targetPos.Z - 1000); Vector end = new(targetPos.X, targetPos.Y, targetPos.Z - 1000);
CGameTrace groundTrace = TraceRay.TraceShape(start, end, mask, contents, player); var groundResult = RayTrace.TraceShape(player, start, end, mask, contents);
if (!groundTrace.DidHit()) continue; if (!groundResult.HasValue || !groundResult.Value.DidHit) continue;
hasGround = true;
Vector newPos = Vector newPos =
groundTrace.EndPos.Z > targetPos.Z groundResult.Value.EndPos.Z > targetPos.Z
? new(groundTrace.EndPos.X, groundTrace.EndPos.Y, groundTrace.EndPos.Z) ? new(groundResult.Value.EndPos.X, groundResult.Value.EndPos.Y, groundResult.Value.EndPos.Z)
: targetPos; : targetPos;
if (IsPositionSafe(newPos, player)) hasGround = true;
stuckVector = newPos;
var result = RayTrace.TraceHullShape(
targetPos,
targetPos,
player
);
if (result.HasValue && !result.Value.DidHit)
return newPos; return newPos;
} }
if (hasGround) if (hasGround)
skillInfo.Cooldown = DateTime.Now.AddSeconds(-SkillsInfo.GetValue<float>(skillName, "cooldown") + SkillsInfo.GetValue<float>(skillName, "cooldownWhenStuck")); skillInfo.Cooldown = DateTime.Now.AddSeconds(-SkillsInfo.GetValue<float>(skillName, "cooldown") + SkillsInfo.GetValue<float>(skillName, "cooldownWhenStuck"));
return hasGround ? currentPos : null; return hasGround ? stuckVector : null;
}
private static bool IsPositionSafe(Vector pos, CCSPlayerController player)
{
var playerPawn = player.PlayerPawn.Value;
if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return false;
float footHeight = 0;
float headHeight = 70;
float innerDist = 12;
ulong mask = playerPawn.Collision.CollisionAttribute.InteractsWith;
ulong contents = playerPawn.Collision.CollisionGroup;
Vector s1 = new(pos.X - innerDist, pos.Y - innerDist, pos.Z + footHeight);
Vector e1 = new(pos.X + innerDist, pos.Y + innerDist, pos.Z + headHeight);
CGameTrace t1 = TraceRay.TraceShape(s1, e1, mask, contents, player);
if (t1.DidHit() || t1.AllSolid) return false;
Vector s2 = new(pos.X + innerDist, pos.Y - innerDist, pos.Z + footHeight);
Vector e2 = new(pos.X - innerDist, pos.Y + innerDist, pos.Z + headHeight);
CGameTrace t2 = TraceRay.TraceShape(s2, e2, mask, contents, player);
if (t2.DidHit() || t2.AllSolid) return false;
return true;
} }
public class PlayerSkillInfo public class PlayerSkillInfo

View file

@ -1,5 +1,6 @@
using CounterStrikeSharp.API; using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Entities;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using src.utils; using src.utils;
using static src.jRandomSkills; using static src.jRandomSkills;
@ -29,7 +30,15 @@ namespace src.player.skills
lock (setLock) lock (setLock)
{ {
player.Respawn(); player.Respawn();
Instance.AddTimer(.2f, () => player.Respawn()); ulong steamId = player.SteamID;
Instance.AddTimer(.2f, () => {
var player = Utilities.GetPlayerFromSteamId(steamId);
if (player == null || !player.IsValid) return;
player.Respawn();
});
SkillUtils.PrintToChat(player, player.GetTranslation("phoenix_respawn")); SkillUtils.PrintToChat(player, player.GetTranslation("phoenix_respawn"));
} }
} }

View file

@ -45,7 +45,10 @@ namespace src.player.skills
var plantedBomb = Utilities.FindAllEntitiesByDesignerName<CPlantedC4>("planted_c4").FirstOrDefault(); var plantedBomb = Utilities.FindAllEntitiesByDesignerName<CPlantedC4>("planted_c4").FirstOrDefault();
if (plantedBomb != null) if (plantedBomb != null)
Server.NextFrame(() => plantedBomb.C4Blow = Server.CurrentTime + SkillsInfo.GetValue<int>(skillName, "extraC4BlowTime")); Server.NextFrame(() => {
if (plantedBomb != null && plantedBomb.IsValid)
plantedBomb.C4Blow = Server.CurrentTime + SkillsInfo.GetValue<int>(skillName, "extraC4BlowTime");
});
foreach (var p in Utilities.GetPlayers().Where(p => p.IsValid)) foreach (var p in Utilities.GetPlayers().Where(p => p.IsValid))
p.PrintToCenterAlert(p.GetTranslation("bombplanted", SkillsInfo.GetValue<int>(skillName, "extraC4BlowTime"))); p.PrintToCenterAlert(p.GetTranslation("bombplanted", SkillsInfo.GetValue<int>(skillName, "extraC4BlowTime")));

View file

@ -10,7 +10,7 @@ namespace src.player.skills
public class Poison : ISkill public class Poison : ISkill
{ {
private const Skills skillName = Skills.Poison; private const Skills skillName = Skills.Poison;
private static readonly ConcurrentDictionary<CCSPlayerController, byte> poisonedPlayers = []; private static readonly ConcurrentDictionary<uint, byte> poisonedPlayers = [];
private static readonly object setLock = new(); private static readonly object setLock = new();
public static void LoadSkill() public static void LoadSkill()
@ -28,10 +28,14 @@ namespace src.player.skills
{ {
if (Server.TickCount % (int)(64 * SkillsInfo.GetValue<float>(skillName, "Cooldown")) == 0) if (Server.TickCount % (int)(64 * SkillsInfo.GetValue<float>(skillName, "Cooldown")) == 0)
{ {
foreach (var player in poisonedPlayers.Keys) foreach (var playerIndex in poisonedPlayers.Keys)
{ {
var player = Utilities.GetPlayerFromIndex((int)playerIndex);
if (player == null || !player.IsValid || player.PlayerPawn == null) continue;
var pawn = player.PlayerPawn.Value; var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid) continue; if (pawn == null || !pawn.IsValid) continue;
if (pawn.Health <= SkillsInfo.GetValue<int>(skillName, "MinHealth")) continue; if (pawn.Health <= SkillsInfo.GetValue<int>(skillName, "MinHealth")) continue;
SkillUtils.TakeHealth(pawn, SkillsInfo.GetValue<int>(skillName, "Damage")); SkillUtils.TakeHealth(pawn, SkillsInfo.GetValue<int>(skillName, "Damage"));
} }
@ -72,7 +76,7 @@ namespace src.player.skills
return; return;
} }
poisonedPlayers.TryAdd(enemy, 0); poisonedPlayers.TryAdd(enemy.Index, 0);
playerInfo.SkillUsed = true; playerInfo.SkillUsed = true;
player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("poison_player_info", enemy.PlayerName)); player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("poison_player_info", enemy.PlayerName));
enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("poison_enemy_info")); enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("poison_enemy_info"));
@ -96,7 +100,7 @@ namespace src.player.skills
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
{ {
poisonedPlayers.TryRemove(player, out _); poisonedPlayers.TryRemove(player.Index, out _);
SkillUtils.CloseMenu(player); SkillUtils.CloseMenu(player);
} }

View file

@ -4,14 +4,13 @@ using CounterStrikeSharp.API.Modules.Utils;
using static src.jRandomSkills; using static src.jRandomSkills;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using src.utils; using src.utils;
using CounterStrikeSharp.API.Modules.Entities.Constants;
namespace src.player.skills namespace src.player.skills
{ {
public class PsychicDefusing : ISkill public class PsychicDefusing : ISkill
{ {
private const Skills skillName = Skills.PsychicDefusing; private const Skills skillName = Skills.PsychicDefusing;
private static readonly ConcurrentDictionary<CCSPlayerPawn, PlayerSkillInfo> SkillPlayerInfo = []; private static readonly ConcurrentDictionary<uint, PlayerSkillInfo> SkillPlayerInfo = [];
private static Vector? bombLocation = null; private static Vector? bombLocation = null;
private static readonly float tickRate = 64f; private static readonly float tickRate = 64f;
private static readonly object setLock = new(); private static readonly object setLock = new();
@ -35,12 +34,9 @@ namespace src.player.skills
var player = @event.Userid; var player = @event.Userid;
if (player == null || !player.IsValid) return; if (player == null || !player.IsValid) return;
var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid) return;
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo?.Skill == skillName) if (playerInfo?.Skill == skillName)
SkillPlayerInfo.TryRemove(pawn, out _); SkillPlayerInfo.TryRemove(player.Index, out _);
} }
public static void BombPlanted(EventBombPlanted _) public static void BombPlanted(EventBombPlanted _)
@ -55,15 +51,15 @@ namespace src.player.skills
if (bombLocation == null) return; if (bombLocation == null) return;
foreach (var skillInfo in SkillPlayerInfo) foreach (var skillInfo in SkillPlayerInfo)
{ {
var pawn = skillInfo.Key; var playerIndex = skillInfo.Key;
var info = skillInfo.Value; var info = skillInfo.Value;
var playerController = pawn.Controller.Value; var player = Utilities.GetPlayerFromIndex((int)playerIndex);
if (playerController == null || !pawn.Controller.IsValid) return; if (player == null || !player.IsValid || player.PlayerPawn == null) continue;
var player = playerController.As<CCSPlayerController>();
if (player == null || !player.IsValid) return;
var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid) continue;
if (pawn.AbsOrigin == null || SkillUtils.GetDistance(pawn.AbsOrigin, bombLocation) > SkillsInfo.GetValue<float>(skillName, "maxDefusingRange")) if (pawn.AbsOrigin == null || SkillUtils.GetDistance(pawn.AbsOrigin, bombLocation) > SkillsInfo.GetValue<float>(skillName, "maxDefusingRange"))
{ {
info.Defusing = false; info.Defusing = false;
@ -97,7 +93,8 @@ namespace src.player.skills
{ {
var pawn = player.PlayerPawn.Value; var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid) return; if (pawn == null || !pawn.IsValid) return;
SkillPlayerInfo.TryAdd(pawn, new PlayerSkillInfo
SkillPlayerInfo.TryAdd(player.Index, new PlayerSkillInfo
{ {
SteamID = player.SteamID, SteamID = player.SteamID,
Defusing = false, Defusing = false,
@ -108,9 +105,7 @@ namespace src.player.skills
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
{ {
SkillUtils.ResetPrintHTML(player); SkillUtils.ResetPrintHTML(player);
var pawn = player.PlayerPawn.Value; SkillPlayerInfo.TryRemove(player.Index, out _);
if (pawn == null || !pawn.IsValid) return;
SkillPlayerInfo.TryRemove(pawn, out _);
} }
private static void UpdateHUD(CCSPlayerController player, PlayerSkillInfo skillInfo) private static void UpdateHUD(CCSPlayerController player, PlayerSkillInfo skillInfo)

View file

@ -44,16 +44,16 @@ namespace src.player.skills
private static void PushEnemy(CCSPlayerController player, QAngle attackerAngle) private static void PushEnemy(CCSPlayerController player, QAngle attackerAngle)
{ {
if (player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid || player.PlayerPawn.Value.LifeState != (int)LifeState_t.LIFE_ALIVE) var playerPawn = player.PlayerPawn.Value;
if (playerPawn == null || !playerPawn.IsValid || playerPawn.LifeState != (int)LifeState_t.LIFE_ALIVE)
return; return;
var currentPosition = player.PlayerPawn.Value.AbsOrigin; var currentPosition = playerPawn.AbsOrigin;
var currentAngles = player.PlayerPawn.Value.EyeAngles;
Vector newVelocity = SkillUtils.GetForwardVector(attackerAngle) * SkillsInfo.GetValue<float>(skillName, "pushVelocity"); Vector newVelocity = SkillUtils.GetForwardVector(attackerAngle) * SkillsInfo.GetValue<float>(skillName, "pushVelocity");
newVelocity.Z = player.PlayerPawn.Value.AbsVelocity.Z + SkillsInfo.GetValue<float>(skillName, "jumpVelocity"); newVelocity.Z = playerPawn.AbsVelocity.Z + SkillsInfo.GetValue<float>(skillName, "jumpVelocity");
player.PlayerPawn.Value.Teleport(currentPosition, currentAngles, newVelocity); playerPawn.Teleport(currentPosition, null, newVelocity);
} }
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#1e9ab0", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float chanceFrom = .3f, float chanceTo = .4f, float jumpVelocity = 300f, float pushVelocity = 400f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#1e9ab0", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float chanceFrom = .3f, float chanceTo = .4f, float jumpVelocity = 300f, float pushVelocity = 400f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)

View file

@ -30,9 +30,14 @@ namespace src.player.skills
var weapon = weaponServices.ActiveWeapon.Value; var weapon = weaponServices.ActiveWeapon.Value;
if (weapon == null || !weapon.IsValid || pawn.CameraServices == null) continue; if (weapon == null || !weapon.IsValid || pawn.CameraServices == null) continue;
pawn.AimPunchTickBase = 0; if (pawn.AimPunchServices != null)
pawn.AimPunchTickFraction = 0f; {
pawn.AimPunchServices.PredictableBaseTick = 0;
pawn.AimPunchServices.PredictableBaseTickInterpAmount = 0;
pawn.AimPunchServices.UnpredictableBaseTick = 0;
}
pawn.CameraServices.CsViewPunchAngleTick = 0; pawn.CameraServices.CsViewPunchAngleTick = 0;
pawn.CameraServices.CsViewPunchAngleTickRatio = 0f; pawn.CameraServices.CsViewPunchAngleTickRatio = 0f;

View file

@ -1,274 +0,0 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
using CounterStrikeSharp.API.Modules.Utils;
using CS2TraceRay.Class;
using CS2TraceRay.Struct;
using src.utils;
using System.Collections.Concurrent;
using Vector = CounterStrikeSharp.API.Modules.Utils.Vector;
using static src.jRandomSkills;
namespace src.player.skills
{
public class RCMelon : ISkill
{
private const Skills skillName = Skills.RCMelon;
private static readonly ConcurrentDictionary<CCSPlayerController, PlayerSkill> playersInfo = [];
private const string melonProp = "models/cs_italy/italy_food_melon/italy_food_melon.vmdl";
private static readonly object setLock = new();
public static void LoadSkill()
{
// SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
Instance.AddToManifest(melonProp);
}
public static void NewRound()
{
foreach (var playerSkill in playersInfo.Values)
KillClone(playerSkill);
lock (setLock)
playersInfo.Clear();
}
public static void WeaponPickup(EventItemPickup @event)
{
var player = @event.Userid;
if (player == null) return;
if (playersInfo.TryGetValue(player, out var playerSkill))
if (playerSkill.CloneProp != null)
BlockWeapon(player, true);
}
public static void WeaponEquip(EventItemEquip @event)
{
var player = @event.Userid;
if (player == null) return;
if (playersInfo.TryGetValue(player, out var playerSkill))
if (playerSkill.CloneProp != null)
BlockWeapon(player, true);
}
public static void UseSkill(CCSPlayerController player)
{
var playerPawn = player.PlayerPawn.Value;
if (playerPawn?.CBodyComponent == null) return;
if (playersInfo.TryGetValue(player, out var playerSkill))
if (playerSkill.CloneProp == null && playerSkill.NextUse <= Server.TickCount)
CreateMelon(playerSkill);
else if (playerSkill.CloneProp != null)
KillClone(playerSkill);
}
public static void EnableSkill(CCSPlayerController player)
{
if (player.PlayerPawn.Value == null || player.PlayerPawn.Value.CameraServices == null) return;
playersInfo.TryAdd(player, new PlayerSkill
{
Player = player,
CloneProp = null,
NextUse = 0,
UseTime = 0,
PlayerModel = player.PlayerPawn.Value!.CBodyComponent!.SceneNode!.GetSkeletonInstance().ModelState.ModelName,
});
}
public static void DisableSkill(CCSPlayerController player)
{
if (playersInfo.TryGetValue(player, out var playerSkill))
KillClone(playerSkill);
playersInfo.TryRemove(player, out _);
}
private static void KillClone(PlayerSkill playerSkill)
{
playerSkill.Player.EmitSound("SolidMetal.BulletImpact");
if (playerSkill.CloneProp != null && playerSkill.CloneProp.IsValid && playerSkill.CloneProp.AbsOrigin != null && playerSkill.CloneProp.AbsRotation != null)
{
var playerPawn = playerSkill.Player.PlayerPawn.Value;
if (playerPawn != null && playerPawn.IsValid)
{
Vector pos = new(playerSkill.CloneProp.AbsOrigin.X, playerSkill.CloneProp.AbsOrigin.Y, playerSkill.CloneProp.AbsOrigin.Z);
QAngle angle = new(playerSkill.CloneProp.AbsRotation.X, playerSkill.CloneProp.AbsRotation.Y, playerSkill.CloneProp.AbsRotation.Z);
Server.NextFrame(() =>
{
playerPawn.Teleport(pos, angle);
});
}
playerSkill.CloneProp.AcceptInput("Kill");
playerSkill.CloneProp = null;
}
BlockWeapon(playerSkill.Player, false);
playerSkill.NextUse = Server.TickCount + SkillsInfo.GetValue<float>(skillName, "Cooldown") * 64;
playerSkill.UseTime = 0;
}
public static void OnTick()
{
foreach (var playerSkill in playersInfo.Values)
UpdateHUD(playerSkill);
}
private static CDynamicProp? CreateMelon(PlayerSkill playerSkill)
{
var player = playerSkill.Player;
if (player == null) return null;
var playerPawn = player.PlayerPawn.Value;
if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null || playerPawn.AbsRotation == null) return null;
Vector pos = playerPawn.AbsOrigin + SkillUtils.GetForwardVector(playerPawn.AbsRotation) * 50;
Vector pos2 = playerPawn.AbsOrigin + SkillUtils.GetForwardVector(playerPawn.AbsRotation) * (50 + 25);
if (!CheckPosition(player, pos2) || !((PlayerFlags)playerPawn.Flags).HasFlag(PlayerFlags.FL_ONGROUND))
{
playerSkill.InfoTime = Server.TickCount;
return null;
}
var clone = Utilities.CreateEntityByName<CDynamicProp>("prop_dynamic");
if (clone == null || !clone.IsValid) return null;
clone.Collision.SolidType = SolidType_t.SOLID_VPHYSICS;
clone.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags = (uint)(clone.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags & ~(1 << 2));
clone.Entity!.Name = clone.Globalname = $"IanaClone_{Server.TickCount}_{player.SteamID}";
clone.DispatchSpawn();
Server.NextFrame(() =>
{
clone.SetModel(playerSkill.PlayerModel);
clone.Teleport(playerPawn.AbsOrigin, new QAngle(0, playerPawn.V_angle.Y, 0));
playerPawn.Teleport(pos);
BlockWeapon(playerSkill.Player, true);
playerSkill.UseTime = Server.TickCount;
playerSkill.NextUse = Server.TickCount + 64000;
playerSkill.CloneProp = clone;
Instance.AddTimer(SkillsInfo.GetValue<float>(skillName, "Duration"), () =>
{
if (playerSkill.CloneProp != null)
KillClone(playerSkill);
});
playerPawn.SetModel(melonProp);
});
return clone;
}
private unsafe static bool CheckPosition(CCSPlayerController player, Vector endPos)
{
var playerPawn = player.PlayerPawn.Value;
if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return false;
Vector eyePos = new(playerPawn.AbsOrigin.X, playerPawn.AbsOrigin.Y, playerPawn.AbsOrigin.Z + 25);
endPos.Z += 25;
ulong mask = playerPawn.Collision.CollisionAttribute.InteractsWith;
ulong contents = playerPawn.Collision.CollisionGroup;
CGameTrace trace = TraceRay.TraceShape(eyePos, endPos, mask, contents, player);
return !trace.DidHit();
}
public static void OnTakeDamage(DynamicHook h)
{
CEntityInstance param = h.GetParam<CEntityInstance>(0);
CTakeDamageInfo param2 = h.GetParam<CTakeDamageInfo>(1);
if (param == null || param.Entity == null || param2 == null)
return;
if (string.IsNullOrEmpty(param.Entity.Name)) return;
if (!param.Entity.Name.StartsWith("IanaClone_")) return;
var nameParams = param.Entity.Name.Split('_')[2];
_ = ulong.TryParse(nameParams, out ulong steamID);
if (steamID == 0) return;
var player = Utilities.GetPlayerFromSteamId(steamID);
if (player == null) return;
if (playersInfo.TryGetValue(player, out var playerSkill))
{
KillClone(playerSkill);
var playerPawn = player.PlayerPawn.Value;
if (playerPawn != null)
SkillUtils.TakeHealth(playerPawn, (int)param2.Damage);
}
}
public static void PlayerHurt(EventPlayerHurt @event)
{
var victim = @event.Userid!;
if (!Instance.IsPlayerValid(victim)) return;
if (playersInfo.TryGetValue(victim, out var playerSkill) && playerSkill.CloneProp != null)
{
KillClone(playerSkill);
SkillUtils.RestoreHealth(victim);
}
}
private static void BlockWeapon(CCSPlayerController player, bool block)
{
if (player == null || !player.IsValid) return;
var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid || pawn.WeaponServices == null) return;
foreach (var weapon in pawn.WeaponServices.MyWeapons)
if (weapon != null && weapon.IsValid && weapon.Value != null && weapon.Value.IsValid)
{
weapon.Value.NextPrimaryAttackTick = block ? int.MaxValue : Server.TickCount;
weapon.Value.NextSecondaryAttackTick = block ? int.MaxValue : Server.TickCount;
Utilities.SetStateChanged(weapon.Value, "CBasePlayerWeapon", "m_nNextPrimaryAttackTick");
Utilities.SetStateChanged(weapon.Value, "CBasePlayerWeapon", "m_nNextSecondaryAttackTick");
}
}
private static void UpdateHUD(PlayerSkill playerSkill)
{
if (playerSkill == null || playerSkill.Player == null) return;
float cooldown = 0;
float time1 = (playerSkill.NextUse - Server.TickCount) / 64;
cooldown = (int)Math.Ceiling(Math.Max(time1, 0));
float duration = 0;
float time2 = SkillsInfo.GetValue<float>(skillName, "Duration") - (Server.TickCount - playerSkill.UseTime) / 64;
duration = (int)Math.Ceiling(Math.Max(time2, 0));
var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == playerSkill?.Player?.SteamID);
if (playerInfo == null) return;
if (playerSkill.InfoTime + (64 * 2) > Server.TickCount)
playerInfo.PrintHTML = $"{playerSkill?.Player.GetTranslation("shade_nospace")}";
else if (cooldown == 0 && duration == 0)
playerInfo.PrintHTML = null;
else if (duration > 0)
playerInfo.PrintHTML = $"{playerSkill?.Player.GetTranslation("hud_info", $"<font color='#00FF00'>{duration}</font>")}";
else if (cooldown > 0)
playerInfo.PrintHTML = $"{playerSkill?.Player.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}";
}
public class PlayerSkill
{
public required CCSPlayerController Player { get; set; }
public CDynamicProp? CloneProp { get; set; }
public float NextUse { get; set; }
public float UseTime { get; set; }
public int InfoTime { get; set; }
public string PlayerModel { get; set; }
}
public class SkillConfig(Skills skill = skillName, bool active = false, string color = "#d0d930", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = true, bool needsTeammates = false, string requiredPermission = "", float cooldown = 30, float duration = 10) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)
{
public float Cooldown { get; set; } = cooldown;
public float Duration { get; set; } = duration;
}
}
}

View file

@ -1,10 +1,10 @@
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 System.Collections.Concurrent;
using System.Collections.Immutable; using System.Collections.Immutable;
using static src.jRandomSkills; using static src.jRandomSkills;
using System.Collections.Concurrent;
using src.utils;
namespace src.player.skills namespace src.player.skills
{ {
@ -113,7 +113,7 @@ namespace src.player.skills
ConcurrentBag<string> weaponList = [.. pistols.Concat(rifles).Where(w => !playerWeapons.Contains(w))]; ConcurrentBag<string> weaponList = [.. pistols.Concat(rifles).Where(w => !playerWeapons.Contains(w))];
if (weaponList.Count == 0) if (weaponList.IsEmpty)
return; return;
string weapon = weaponList.ToArray()[Instance.Random.Next(weaponList.Count)]; string weapon = weaponList.ToArray()[Instance.Random.Next(weaponList.Count)];
@ -131,8 +131,12 @@ namespace src.player.skills
} }
} }
ulong steamId = player.SteamID;
Instance.AddTimer(.1f, () => Instance.AddTimer(.1f, () =>
{ {
var player = Utilities.GetPlayerFromSteamId(steamId);
if (player == null || !player.IsValid) return;
player.GiveNamedItem(weapon); player.GiveNamedItem(weapon);
}); });
} }

View file

@ -1,17 +1,18 @@
using CounterStrikeSharp.API; using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using src.utils;
using System.Collections.Concurrent;
using System.Drawing; using System.Drawing;
using static src.jRandomSkills; using static src.jRandomSkills;
using System.Collections.Concurrent;
using src.utils;
namespace src.player.skills namespace src.player.skills
{ {
public class ReZombie : ISkill public class ReZombie : ISkill
{ {
private const Skills skillName = Skills.ReZombie; private const Skills skillName = Skills.ReZombie;
private static readonly ConcurrentDictionary<CCSPlayerController, byte> zombies = []; private static readonly ConcurrentDictionary<uint, byte> zombies = [];
private static readonly object setLock = new(); private static readonly object setLock = new();
public static void LoadSkill() public static void LoadSkill()
@ -21,14 +22,27 @@ namespace src.player.skills
public static void EnableSkill(CCSPlayerController player) public static void EnableSkill(CCSPlayerController player)
{ {
zombies.TryRemove(player, out _); zombies.TryRemove(player.Index, out _);
} }
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
{ {
if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return; if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return;
zombies.TryRemove(player, out _); zombies.TryRemove(player.Index, out _);
SetPlayerColor(player.PlayerPawn.Value, true); SetPlayerColor(player.PlayerPawn.Value, true);
ResetHealth(player);
}
public static void ResetHealth(CCSPlayerController player)
{
var pawn = player.PlayerPawn?.Value;
if (pawn == null) return;
pawn.MaxHealth = 100;
Utilities.SetStateChanged(pawn, "CBaseEntity", "m_iMaxHealth");
pawn.Health = Math.Min(pawn.Health, 100);
Utilities.SetStateChanged(pawn, "CBaseEntity", "m_iHealth");
} }
public static void WeaponEquip(EventItemEquip @event) public static void WeaponEquip(EventItemEquip @event)
@ -36,46 +50,88 @@ namespace src.player.skills
var player = @event.Userid; var player = @event.Userid;
var weapon = @event.Item; var weapon = @event.Item;
if (player == null || !player.IsValid) return; if (player == null || !player.IsValid) return;
if (!zombies.ContainsKey(player) || weapon == "c4") return; if (!zombies.ContainsKey(player.Index) || weapon == "c4") return;
player.ExecuteClientCommand("slot3"); player.ExecuteClientCommand("slot3");
} }
public static void NewRound() public static void NewRound()
{ {
foreach (var player in zombies.Keys) foreach (var playerIndex in zombies.Keys)
{
var player = Utilities.GetPlayerFromIndex((int)playerIndex);
if (player == null || !player.IsValid) continue;
DisableSkill(player); DisableSkill(player);
}
zombies.Clear(); zombies.Clear();
} }
public static void PlayerDeath(EventPlayerDeath @event) public static void PlayerDeath(EventPlayerDeath @event)
{ {
var player = @event.Userid; var player = @event.Userid;
if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid || zombies.ContainsKey(player)) return; if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid || zombies.ContainsKey(player.Index)) return;
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo?.Skill != skillName) return; if (playerInfo?.Skill != skillName) return;
var pawn = player.PlayerPawn.Value; var pawn = player.PlayerPawn.Value;
if (pawn.AbsOrigin == null) return; if (pawn.AbsOrigin == null) return;
Vector deadPosition = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z);
QAngle deadRotation = new(pawn.EyeAngles.X, pawn.EyeAngles.Y, pawn.EyeAngles.Z);
Vector deadPosition = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z);
QAngle angle = new(pawn.V_angle.X, pawn.V_angle.Y, 0);
ulong steamID = player.SteamID;
player.Respawn(); player.Respawn();
Instance.AddTimer(.2f, () => { Instance.AddTimer(.2f, () => {
lock (setLock) lock (setLock)
{ {
var player = Utilities.GetPlayerFromSteamId(steamID);
if (player == null || !player.IsValid || !player.PlayerPawn.IsValid) return;
var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid) return;
var zombieHealth = SkillsInfo.GetValue<int>(skillName, "zombieHealth"); var zombieHealth = SkillsInfo.GetValue<int>(skillName, "zombieHealth");
player.Respawn(); player.Respawn();
zombies.TryAdd(player, 0); zombies.TryAdd(player.Index, 0);
SetPlayerColor(pawn, false); SetPlayerColor(pawn, false);
SkillUtils.AddHealth(pawn, zombieHealth - 100, zombieHealth); SkillUtils.AddHealth(pawn, zombieHealth - 100, zombieHealth);
pawn.Teleport(deadPosition, deadRotation);
pawn.Teleport(deadPosition);
pawn.Look(angle);
player.ExecuteClientCommand("slot3"); player.ExecuteClientCommand("slot3");
Instance.AddTimer(1, () => player.ExecuteClientCommand("slot3"));
Instance.AddTimer(1, () => {
var player = Utilities.GetPlayerFromSteamId(steamID);
if (player == null || !player.IsValid || !player.PlayerPawn.IsValid) return;
player.ExecuteClientCommand("slot3");
});
} }
}); });
} }
public static bool OnWeaponCanAcquire(DynamicHook hook, CCSPlayerController player, CEconItemView econItem, CCSWeaponBaseVData vdata)
{
string weaponName = vdata.Name;
if (string.IsNullOrEmpty(weaponName)) return false;
if (!zombies.ContainsKey(player.Index))
return false;
if (weaponName.Contains("knife") || weaponName.Contains("bayonet"))
return false;
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo?.Skill != skillName) return false;
hook.SetReturn(AcquireResult.InvalidItem);
return true;
}
private static void SetPlayerColor(CCSPlayerPawn pawn, bool normal) private static void SetPlayerColor(CCSPlayerPawn pawn, bool normal)
{ {
var color = normal ? Color.FromArgb(255, 255, 255, 255) : Color.FromArgb(255, 255, 0, 0); var color = normal ? Color.FromArgb(255, 255, 255, 255) : Color.FromArgb(255, 255, 0, 0);
@ -83,7 +139,7 @@ namespace src.player.skills
Utilities.SetStateChanged(pawn, "CBaseModelEntity", "m_clrRender"); Utilities.SetStateChanged(pawn, "CBaseModelEntity", "m_clrRender");
} }
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#ff5C0A", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int zombieHealth = 250) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#ff5C0A", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int zombieHealth = 500) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)
{ {
public int ZombieHealth { get; set; } = zombieHealth; public int ZombieHealth { get; set; } = zombieHealth;
} }

View file

@ -5,6 +5,7 @@ using CounterStrikeSharp.API.Modules.Utils;
using static src.jRandomSkills; using static src.jRandomSkills;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using src.utils; using src.utils;
using CounterStrikeSharp.API.Modules.Memory;
namespace src.player.skills namespace src.player.skills
{ {
@ -102,13 +103,13 @@ namespace src.player.skills
private static void CreateReplica(CCSPlayerController player) private static void CreateReplica(CCSPlayerController player)
{ {
var playerPawn = player.PlayerPawn.Value; var playerPawn = player.PlayerPawn.Value;
var replica = Utilities.CreateEntityByName<CDynamicProp>("prop_dynamic_override"); if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null || playerPawn.AbsRotation == null)
if (replica == null || playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null || playerPawn.AbsRotation == null) return;
var replica = Utilities.CreateEntityByName<CDynamicProp>("prop_dynamic_override");
if (replica == null || !replica.IsValid)
return; return;
float distance = 40;
Vector pos = playerPawn.AbsOrigin + SkillUtils.GetForwardVector(playerPawn.AbsRotation) * distance;
replica.Flags = playerPawn.Flags; replica.Flags = playerPawn.Flags;
replica.Flags |= (uint)Flags_t.FL_DUCKING; replica.Flags |= (uint)Flags_t.FL_DUCKING;
replica.Collision.SolidType = SolidType_t.SOLID_VPHYSICS; replica.Collision.SolidType = SolidType_t.SOLID_VPHYSICS;
@ -116,12 +117,13 @@ namespace src.player.skills
replica.SetModel(playerPawn!.CBodyComponent!.SceneNode!.GetSkeletonInstance().ModelState.ModelName); replica.SetModel(playerPawn!.CBodyComponent!.SceneNode!.GetSkeletonInstance().ModelState.ModelName);
replica.Entity!.Name = replica.Globalname = $"Replica_{Server.TickCount}_{(player.Team == CsTeam.CounterTerrorist ? "CT" : "TT")}"; replica.Entity!.Name = replica.Globalname = $"Replica_{Server.TickCount}_{(player.Team == CsTeam.CounterTerrorist ? "CT" : "TT")}";
replica.UseAnimGraph = false; replica.UseAnimGraph = true;
string animName = "idle_for_turns_stand_pistol"; replica.AnimGraphUpdateEnabled = true;
if (((PlayerFlags)playerPawn.Flags).HasFlag(PlayerFlags.FL_DUCKING)) bool isDucking = ((PlayerFlags)playerPawn.Flags).HasFlag(PlayerFlags.FL_DUCKING);
animName = "idle_for_turns_crouch_pistol";
float distance = 40;
Vector pos = playerPawn.AbsOrigin + SkillUtils.GetForwardVector(playerPawn.AbsRotation) * distance;
replica.AcceptInput("SetAnimation", value: animName);
replica.Teleport(pos, playerPawn.AbsRotation, null); replica.Teleport(pos, playerPawn.AbsRotation, null);
replica.DispatchSpawn(); replica.DispatchSpawn();
} }

View file

@ -10,7 +10,7 @@ namespace src.player.skills
public class Rubber: ISkill public class Rubber: ISkill
{ {
private const Skills skillName = Skills.Rubber; private const Skills skillName = Skills.Rubber;
private static readonly ConcurrentDictionary<CCSPlayerPawn, float> playersToSlow = []; private static readonly ConcurrentDictionary<uint, float> playersToSlow = [];
public static void LoadSkill() public static void LoadSkill()
{ {
@ -35,25 +35,33 @@ namespace src.player.skills
var rubberTime = SkillsInfo.GetValue<float>(skillName, "slownessTime"); var rubberTime = SkillsInfo.GetValue<float>(skillName, "slownessTime");
if (attackerInfo?.Skill == skillName) if (attackerInfo?.Skill == skillName)
playersToSlow.AddOrUpdate(victimPawn, Server.TickCount + (64 * rubberTime), (k, v) => Server.TickCount + (64 * rubberTime)); playersToSlow.AddOrUpdate(victim.Index, Server.TickCount + (64 * rubberTime), (k, v) => Server.TickCount + (64 * rubberTime));
} }
public static void OnTick() public static void OnTick()
{ {
foreach(var item in playersToSlow) foreach(var item in playersToSlow)
{ {
var pawn = item.Key; var playerIndex = item.Key;
var time = item.Value; var time = item.Value;
var player = Utilities.GetPlayerFromIndex((int)playerIndex);
if (player == null || !player.IsValid) continue;
if (time >= Server.TickCount) if (time >= Server.TickCount)
ChangeVelocity(pawn); ChangeVelocity(player);
else else
playersToSlow.TryRemove(item.Key, out _); playersToSlow.TryRemove(item.Key, out _);
} }
} }
private static void ChangeVelocity(CCSPlayerPawn pawn) private static void ChangeVelocity(CCSPlayerController player)
{ {
if (player.PlayerPawn == null) return;
var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid) return; if (pawn == null || !pawn.IsValid) return;
pawn.VelocityModifier = SkillsInfo.GetValue<float>(skillName, "slownessModifier"); pawn.VelocityModifier = SkillsInfo.GetValue<float>(skillName, "slownessModifier");
} }

View file

@ -25,7 +25,10 @@ namespace src.player.skills
{ {
var plantedBomb = Utilities.FindAllEntitiesByDesignerName<CPlantedC4>("planted_c4").FirstOrDefault(); var plantedBomb = Utilities.FindAllEntitiesByDesignerName<CPlantedC4>("planted_c4").FirstOrDefault();
if (plantedBomb != null) if (plantedBomb != null)
Server.NextFrame(() => plantedBomb.DefuseCountDown = 0); Server.NextFrame(() => {
if (plantedBomb != null && plantedBomb.IsValid)
plantedBomb.DefuseCountDown = 0;
});
} }
} }
} }

View file

@ -43,7 +43,7 @@ namespace src.player.skills
var spawnpoint = SkillUtils.GetSpawnPointVector(victim); var spawnpoint = SkillUtils.GetSpawnPointVector(victim);
if (spawnpoint == null) return; if (spawnpoint == null) return;
victimPawn.Teleport(spawnpoint, victimPawn.AbsRotation, null); victimPawn.Teleport(spawnpoint, null, null);
} }
} }

View file

@ -1,8 +1,6 @@
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 CS2TraceRay.Class;
using CS2TraceRay.Struct;
using static src.jRandomSkills; using static src.jRandomSkills;
using Vector = CounterStrikeSharp.API.Modules.Utils.Vector; using Vector = CounterStrikeSharp.API.Modules.Utils.Vector;
using System.Collections.Concurrent; using System.Collections.Concurrent;
@ -13,7 +11,7 @@ namespace src.player.skills
public class Shade : ISkill public class Shade : ISkill
{ {
private const Skills skillName = Skills.Shade; private const Skills skillName = Skills.Shade;
private static readonly ConcurrentDictionary<CCSPlayerController, float> noSpace = []; private static readonly ConcurrentDictionary<uint, float> noSpace = [];
public static void LoadSkill() public static void LoadSkill()
{ {
@ -44,25 +42,32 @@ namespace src.player.skills
{ {
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo == null) return; if (playerInfo == null) return;
float newChance = (float)Instance.Random.NextDouble() * (SkillsInfo.GetValue<float>(skillName, "ChanceTo") - SkillsInfo.GetValue<float>(skillName, "ChanceFrom")) + SkillsInfo.GetValue<float>(skillName, "ChanceFrom"); float newChance = (float)Instance.Random.NextDouble() * (SkillsInfo.GetValue<float>(skillName, "ChanceTo") - SkillsInfo.GetValue<float>(skillName, "ChanceFrom")) + SkillsInfo.GetValue<float>(skillName, "ChanceFrom");
playerInfo.SkillChance = newChance; playerInfo.SkillChance = newChance;
SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, newChance)}", SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, newChance)}",
border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t");
} }
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
{ {
noSpace.TryRemove(player, out _); noSpace.TryRemove(player.Index, out _);
SkillUtils.ResetPrintHTML(player); SkillUtils.ResetPrintHTML(player);
} }
public static void OnTick() public static void OnTick()
{ {
foreach (var item in noSpace) foreach (var (playerIndex, time) in noSpace)
if (item.Value >= Server.TickCount) {
UpdateHUD(item.Key); var player = Utilities.GetPlayerFromIndex((int)playerIndex);
if (player == null || !player.IsValid) continue;
if (time >= Server.TickCount)
UpdateHUD(player);
else else
SkillUtils.ResetPrintHTML(item.Key); SkillUtils.ResetPrintHTML(player);
}
} }
private static void UpdateHUD(CCSPlayerController player) private static void UpdateHUD(CCSPlayerController player)
@ -72,45 +77,29 @@ namespace src.player.skills
playerInfo.PrintHTML = $"<font color='#FF0000'>{player.GetTranslation("shade_nospace")}</font>"; playerInfo.PrintHTML = $"<font color='#FF0000'>{player.GetTranslation("shade_nospace")}</font>";
} }
private unsafe static bool CheckTeleport(CCSPlayerController player, Vector startPos, Vector endPos) private unsafe static bool CheckTeleport(CCSPlayerController attacker, CCSPlayerController victim, Vector startPos, Vector endPos, QAngle angle)
{ {
var pawn = player.PlayerPawn.Value; var attackerPawn = attacker.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid) return false; if (attackerPawn == null || !attackerPawn.IsValid) return false;
Vector s = startPos + new Vector(0, 0, pawn.ViewOffset.Z / 2); var victimPawn = attacker.PlayerPawn.Value;
Vector e = endPos + new Vector(0, 0, pawn.ViewOffset.Z / 2); if (victimPawn == null || !victimPawn.IsValid) return false;
ulong mask = pawn.Collision.CollisionAttribute.InteractsWith; var result = RayTrace.TraceHullShape(
ulong contents = pawn.Collision.CollisionGroup; startPos,
CGameTrace trace = TraceRay.TraceShape(startPos, endPos, mask, contents, player); endPos,
victim,
attackerPawn.Collision.Mins,
attackerPawn.Collision.Maxs,
null,
null,
angle
);
if (trace.DidHit()) return false; if (!result.HasValue)
return IsPositionSafe(player, endPos); return false;
}
private static bool IsPositionSafe(CCSPlayerController player, Vector pos) return !result.Value.DidHit;
{
var playerPawn = player.PlayerPawn.Value;
if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return false;
float footHeight = 0;
float headHeight = 70;
float innerDist = 12;
ulong mask = playerPawn.Collision.CollisionAttribute.InteractsWith;
ulong contents = playerPawn.Collision.CollisionGroup;
Vector s1 = new(pos.X - innerDist, pos.Y - innerDist, pos.Z + footHeight);
Vector e1 = new(pos.X + innerDist, pos.Y + innerDist, pos.Z + headHeight);
CGameTrace t1 = TraceRay.TraceShape(s1, e1, mask, contents, player);
if (t1.DidHit() || t1.AllSolid) return false;
Vector s2 = new(pos.X + innerDist, pos.Y - innerDist, pos.Z + footHeight);
Vector e2 = new(pos.X - innerDist, pos.Y + innerDist, pos.Z + headHeight);
CGameTrace t2 = TraceRay.TraceShape(s2, e2, mask, contents, player);
if (t2.DidHit() || t2.AllSolid) return false;
return true;
} }
private static void TeleportAttackerBehindVictim(CCSPlayerController attacker, CCSPlayerController victim) private static void TeleportAttackerBehindVictim(CCSPlayerController attacker, CCSPlayerController victim)
@ -133,7 +122,7 @@ namespace src.player.skills
Vector direction = SkillUtils.GetForwardVector(targetAngle); Vector direction = SkillUtils.GetForwardVector(targetAngle);
Vector targetPos = victimPos - (direction * distance); Vector targetPos = victimPos - (direction * distance);
if (CheckTeleport(victim, victimPos, targetPos)) if (CheckTeleport(attacker, victim, victimPos, targetPos, targetAngle))
{ {
attackerPawn.Teleport(targetPos, targetAngle, Vector.Zero); attackerPawn.Teleport(targetPos, targetAngle, Vector.Zero);
teleported = true; teleported = true;
@ -142,7 +131,7 @@ namespace src.player.skills
} }
if (!teleported) if (!teleported)
noSpace.AddOrUpdate(attacker, Server.TickCount + (64 * 2), (_, _) => Server.TickCount + (64 * 2)); noSpace.AddOrUpdate(attacker.Index, Server.TickCount + (64 * 2), (_, _) => Server.TickCount + (64 * 2));
} }
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#4d4d4d", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float teleportDistance = 100f, float chanceFrom = .3f, float chanceTo = .45f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#4d4d4d", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float teleportDistance = 100f, float chanceFrom = .3f, float chanceTo = .45f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)

View file

@ -25,7 +25,10 @@ namespace src.player.skills
var plantedBomb = Utilities.FindAllEntitiesByDesignerName<CPlantedC4>("planted_c4").FirstOrDefault(); var plantedBomb = Utilities.FindAllEntitiesByDesignerName<CPlantedC4>("planted_c4").FirstOrDefault();
if (plantedBomb != null) if (plantedBomb != null)
Server.NextFrame(() => plantedBomb.C4Blow = Server.CurrentTime + SkillsInfo.GetValue<int>(skillName, "detonationTime")); Server.NextFrame(() => {
if (plantedBomb != null && plantedBomb.IsValid)
plantedBomb.C4Blow = Server.CurrentTime + SkillsInfo.GetValue<int>(skillName, "detonationTime");
});
foreach (var p in Utilities.GetPlayers().Where(p => p.IsValid)) foreach (var p in Utilities.GetPlayers().Where(p => p.IsValid))
p.PrintToCenterAlert(p.GetTranslation("bombplanted", SkillsInfo.GetValue<int>(skillName, "detonationTime"))); p.PrintToCenterAlert(p.GetTranslation("bombplanted", SkillsInfo.GetValue<int>(skillName, "detonationTime")));

View file

@ -1,5 +1,6 @@
using CounterStrikeSharp.API; using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Entities;
using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Entities.Constants;
using CounterStrikeSharp.API.Modules.Timers; using CounterStrikeSharp.API.Modules.Timers;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
@ -50,12 +51,16 @@ namespace src.player.skills
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo?.Skill != skillName) return; if (playerInfo?.Skill != skillName) return;
ulong steamID = player.SteamID;
Vector pos = new(@event.X, @event.Y, @event.Z); Vector pos = new(@event.X, @event.Y, @event.Z);
float refillInterval = 15.5f; float refillInterval = 15.5f;
Timer? smokeTimer = null; Timer? smokeTimer = null;
smokeTimer = Instance.AddTimer(refillInterval, () => smokeTimer = Instance.AddTimer(refillInterval, () =>
{ {
var player = Utilities.GetPlayerFromSteamId(steamID);
if (player == null || !player.IsValid) if (player == null || !player.IsValid)
{ {
smokeTimer?.Kill(); smokeTimer?.Kill();

View file

@ -166,7 +166,10 @@ namespace src.player.skills
} }
Instance.AddTimer(.15f, () => { Instance.AddTimer(.15f, () => {
if (player != null && player.IsValid && player.PlayerPawn.Value != null && player.PlayerPawn.Value.IsValid) var player = Utilities.GetPlayerFromSteamId(steamID);
if (player == null || !player.IsValid) return;
if (player != null && player.IsValid && player.PlayerPawn != null && player.PlayerPawn.Value != null && player.PlayerPawn.Value.IsValid)
{ {
var createdWeapon = player.PlayerPawn.Value?.ItemServices?.As<CCSPlayer_ItemServices>().GiveNamedItem<CEntityInstance>(weaponToGive.Replace("_script", "")); var createdWeapon = player.PlayerPawn.Value?.ItemServices?.As<CCSPlayer_ItemServices>().GiveNamedItem<CEntityInstance>(weaponToGive.Replace("_script", ""));

View file

@ -11,7 +11,7 @@ namespace src.player.skills
public class Spectator : ISkill public class Spectator : ISkill
{ {
private const Skills skillName = Skills.Spectator; private const Skills skillName = Skills.Spectator;
private static readonly ConcurrentDictionary<ulong, (uint, CDynamicProp, CCSPlayerPawn)> cameras = []; private static readonly ConcurrentDictionary<ulong, (uint, uint, uint)> cameras = [];
public static void LoadSkill() public static void LoadSkill()
{ {
@ -20,9 +20,13 @@ namespace src.player.skills
public static void NewRound() public static void NewRound()
{ {
foreach (var camera in cameras) foreach (var info in cameras)
if (camera.Value.Item2 != null && camera.Value.Item2.IsValid) {
camera.Value.Item2.AcceptInput("Kill"); var cam = Utilities.GetEntityFromIndex<CDynamicProp>((int)info.Value.Item2);
if (cam != null && cam.IsValid)
cam.AcceptInput("Kill");
}
cameras.Clear(); cameras.Clear();
} }
@ -54,10 +58,24 @@ namespace src.player.skills
public static void OnTick() public static void OnTick()
{ {
foreach (var player in Utilities.GetPlayers()) foreach (var player in Utilities.GetPlayers())
if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2.IsValid) if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2 != 0)
{ {
var pawn = cameraInfo.Item3;
if (pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE var enemy = Utilities.GetPlayerFromIndex((int)cameraInfo.Item3);
if (enemy == null || !enemy.IsValid || enemy.PlayerPawn == null)
{
ChangeCamera(player, true);
return;
}
var enemyPawn = player.PlayerPawn.Value;
if (enemyPawn == null || !enemyPawn.IsValid)
{
ChangeCamera(player, true);
return;
}
if (enemyPawn.LifeState != (byte)LifeState_t.LIFE_ALIVE
|| (player.PlayerPawn.Value != null && player.PlayerPawn.Value.LifeState != (byte)LifeState_t.LIFE_ALIVE)) || (player.PlayerPawn.Value != null && player.PlayerPawn.Value.LifeState != (byte)LifeState_t.LIFE_ALIVE))
ChangeCamera(player, true); ChangeCamera(player, true);
} }
@ -70,10 +88,14 @@ namespace src.player.skills
var pawn = player.PlayerPawn.Value; var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid || pawn.CameraServices == null) return; if (pawn == null || !pawn.IsValid || pawn.CameraServices == null) return;
if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2 != null && cameraInfo.Item2.IsValid) if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2 != 0)
{ {
orginalCameraRaw = cameraInfo.Item1; orginalCameraRaw = cameraInfo.Item1;
cameraInfo.Item2.AcceptInput("Kill");
var cam = Utilities.GetEntityFromIndex<CDynamicProp>((int)cameraInfo.Item2);
if (cam != null && cam.IsValid)
cam.AcceptInput("Kill");
if (!forceToDefault) if (!forceToDefault)
newCameraRaw = CreateCamera(player); newCameraRaw = CreateCamera(player);
} else } else
@ -109,22 +131,25 @@ namespace src.player.skills
var pawn = enemy.PlayerPawn.Value; var pawn = enemy.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid || pawn.CameraServices == null || pawn.AbsOrigin == null) return 0; if (pawn == null || !pawn.IsValid || pawn.CameraServices == null || pawn.AbsOrigin == null) return 0;
var pos = pawn.AbsOrigin - SkillUtils.GetForwardVector(pawn.EyeAngles) * SkillsInfo.GetValue<float>(skillName, "distance"); QAngle angle = new(0, pawn.EyeAngles.Y, 0);
var pos = pawn.AbsOrigin - SkillUtils.GetForwardVector(angle) * SkillsInfo.GetValue<float>(skillName, "distance");
pos.Z += pawn.ViewOffset.Z; pos.Z += pawn.ViewOffset.Z;
Server.NextFrame(() => Server.NextFrame(() =>
{ {
if (camera == null || !camera.IsValid) return;
camera.SetModel("models/actors/ghost_speaker.vmdl"); camera.SetModel("models/actors/ghost_speaker.vmdl");
camera.Render = Color.FromArgb(0, 255, 255, 255); camera.Render = Color.FromArgb(0, 255, 255, 255);
camera.Teleport(pos, new QAngle(0, pawn.EyeAngles.Y, 0)); camera.Teleport(pos, angle);
camera.DispatchSpawn(); camera.DispatchSpawn();
camera.AcceptInput("SetParent", pawn, pawn, "!activator"); camera.AcceptInput("SetParent", pawn, pawn, "!activator");
}); });
if (cameras.TryGetValue(player.SteamID, out var cameraInfo)) if (cameras.TryGetValue(player.SteamID, out var cameraInfo))
cameras.AddOrUpdate(player.SteamID, (cameraInfo.Item1, camera, pawn), (k, v) => (cameraInfo.Item1, camera, pawn)); cameras.AddOrUpdate(player.SteamID, (cameraInfo.Item1, camera.Index, player.Index), (k, v) => (cameraInfo.Item1, camera.Index, player.Index));
else else
cameras.AddOrUpdate(player.SteamID, (pawn.CameraServices.ViewEntity.Raw, camera, pawn), (k, v) => (pawn.CameraServices.ViewEntity.Raw, camera, pawn)); cameras.AddOrUpdate(player.SteamID, (pawn.CameraServices.ViewEntity.Raw, camera.Index, player.Index), (k, v) => (pawn.CameraServices.ViewEntity.Raw, camera.Index, player.Index));
return camera.EntityHandle.Raw; return camera.EntityHandle.Raw;
} }

View file

@ -123,15 +123,18 @@ namespace src.player.skills
if (attackerPawn.AbsOrigin == null || attackerPawn.AbsRotation == null || victimPawn.AbsOrigin == null || victimPawn.AbsRotation == null) return; if (attackerPawn.AbsOrigin == null || attackerPawn.AbsRotation == null || victimPawn.AbsOrigin == null || victimPawn.AbsRotation == null) return;
Vector attackerPosition = new(attackerPawn.AbsOrigin.X, attackerPawn.AbsOrigin.Y, attackerPawn.AbsOrigin.Z); Vector attackerPosition = new(attackerPawn.AbsOrigin.X, attackerPawn.AbsOrigin.Y, attackerPawn.AbsOrigin.Z);
QAngle attackerAngles = new(attackerPawn.AbsRotation.X, attackerPawn.AbsRotation.Y, attackerPawn.AbsRotation.Z); QAngle attackerAngles = new(attackerPawn.V_angle.X, attackerPawn.V_angle.Y, 0);
Vector attackerVelocity = new(attackerPawn.AbsVelocity.X, attackerPawn.AbsVelocity.Y, attackerPawn.AbsVelocity.Z); Vector attackerVelocity = new(attackerPawn.AbsVelocity.X, attackerPawn.AbsVelocity.Y, attackerPawn.AbsVelocity.Z);
Vector victimPosition = new(victimPawn.AbsOrigin.X, victimPawn.AbsOrigin.Y, victimPawn.AbsOrigin.Z); Vector victimPosition = new(victimPawn.AbsOrigin.X, victimPawn.AbsOrigin.Y, victimPawn.AbsOrigin.Z);
QAngle victimAngles = new(victimPawn.AbsRotation.X, victimPawn.AbsRotation.Y, victimPawn.AbsRotation.Z); QAngle victimAngles = new(victimPawn.V_angle.X, victimPawn.V_angle.Y, 0);
Vector victimVelocity = new(victimPawn.AbsVelocity.X, victimPawn.AbsVelocity.Y, victimPawn.AbsVelocity.Z); Vector victimVelocity = new(victimPawn.AbsVelocity.X, victimPawn.AbsVelocity.Y, victimPawn.AbsVelocity.Z);
victimPawn.Teleport(attackerPosition, attackerAngles, attackerVelocity); victimPawn.Teleport(attackerPosition, null, attackerVelocity);
attackerPawn.Teleport(victimPosition, victimAngles, victimVelocity); attackerPawn.Teleport(victimPosition, null, victimVelocity);
victimPawn.Look(attackerAngles);
attackerPawn.Look(victimAngles);
} }
public class ZamianaMiejsc_PlayerInfo public class ZamianaMiejsc_PlayerInfo

View file

@ -49,15 +49,18 @@ namespace src.player.skills
if (attackerPawn.AbsOrigin == null || victimPawn.AbsOrigin == null || attackerPawn.AbsRotation == null || victimPawn.AbsRotation == null) return; if (attackerPawn.AbsOrigin == null || victimPawn.AbsOrigin == null || attackerPawn.AbsRotation == null || victimPawn.AbsRotation == null) return;
Vector attackerPosition = new(attackerPawn.AbsOrigin.X, attackerPawn.AbsOrigin.Y, attackerPawn.AbsOrigin.Z); Vector attackerPosition = new(attackerPawn.AbsOrigin.X, attackerPawn.AbsOrigin.Y, attackerPawn.AbsOrigin.Z);
QAngle attackerAngles = new(attackerPawn.AbsRotation.X, attackerPawn.AbsRotation.Y, attackerPawn.AbsRotation.Z); QAngle attackerAngles = new(attackerPawn.V_angle.X, attackerPawn.V_angle.Y, 0);
Vector attackerVelocity = new(attackerPawn.AbsVelocity.X, attackerPawn.AbsVelocity.Y, attackerPawn.AbsVelocity.Z); Vector attackerVelocity = new(attackerPawn.AbsVelocity.X, attackerPawn.AbsVelocity.Y, attackerPawn.AbsVelocity.Z);
Vector victimPosition = new(victimPawn.AbsOrigin.X, victimPawn.AbsOrigin.Y, victimPawn.AbsOrigin.Z); Vector victimPosition = new(victimPawn.AbsOrigin.X, victimPawn.AbsOrigin.Y, victimPawn.AbsOrigin.Z);
QAngle victimAngles = new(victimPawn.AbsRotation.X, victimPawn.AbsRotation.Y, victimPawn.AbsRotation.Z); QAngle victimAngles = new(victimPawn.V_angle.X, victimPawn.V_angle.Y, 0);
Vector victimVelocity = new(victimPawn.AbsVelocity.X, victimPawn.AbsVelocity.Y, victimPawn.AbsVelocity.Z); Vector victimVelocity = new(victimPawn.AbsVelocity.X, victimPawn.AbsVelocity.Y, victimPawn.AbsVelocity.Z);
victimPawn.Teleport(attackerPosition, attackerAngles, attackerVelocity); victimPawn.Teleport(attackerPosition, null, attackerVelocity);
attackerPawn.Teleport(victimPosition, victimAngles, victimVelocity); attackerPawn.Teleport(victimPosition, null, victimVelocity);
victimPawn.Look(attackerAngles);
attackerPawn.Look(victimAngles);
} }
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#8A2BE2", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float chanceFrom = .5f, float chanceTo = .6f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#8A2BE2", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float chanceFrom = .5f, float chanceTo = .6f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)

View file

@ -120,10 +120,19 @@ namespace src.player.skills
bool ctSkill = Event.counterterroristSkills.Any(s => s.Name == enemySkill.ToString()); bool ctSkill = Event.counterterroristSkills.Any(s => s.Name == enemySkill.ToString());
bool ttSkill = Event.terroristSkills.Any(s => s.Name == enemySkill.ToString()); bool ttSkill = Event.terroristSkills.Any(s => s.Name == enemySkill.ToString());
ulong enemySteamId = enemy.SteamID;
ulong playerSteamId = player.SteamID;
if ((player.Team == CsTeam.Terrorist && ctSkill) || (player.Team == CsTeam.CounterTerrorist && ttSkill)) if ((player.Team == CsTeam.Terrorist && ctSkill) || (player.Team == CsTeam.CounterTerrorist && ttSkill))
{ {
Instance.AddTimer(.1f, () => Instance.AddTimer(.1f, () =>
{ {
var enemy = Utilities.GetPlayerFromSteamId(enemySteamId);
if (enemy == null || !enemy.IsValid) return;
var player = Utilities.GetPlayerFromSteamId(playerSteamId);
if (player == null || !player.IsValid) return;
Instance.SkillAction(skillName.ToString(), "EnableSkill", [player]); Instance.SkillAction(skillName.ToString(), "EnableSkill", [player]);
player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("thief_incorrect_skill", enemy.PlayerName)); player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("thief_incorrect_skill", enemy.PlayerName));
}); });
@ -133,24 +142,42 @@ namespace src.player.skills
SkillUtils.CloseMenu(player); SkillUtils.CloseMenu(player);
Instance.AddTimer(.1f, () => Instance.AddTimer(.1f, () =>
{ {
var enemy = Utilities.GetPlayerFromSteamId(enemySteamId);
if (enemy == null || !enemy.IsValid) return;
var player = Utilities.GetPlayerFromSteamId(playerSteamId);
if (player == null || !player.IsValid) return;
playerInfo.Skill = enemySkill; playerInfo.Skill = enemySkill;
playerInfo.SpecialSkill = skillName; playerInfo.SpecialSkill = skillName;
SkillUtils.CloseMenu(player); SkillUtils.CloseMenu(player);
Instance.SkillAction(enemySkill.ToString(), "EnableSkill", [player]); Instance.SkillAction(enemySkill.ToString(), "EnableSkill", [player]);
player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("thief_player_info", enemy.PlayerName)); player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("thief_player_info", enemy.PlayerName));
if (SkillsInfo.GetValue<bool>(enemySkill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime()) if (SkillsInfo.GetValue<bool>(enemySkill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime())
Instance?.AddTimer(Math.Max((float)(Event.GetFreezeTimeEnd() - DateTime.Now).TotalSeconds, 0), () => { Instance?.AddTimer(Math.Max((float)(Event.GetFreezeTimeEnd() - DateTime.Now).TotalSeconds, 0), () => {
var player = Utilities.GetPlayerFromSteamId(playerSteamId);
if (player == null || !player.IsValid) return;
if (Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID && p.Skill == enemySkill) == null) return; if (Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID && p.Skill == enemySkill) == null) return;
Instance?.SkillAction(enemySkill.ToString(), "EnableSkill", new[] { player }); Instance?.SkillAction(enemySkill.ToString(), "EnableSkill", [player]);
}); });
else else
Instance?.SkillAction(enemySkill.ToString(), "EnableSkill", new[] { player }); Instance?.SkillAction(enemySkill.ToString(), "EnableSkill", [player]);
}); });
Instance.AddTimer(.1f, () => Instance.AddTimer(.1f, () =>
{ {
var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemySteamId);
if (enemyInfo == null) return;
var enemy = Utilities.GetPlayerFromSteamId(enemySteamId);
if (enemy == null || !enemy.IsValid) return;
Instance.SkillAction(enemySkill.ToString(), "DisableSkill", [enemy]); Instance.SkillAction(enemySkill.ToString(), "DisableSkill", [enemy]);
enemyInfo.SpecialSkill = enemySkill; enemyInfo.SpecialSkill = enemySkill;
enemyInfo.Skill = Skills.None; enemyInfo.Skill = Skills.None;
enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("thief_enemy_info")); enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("thief_enemy_info"));

View file

@ -10,7 +10,7 @@ namespace src.player.skills
public class ThirdEye : ISkill public class ThirdEye : ISkill
{ {
private const Skills skillName = Skills.ThirdEye; private const Skills skillName = Skills.ThirdEye;
private static readonly ConcurrentDictionary<ulong, (uint, CDynamicProp)> cameras = []; private static readonly ConcurrentDictionary<ulong, (uint, uint)> cameras = [];
private static readonly object setLock = new(); private static readonly object setLock = new();
public static void LoadSkill() public static void LoadSkill()
@ -20,9 +20,13 @@ namespace src.player.skills
public static void NewRound() public static void NewRound()
{ {
foreach (var camera in cameras) foreach (var cameraIndex in cameras.Values)
if (camera.Value.Item2 != null && camera.Value.Item2.IsValid) {
camera.Value.Item2.AcceptInput("Kill"); var camera = Utilities.GetEntityFromIndex<CDynamicProp>((int)cameraIndex.Item2);
if (camera != null && camera.IsValid)
camera.AcceptInput("Kill");
}
lock (setLock) lock (setLock)
cameras.Clear(); cameras.Clear();
} }
@ -42,7 +46,7 @@ namespace src.player.skills
public static void OnTick() public static void OnTick()
{ {
foreach (var player in Utilities.GetPlayers()) foreach (var player in Utilities.GetPlayers())
if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2.IsValid) if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2 != 0)
{ {
var pawn = player.PlayerPawn.Value; var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) continue; if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) continue;
@ -55,7 +59,7 @@ namespace src.player.skills
var pos = pawn.AbsOrigin - SkillUtils.GetForwardVector(pawn.EyeAngles) * SkillsInfo.GetValue<float>(skillName, "distance"); var pos = pawn.AbsOrigin - SkillUtils.GetForwardVector(pawn.EyeAngles) * SkillsInfo.GetValue<float>(skillName, "distance");
pos.Z += pawn.ViewOffset.Z; pos.Z += pawn.ViewOffset.Z;
var cam = cameraInfo.Item2; var cam = Utilities.GetEntityFromIndex<CDynamicProp>((int)cameraInfo.Item2);
if (cam == null || cam.AbsOrigin == null || cam.AbsRotation == null) continue; if (cam == null || cam.AbsOrigin == null || cam.AbsRotation == null) continue;
cam.Teleport(pos, pawn.V_angle); cam.Teleport(pos, pawn.V_angle);
} }
@ -66,10 +70,14 @@ namespace src.player.skills
uint orginalCameraRaw; uint orginalCameraRaw;
uint newCameraRaw; uint newCameraRaw;
var pawn = player.PlayerPawn.Value; var pawn = player.PlayerPawn.Value;
if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2.IsValid) if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2 != 0)
{ {
orginalCameraRaw = cameraInfo.Item1; orginalCameraRaw = cameraInfo.Item1;
newCameraRaw = cameraInfo.Item2.EntityHandle.Raw;
var cam = Utilities.GetEntityFromIndex<CDynamicProp>((int)cameraInfo.Item2);
if (cam == null || !cam.IsValid) return;
newCameraRaw = cam.EntityHandle.Raw;
} }
else else
{ {
@ -100,13 +108,14 @@ namespace src.player.skills
Server.NextFrame(() => Server.NextFrame(() =>
{ {
if (camera == null || !camera.IsValid) return;
camera.SetModel("models/actors/ghost_speaker.vmdl"); camera.SetModel("models/actors/ghost_speaker.vmdl");
camera.Render = Color.FromArgb(0, 255, 255, 255); camera.Render = Color.FromArgb(0, 255, 255, 255);
camera.Teleport(pawn!.AbsOrigin, pawn.EyeAngles); camera.Teleport(pawn!.AbsOrigin, pawn.EyeAngles);
camera.DispatchSpawn(); camera.DispatchSpawn();
}); });
cameras.AddOrUpdate(player.SteamID, (pawn.CameraServices!.ViewEntity.Raw, camera), (v, k) => (pawn.CameraServices!.ViewEntity.Raw, camera)); cameras.AddOrUpdate(player.SteamID, (pawn.CameraServices!.ViewEntity.Raw, camera.Index), (v, k) => (pawn.CameraServices!.ViewEntity.Raw, camera.Index));
return camera.EntityHandle.Raw; return camera.EntityHandle.Raw;
} }

View file

@ -129,7 +129,7 @@ namespace src.player.skills
if (trigger != null && trigger.IsValid) if (trigger != null && trigger.IsValid)
Server.NextFrame(() => Server.NextFrame(() =>
{ {
if (trigger.IsValid) if (trigger != null && trigger.IsValid)
trigger.AcceptInput("Kill"); trigger.AcceptInput("Kill");
}); });
} }
@ -140,7 +140,7 @@ namespace src.player.skills
if (glow != null && glow.IsValid) if (glow != null && glow.IsValid)
Server.NextFrame(() => Server.NextFrame(() =>
{ {
if (glow.IsValid) if (glow != null && glow.IsValid)
glow.AcceptInput("Kill"); glow.AcceptInput("Kill");
}); });
} }
@ -151,7 +151,7 @@ namespace src.player.skills
if (relay != null && relay.IsValid) if (relay != null && relay.IsValid)
Server.NextFrame(() => Server.NextFrame(() =>
{ {
if (relay.IsValid) if (relay != null && relay.IsValid)
relay.AcceptInput("Kill"); relay.AcceptInput("Kill");
}); });
} }
@ -178,7 +178,11 @@ namespace src.player.skills
if (weapon == null || !weapon.IsValid || (!weapon.DesignerName.Contains("knife") && !weapon.DesignerName.Contains("bayonet"))) return; if (weapon == null || !weapon.IsValid || (!weapon.DesignerName.Contains("knife") && !weapon.DesignerName.Contains("bayonet"))) return;
player.DropActiveWeapon(); player.DropActiveWeapon();
Server.NextFrame(() => ThrowKnife(player, weapon) ); Server.NextFrame(() => {
if (player == null || !player.IsValid) return;
if (weapon == null || !weapon.IsValid) return;
ThrowKnife(player, weapon);
});
}); });
} }

View file

@ -65,6 +65,7 @@ namespace src.player.skills
Server.NextFrame(() => Server.NextFrame(() =>
{ {
if (entity == null || !entity.IsValid) return;
var smoke = entity.As<CSmokeGrenadeProjectile>(); var smoke = entity.As<CSmokeGrenadeProjectile>();
smoke.SmokeColor.X = 255; smoke.SmokeColor.X = 255;
smoke.SmokeColor.Y = 0; smoke.SmokeColor.Y = 0;

View file

@ -133,6 +133,8 @@ namespace src.player.skills
Server.NextFrame(() => Server.NextFrame(() =>
{ {
if (player == null || !player.IsValid) return;
if (enemy == null || !enemy.IsValid) return;
player.RemoveWeapons(); player.RemoveWeapons();
enemy.RemoveWeapons(); enemy.RemoveWeapons();
GiveWeapons(player, enemyWeapon, playerWeapon.Contains("weapon_c4")); GiveWeapons(player, enemyWeapon, playerWeapon.Contains("weapon_c4"));

View file

@ -88,7 +88,7 @@ namespace src.utils
public bool DisplayAlwaysDescription { get; set; } public bool DisplayAlwaysDescription { get; set; }
public bool DisableSpectateHUD { get; set; } public bool DisableSpectateHUD { get; set; }
public bool FlashingHtmlHudFix { get; set; } public bool FlashingHtmlHudFix { get; set; }
public bool CS2TraceRayDebug { get; set; } public bool TraceRayBeam { get; set; }
public string DisableHUDOnDeathPermission { get; set; } public string DisableHUDOnDeathPermission { get; set; }
public bool DisableSkillsOnRoundEnd { get; set; } public bool DisableSkillsOnRoundEnd { get; set; }
public LanguageSystem LanguageSystem { get; set; } public LanguageSystem LanguageSystem { get; set; }
@ -112,7 +112,7 @@ namespace src.utils
SkillDescriptionDuration = 7; SkillDescriptionDuration = 7;
DisplayAlwaysDescription = false; DisplayAlwaysDescription = false;
FlashingHtmlHudFix = true; FlashingHtmlHudFix = true;
CS2TraceRayDebug = false; TraceRayBeam = false;
DisableSpectateHUD = false; DisableSpectateHUD = false;
DisableHUDOnDeathPermission = "@jRandomSkills/death"; DisableHUDOnDeathPermission = "@jRandomSkills/death";
DisableSkillsOnRoundEnd = false; DisableSkillsOnRoundEnd = false;
@ -180,6 +180,7 @@ namespace src.utils
SetStaticSkillCommand = new NormalCommand("ustawstatycznyskill, ustaw_statyczny_skill, setstaticskill, set_static_skill", "@jRandomSkills/admin"), SetStaticSkillCommand = new NormalCommand("ustawstatycznyskill, ustaw_statyczny_skill, setstaticskill, set_static_skill", "@jRandomSkills/admin"),
ChangeLanguageCommand = new NormalCommand("lang, language, changelang, change_lang, jezyk, język", ""), ChangeLanguageCommand = new NormalCommand("lang, language, changelang, change_lang, jezyk, język", ""),
ReloadCommand = new NormalCommand("reload, refresh", "@jRandomSkills/admin"), ReloadCommand = new NormalCommand("reload, refresh", "@jRandomSkills/admin"),
NextCommand = new NormalCommand("next_skill", "@jRandomSkills/admin"),
}; };
VotingCommands = new VotingCommands VotingCommands = new VotingCommands
@ -259,6 +260,7 @@ namespace src.utils
public required NormalCommand SetStaticSkillCommand { get; set; } public required NormalCommand SetStaticSkillCommand { get; set; }
public required NormalCommand ChangeLanguageCommand { get; set; } public required NormalCommand ChangeLanguageCommand { get; set; }
public required NormalCommand ReloadCommand { get; set; } public required NormalCommand ReloadCommand { get; set; }
public required NormalCommand NextCommand { get; set; }
} }
public class VotingCommand(bool enableVoting, string alias, string permissions, float timeToVote, float percentagesToSuccess, float timeToNextVoting, float timeToNextSameVoting, int minimumPlayersToStartVoting) : NormalCommand(alias, permissions) public class VotingCommand(bool enableVoting, string alias, string permissions, float timeToVote, float percentagesToSuccess, float timeToNextVoting, float timeToNextSameVoting, int minimumPlayersToStartVoting) : NormalCommand(alias, permissions)

View file

@ -0,0 +1,36 @@
using RayTraceAPI;
using System.Numerics;
using Vector = CounterStrikeSharp.API.Modules.Utils.Vector;
namespace jRandomSkills.src.utils
{
public struct CustomTraceResult (TraceResult result, Vector startPos, ulong mask, ulong contents, bool drawBeam)
{
public float StartPosX = startPos.X;
public float StartPosY = startPos.Y;
public float StartPosZ = startPos.Z;
public float EndPosX = result.EndPosX;
public float EndPosY = result.EndPosY;
public float EndPosZ = result.EndPosZ;
public nint HitEntity = result.HitEntity;
public float Fraction = result.Fraction;
public int AllSolid = result.AllSolid;
public float NormalX = result.NormalX;
public float NormalY = result.NormalY;
public float NormalZ = result.NormalZ;
public ulong InteractsWith = mask;
public ulong InteractsExclude = contents;
public bool DrawBeam = drawBeam;
public readonly Vector3 StartPos => new(StartPosX, StartPosY, StartPosZ);
public readonly Vector3 EndPos => new(EndPosX, EndPosY, EndPosZ);
public readonly Vector3 Normal => new(NormalX, NormalY, NormalZ);
public readonly float Distance => Vector3.Distance(StartPos, EndPos);
public readonly bool DidHit => Fraction < 1f;
public readonly bool IsAllSolid => AllSolid != 0;
}
}

View file

@ -0,0 +1,299 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Core.Capabilities;
using CounterStrikeSharp.API.Modules.Utils;
using jRandomSkills.src.utils;
using RayTraceAPI;
using System.Drawing;
using System.Numerics;
using TraceOptions = RayTraceAPI.TraceOptions;
using Vector = CounterStrikeSharp.API.Modules.Utils.Vector;
namespace src.utils
{
public static class RayTrace
{
private static PluginCapability<CRayTraceInterface> RayTraceInterface { get; } = new("raytrace:craytraceinterface");
public static CustomTraceResult? TraceShape(CCSPlayerController player, Vector startPos, Vector endPos, ulong? mask = null, ulong? contents = null)
{
var playerPawn = player.PlayerPawn.Value;
if (playerPawn == null)
return null;
var rayTrace = RayTraceInterface.Get();
if (rayTrace == null)
return null;
if (mask == null)
{
mask = playerPawn.Collision.CollisionAttribute.InteractsWith | (ulong)InteractionLayers.Hitboxes;
mask &= ~(ulong)InteractionLayers.PlayerClip;
}
contents ??= playerPawn.Collision.CollisionGroup;
bool drawBeam = Config.LoadedConfig.TraceRayBeam;
TraceOptions options = new()
{
InteractsWith = (ulong)mask,
InteractsExclude = (ulong)contents,
DrawBeam = drawBeam == true ? 1 : 0,
};
rayTrace.TraceEndShape(startPos, endPos, playerPawn, options, out TraceResult result);
return new CustomTraceResult(result, startPos, (ulong)mask, (ulong)contents, drawBeam);
}
public static CustomTraceResult? EyeTrace(CCSPlayerController player)
{
var playerPawn = player.PlayerPawn.Value;
if (playerPawn == null)
return null;
var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID);
if (playerInfo == null) return null;
float maxDistance = SkillsInfo.GetValue<float>(playerInfo.Skill, "maxDistance");
if (maxDistance == 0) maxDistance = 4096f;
Vector startPos = new(playerPawn.AbsOrigin!.X, playerPawn.AbsOrigin!.Y, playerPawn.AbsOrigin!.Z + playerPawn.ViewOffset.Z);
Vector endPos = startPos + SkillUtils.GetForwardVector(playerPawn.EyeAngles) * maxDistance;
return TraceShape(player, startPos, endPos);
}
public static CustomTraceResult? TraceHullShape(Vector startPos, Vector endPos, CCSPlayerController player, Vector? mins = null, Vector? maxs = null, ulong? mask = null, ulong? contents = null, QAngle? angle = null)
{
var playerPawn = player.PlayerPawn.Value;
if (playerPawn == null)
return null;
var rayTrace = RayTraceInterface.Get();
if (rayTrace == null)
return null;
mask ??= playerPawn.Collision.CollisionAttribute.InteractsWith;
contents ??= playerPawn.Collision.CollisionGroup;
bool drawBeam = Config.LoadedConfig.TraceRayBeam;
TraceOptions options = new()
{
InteractsWith = (ulong)mask,
InteractsExclude = (ulong)contents,
DrawBeam = drawBeam == true ? 1 : 0,
};
mins ??= playerPawn.Collision.Mins;
maxs ??= playerPawn.Collision.Maxs;
rayTrace.TraceHullShape(startPos, endPos, mins, maxs, playerPawn, options, out TraceResult result);
if (drawBeam)
{
angle ??= new(0, playerPawn.EyeAngles.Y, 0);
DrawBoxEdges(startPos, endPos, angle, mins, maxs, Color.Green);
}
return new CustomTraceResult(result, startPos, (ulong)mask, (ulong)contents, drawBeam);
}
private static void DrawBoxEdges(Vector start, Vector end, QAngle angles, Vector mins, Vector maxs, Color color)
{
AngleVectors(angles, out Vector forward, out Vector right, out Vector up);
float halfLength = (maxs.X - mins.X) / 2.0f;
Vector visualStart = start - (forward * halfLength);
Vector visualEnd = end + (forward * halfLength);
Vector GetVertex(Vector center, float rx, float ux)
{
return center + (right * rx) + (up * ux);
}
Vector[] s = [
GetVertex(visualStart, mins.Y, mins.Z),
GetVertex(visualStart, maxs.Y, mins.Z),
GetVertex(visualStart, maxs.Y, maxs.Z),
GetVertex(visualStart, mins.Y, maxs.Z)
];
Vector[] e = [
GetVertex(visualEnd, mins.Y, mins.Z),
GetVertex(visualEnd, maxs.Y, mins.Z),
GetVertex(visualEnd, maxs.Y, maxs.Z),
GetVertex(visualEnd, mins.Y, maxs.Z)
];
for (int i = 0; i < 4; i++)
{
int next = (i + 1) % 4;
CreateBeamLine(s[i], s[next], color);
CreateBeamLine(e[i], e[next], color);
CreateBeamLine(s[i], e[i], color);
}
}
private static void AngleVectors(QAngle angles, out Vector forward, out Vector right, out Vector up)
{
float sp, sy, cp, cy, sr, cr;
float pitch = angles.X * (MathF.PI / 180.0f);
float yaw = angles.Y * (MathF.PI / 180.0f);
float roll = angles.Z * (MathF.PI / 180.0f);
sp = MathF.Sin(pitch); cp = MathF.Cos(pitch);
sy = MathF.Sin(yaw); cy = MathF.Cos(yaw);
sr = MathF.Sin(roll); cr = MathF.Cos(roll);
forward = new Vector(cp * cy, cp * sy, -sp);
right = new Vector(-1 * sr * sp * cy + cr * sy, -1 * sr * sp * sy - cr * cy, -1 * sr * cp);
up = new Vector(cr * sp * cy + sr * sy, cr * sp * sy - sr * cy, cr * cp);
}
private static void CreateBeamLine(Vector start, Vector end, Color color)
{
var beam = Utilities.CreateEntityByName<CBeam>("env_beam");
if (beam == null || !beam.IsValid) return;
beam.Render = color;
beam.Width = 1.3f;
beam.Teleport(start, new QAngle(0, 0, 0), new Vector(0, 0, 0));
beam.EndPos.X = end.X;
beam.EndPos.Y = end.Y;
beam.EndPos.Z = end.Z;
beam.DispatchSpawn();
}
public static float Distance(this CustomTraceResult result)
{
return Vector3.Distance(result.StartPos, result.EndPos);
}
public static Vector3 Direction(this CustomTraceResult result)
{
return Vector3.Normalize(result.EndPos - result.Normal);
}
public static bool HitEntityByDesignerName<T>(this CustomTraceResult result, out T? entity, string designerName, DesignerNameMatchType matchType = DesignerNameMatchType.Equals) where T : CEntityInstance
{
T? val = (T?)Activator.CreateInstance(typeof(T), result.HitEntity);
if ((object?)val != null && matchType switch
{
DesignerNameMatchType.Equals => val.DesignerName == designerName,
DesignerNameMatchType.StartsWith => val.DesignerName.StartsWith(designerName, StringComparison.OrdinalIgnoreCase),
DesignerNameMatchType.EndsWith => val.DesignerName.EndsWith(designerName, StringComparison.OrdinalIgnoreCase),
_ => false,
})
{
entity = val;
return true;
}
entity = null;
return false;
}
public static bool HitEntity(this CustomTraceResult result, out CBaseEntity? entity)
{
CEntityInstance entityInstance = new(result.HitEntity);
if (string.IsNullOrEmpty(entityInstance.DesignerName))
{
entity = null;
return false;
}
entity = entityInstance.As<CBaseEntity>();
return entity != null;
}
public static bool HitPlayer(this CustomTraceResult result, out CCSPlayerController? player)
{
if (result.HitEntityByDesignerName<CCSPlayerPawn>(out CCSPlayerPawn? entity, "player"))
{
player = entity?.OriginalController.Value;
return player != null;
}
player = null;
return false;
}
public static bool HitWeapon(this CustomTraceResult result, out CBasePlayerWeapon? weapon)
{
return result.HitEntityByDesignerName<CBasePlayerWeapon>(out weapon, "weapon_", DesignerNameMatchType.StartsWith);
}
public static bool HitChicken(this CustomTraceResult result, out CChicken? chicken)
{
return result.HitEntityByDesignerName<CChicken>(out chicken, "chicken");
}
public static bool HitButton(this CustomTraceResult result, out CBaseButton? button)
{
return result.HitEntityByDesignerName<CBaseButton>(out button, "func_door");
}
public static bool HitBuyzone(this CustomTraceResult result, out CBuyZone? buyzone)
{
return result.HitEntityByDesignerName<CBuyZone>(out buyzone, "func_buyzone");
}
public static bool HitSky(this CustomTraceResult result, out CEnvSky? sky)
{
return result.HitEntityByDesignerName<CEnvSky>(out sky, "env_sky");
}
public static bool HitDoor(this CustomTraceResult result, out CBaseDoor? door)
{
return result.HitEntityByDesignerName<CBaseDoor>(out door, "func_door");
}
public static bool HitDoor(this CustomTraceResult result, out CRotDoor? door)
{
return result.HitEntityByDesignerName<CRotDoor>(out door, "func_door_rotating");
}
public static bool HitLadder(this CustomTraceResult result, out CFuncLadder? ladder)
{
return result.HitEntityByDesignerName<CFuncLadder>(out ladder, "func_ladder");
}
public static bool HitGrenade(this CustomTraceResult result, out CBaseCSGrenade? grenade)
{
return result.HitEntityByDesignerName<CBaseCSGrenade>(out grenade, "grenade");
}
public static bool HitPlantedC4(this CustomTraceResult result, out CPlantedC4? c4)
{
return result.HitEntityByDesignerName<CPlantedC4>(out c4, "planted_c4");
}
public static bool HitPointWorldText(this CustomTraceResult result, out CPointWorldText? pointWorldText)
{
return result.HitEntityByDesignerName<CPointWorldText>(out pointWorldText, "point_worldtext");
}
public static bool HitC4(this CustomTraceResult result, out CC4? c4)
{
return result.HitEntityByDesignerName<CC4>(out c4, "weapon_c4");
}
public static bool HitWorld(this CustomTraceResult result, out CWorld? world)
{
return result.HitEntityByDesignerName<CWorld>(out world, "worldent");
}
public enum DesignerNameMatchType
{
Equals,
StartsWith,
EndsWith
}
}
}

View file

@ -165,7 +165,11 @@ namespace src.utils
skeleton.Scale = scale; skeleton.Scale = scale;
playerPawn.AcceptInput("SetScale", null, null, scale.ToString(CultureInfo.InvariantCulture)); playerPawn.AcceptInput("SetScale", null, null, scale.ToString(CultureInfo.InvariantCulture));
Server.NextWorldUpdate(() => Utilities.SetStateChanged(player.PlayerPawn.Value!, "CBaseEntity", "m_CBodyComponent"));
Server.NextWorldUpdate(() => {
if (playerPawn == null || !playerPawn.IsValid) return;
Utilities.SetStateChanged(playerPawn, "CBaseEntity", "m_CBodyComponent");
});
} }
public static Vector? GetSpawnPointVector(CCSPlayerController player, bool enemySpawn = false) public static Vector? GetSpawnPointVector(CCSPlayerController player, bool enemySpawn = false)
@ -224,6 +228,7 @@ namespace src.utils
if (pawn.Health <= 0) if (pawn.Health <= 0)
Server.NextFrame(() => Server.NextFrame(() =>
{ {
if (pawn == null || !pawn.IsValid) return;
pawn?.CommitSuicide(false, true); pawn?.CommitSuicide(false, true);
}); });
} }

Binary file not shown.

View file

@ -16,15 +16,22 @@
"Shoot_Secondary": { "Shoot_Secondary": {
"signatures": { "signatures": {
"library": "server", "library": "server",
"windows": "48 89 5C 24 ? 57 48 83 EC 20 44 0F BF C2", "windows": "48 89 5C 24 ? 57 48 83 EC 20 48 8B 01 48 8B F9 0F BF DA",
"linux": "55 48 89 E5 41 54 53 48 89 FB 66 83 FE 65" "linux": "55 48 8D 15 ? ? ? ? 48 89 E5 41 54 41 89 F4 53 48 8B 07 48 89 FB 48 8B 80 ? ? ? ? 48 39 D0 0F 85"
} }
}, },
"SnapViewAngles": { "SnapViewAngles": {
"signatures": { "signatures": {
"library": "server", "library": "server",
"windows": "48 89 5C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 55 48 8D 6C 24 ? 48 81 EC ? ? ? ? 48 8B DA 48 8B F1 48 8D 55", "windows": "48 89 5C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 55 48 8D 6C 24 ? 48 81 EC ? ? ? ? 48 8B DA 48 8B F1 48 8D 55",
"linux": "55 48 89 E5 41 57 41 56 41 55 41 54 53 48 89 FB 48 89 F7 48 81 EC ? ? ? ? E8 ? ? ? ? 48 8B 93" "linux": "55 48 89 E5 41 57 49 89 FF 48 89 F7 41 56 41 55 41 54 53 48 81 EC"
}
},
"CCSPlayerController_HandleCommandDrop": {
"signatures": {
"library": "server",
"windows": "48 89 5C 24 ? 57 48 83 EC ? 48 8B FA E8 ? ? ? ? 48 8B D8",
"linux": "55 48 89 E5 41 54 49 89 F4 53 E8 ? ? ? ? 48 85 C0 74 ? 48 89 C3"
} }
} }
} }

View file

@ -13,7 +13,7 @@
"DisplayAlwaysDescription": false, "DisplayAlwaysDescription": false,
"DisableSpectateHUD": false, "DisableSpectateHUD": false,
"FlashingHtmlHudFix": true, "FlashingHtmlHudFix": true,
"CS2TraceRayDebug": false, "TraceRayBeam": false,
"DisableHUDOnDeathPermission": "@jRandomSkills/death", "DisableHUDOnDeathPermission": "@jRandomSkills/death",
"DisableSkillsOnRoundEnd": false, "DisableSkillsOnRoundEnd": false,
"LanguageSystem": { "LanguageSystem": {
@ -130,6 +130,10 @@
"ReloadCommand": { "ReloadCommand": {
"Alias": "reload, refresh", "Alias": "reload, refresh",
"Permissions": "@jRandomSkills/admin" "Permissions": "@jRandomSkills/admin"
},
"NextCommand": {
"Alias": "next_skill",
"Permissions": "@jRandomSkills/admin"
} }
}, },
"VotingCommands": { "VotingCommands": {

View file

@ -262,7 +262,7 @@
"RequiredPermission": "" "RequiredPermission": ""
}, },
{ {
"ZombieHealth": 250, "ZombieHealth": 500,
"NeedsTeammates": false, "NeedsTeammates": false,
"DisableOnFreezeTime": false, "DisableOnFreezeTime": false,
"OnlyTeam": 0, "OnlyTeam": 0,
@ -323,17 +323,6 @@
"Name": "ReactiveArmor", "Name": "ReactiveArmor",
"RequiredPermission": "" "RequiredPermission": ""
}, },
{
"Cooldown": 30.0,
"Duration": 10.0,
"NeedsTeammates": false,
"DisableOnFreezeTime": true,
"OnlyTeam": 0,
"Color": "#d0d930",
"Active": false,
"Name": "RCMelon",
"RequiredPermission": ""
},
{ {
"Cooldown": 15.0, "Cooldown": 15.0,
"NeedsTeammates": false, "NeedsTeammates": false,
@ -706,6 +695,7 @@
"RequiredPermission": "" "RequiredPermission": ""
}, },
{ {
"ParticleName": "particles/ui/hud/ui_map_def_utility_trail.vpcf",
"NeedsTeammates": false, "NeedsTeammates": false,
"DisableOnFreezeTime": false, "DisableOnFreezeTime": false,
"OnlyTeam": 0, "OnlyTeam": 0,
@ -747,9 +737,6 @@
"RequiredPermission": "" "RequiredPermission": ""
}, },
{ {
"MaximumFuel": 150.0,
"FuelConsumption": 0.64,
"Refuelling": 0.1,
"NeedsTeammates": false, "NeedsTeammates": false,
"DisableOnFreezeTime": true, "DisableOnFreezeTime": true,
"OnlyTeam": 0, "OnlyTeam": 0,
@ -1307,7 +1294,6 @@
{ {
"Cooldown": 20.0, "Cooldown": 20.0,
"Duration": 0.3, "Duration": 0.3,
"Offset": 0.0,
"NeedsTeammates": false, "NeedsTeammates": false,
"DisableOnFreezeTime": true, "DisableOnFreezeTime": true,
"OnlyTeam": 0, "OnlyTeam": 0,