v1.21.1.b8
This commit is contained in:
parent
abd3aed8fd
commit
10dbf6629e
77 changed files with 1507 additions and 974 deletions
|
|
@ -15,14 +15,19 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.364" />
|
||||
<PackageReference Include="CS2TraceRay" Version="1.0.9" />
|
||||
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.367" />
|
||||
<PackageReference Include="MaxMind.Db" Version="5.0.0">
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
</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>
|
||||
<ProjectReference Include="../WASDMenuAPI - SRC Files/WASDMenuAPI.csproj" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
BIN
jRandomSkills - SRC Files/libs/RayTraceApi.dll
Normal file
BIN
jRandomSkills - SRC Files/libs/RayTraceApi.dll
Normal file
Binary file not shown.
|
|
@ -17,6 +17,7 @@ namespace src.command
|
|||
private static bool gamePaused = false;
|
||||
private static Config.SettingsModel config = Config.LoadedConfig;
|
||||
private static readonly ConcurrentDictionary<string, CommandInfo.CommandCallback> oldCommands = [];
|
||||
private static readonly ConcurrentDictionary<uint, int> nextSkill = [];
|
||||
private static readonly object setLock = new();
|
||||
|
||||
public static void Load()
|
||||
|
|
@ -47,6 +48,7 @@ namespace src.command
|
|||
{ SplitCommands(config.NormalCommands.SetStaticSkillCommand.Alias), ("Set static skill", Command_SetStaticSkill) },
|
||||
{ SplitCommands(config.NormalCommands.ChangeLanguageCommand.Alias), ("Change language", Command_ChangeLanguage) },
|
||||
{ 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.StartGameCommand.Alias), ("Start game", Command_StartGame) },
|
||||
|
|
@ -142,7 +144,7 @@ namespace src.command
|
|||
{
|
||||
Instance.SkillAction(skillPlayer.Skill.ToString(), "DisableSkill", [targetPlayer]);
|
||||
skillPlayer.Skill = skill.Skill;
|
||||
skillPlayer.SpecialSkill = src.player.Skills.None;
|
||||
skillPlayer.SpecialSkill = Skills.None;
|
||||
Instance.SkillAction(skill.Skill.ToString(), "EnableSkill", [targetPlayer]);
|
||||
skillPlayer.SkillDescriptionHudExpired = DateTime.Now.AddSeconds(Config.LoadedConfig.SkillDescriptionDuration);
|
||||
|
||||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,15 +16,22 @@
|
|||
"Shoot_Secondary": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "48 89 5C 24 ? 57 48 83 EC 20 44 0F BF C2",
|
||||
"linux": "55 48 89 E5 41 54 53 48 89 FB 66 83 FE 65"
|
||||
"windows": "48 89 5C 24 ? 57 48 83 EC 20 48 8B 01 48 8B F9 0F BF DA",
|
||||
"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": {
|
||||
"signatures": {
|
||||
"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",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -28,7 +28,7 @@ namespace src
|
|||
public override string ModuleName => "[CS2] [ jRandomSkills ]";
|
||||
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 ModuleVersion => "1.2.1.b7";
|
||||
public override string ModuleVersion => "1.2.1.b8";
|
||||
|
||||
public override void Load(bool hotReload)
|
||||
{
|
||||
|
|
@ -213,8 +213,9 @@ namespace src
|
|||
{ "WASDMenuAPI", "./WASDMenuAPI.dll" },
|
||||
{ "MaxMind", "./MaxMind.Db.dll" },
|
||||
{ "GeoLite2", "./packages/GeoLite2-Country.mmdb" },
|
||||
{ "CS2TraceRay", "./../../shared/CS2TraceRay/CS2TraceRay.dll" },
|
||||
{ "CS2TraceRay gamedata", "./../../gamedata/CS2TraceRay.gamedata.json" },
|
||||
{ "RayTraceApi", "./../../shared/RayTraceApi/RayTraceApi.dll" },
|
||||
{ "RayTraceImpl", "./../../plugins/RayTraceImpl/RayTraceImpl.dll" },
|
||||
{ "RayTrace MetaMod", "./../../../metamod/RayTrace.vdf" },
|
||||
{ "jRandomSkills gamedata", "./../../gamedata/jRandomSkills.gamedata.json" }
|
||||
};
|
||||
|
||||
|
|
@ -263,7 +264,7 @@ namespace src
|
|||
|
||||
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"));
|
||||
const string URL = "https://api.github.com/repos/Juzlus/jRandomSkills/releases/latest";
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,9 @@ public interface ISkill
|
|||
public static void WeaponEquip(EventItemEquip _) { }
|
||||
public static void WeaponPickup(EventItemPickup _) { }
|
||||
public static void WeaponReload(EventWeaponReload _) { }
|
||||
public static bool WeaponDrop(DynamicHook _, CCSPlayerController __) { return false; }
|
||||
public static void GrenadeThrown(EventGrenadeThrown _) { }
|
||||
public static void BulletImpact(EventBulletImpact _) { }
|
||||
|
||||
public static void BombBeginplant(EventBombBeginplant _) { }
|
||||
public static void BombAbortplant(EventBombAbortplant _) { }
|
||||
|
|
@ -146,7 +148,6 @@ public enum Skills
|
|||
RadarHack,
|
||||
Rambo,
|
||||
RandomWeapon,
|
||||
RCMelon,
|
||||
ReZombie,
|
||||
ReactiveArmor,
|
||||
Regeneration,
|
||||
|
|
|
|||
|
|
@ -2,15 +2,14 @@ using CounterStrikeSharp.API;
|
|||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Core.Attributes;
|
||||
using CounterStrikeSharp.API.Modules.Admin;
|
||||
using CounterStrikeSharp.API.Modules.Commands;
|
||||
using CounterStrikeSharp.API.Modules.Cvars;
|
||||
using CounterStrikeSharp.API.Modules.Events;
|
||||
using CounterStrikeSharp.API.Modules.Memory;
|
||||
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
|
||||
using CounterStrikeSharp.API.Modules.UserMessages;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using CS2TraceRay.Class;
|
||||
using CS2TraceRay.Enum;
|
||||
using CS2TraceRay.Struct;
|
||||
using RayTraceAPI;
|
||||
using src.player.skills;
|
||||
using src.utils;
|
||||
using System.Collections.Concurrent;
|
||||
|
|
@ -40,6 +39,8 @@ namespace src.player
|
|||
public static readonly ConcurrentDictionary<ulong, jSkill_SkillInfo> staticSkills = [];
|
||||
private static readonly object setLock = new();
|
||||
|
||||
private static readonly MemoryFunctionVoid<CBasePlayerPawn, CBasePlayerWeapon> DropWeaponFunc = new(GameData.GetSignature("CCSPlayerController_HandleCommandDrop"));
|
||||
|
||||
public static void Load()
|
||||
{
|
||||
Instance.RegisterEventHandler<EventPlayerConnectFull>(PlayerConnectFull);
|
||||
|
|
@ -78,9 +79,13 @@ namespace src.player
|
|||
Instance.HookUserMessage(208, PlayerMakeSound);
|
||||
VirtualFunctions.CBaseEntity_TakeDamageOldFunc.Hook(OnTakeDamage, HookMode.Pre);
|
||||
|
||||
Instance.RegisterEventHandler<EventBulletImpact>(BulletImpact);
|
||||
|
||||
VirtualFunctions.CBaseTrigger_StartTouchFunc.Hook(OnTriggerEnter, HookMode.Post);
|
||||
VirtualFunctions.CBaseTrigger_EndTouchFunc.Hook(OnTriggerExit, HookMode.Pre);
|
||||
VirtualFunctions.CCSPlayer_ItemServices_CanAcquireFunc.Hook(OnWeaponCanAcquire, HookMode.Pre);
|
||||
|
||||
DropWeaponFunc.Hook(WeaponDrop, HookMode.Pre);
|
||||
}
|
||||
|
||||
private static HookResult PlayerMakeSound(UserMessage um)
|
||||
|
|
@ -427,6 +432,33 @@ namespace src.player
|
|||
}
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
lock (setLock)
|
||||
|
|
@ -488,6 +520,8 @@ namespace src.player
|
|||
var skillPlayer = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
|
||||
if (skillPlayer == null) return HookResult.Continue;
|
||||
|
||||
Instance.SkillAction(skillPlayer.Skill.ToString(), "DisableSkill", [player]);
|
||||
|
||||
var items = Instance.SkillPlayer.ToList();
|
||||
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 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;
|
||||
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;
|
||||
|
||||
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()
|
||||
{
|
||||
setSkillTimer = null;
|
||||
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)
|
||||
{
|
||||
|
|
@ -797,7 +851,7 @@ namespace src.player
|
|||
foreach (var player in validPlayers)
|
||||
{
|
||||
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 = "";
|
||||
|
||||
var skillPlayer = Instance?.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
|
||||
|
|
@ -875,6 +929,8 @@ namespace src.player
|
|||
|
||||
Instance?.AddTimer(.2f, () =>
|
||||
{
|
||||
if(player == null || !player.IsValid) return;
|
||||
|
||||
if (randomSkill.Display)
|
||||
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");
|
||||
|
|
@ -901,6 +957,8 @@ namespace src.player
|
|||
{
|
||||
Instance?.AddTimer(.6f, () =>
|
||||
{
|
||||
if (player == null || !player.IsValid) return;
|
||||
|
||||
foreach (var teammate in teammates)
|
||||
{
|
||||
var teammateInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == teammate.SteamID);
|
||||
|
|
|
|||
|
|
@ -121,9 +121,15 @@ namespace src.player.skills
|
|||
if (enemyPawn == null || enemyPawn.AbsOrigin == null) return;
|
||||
|
||||
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);
|
||||
|
||||
pawn.Look(angle);
|
||||
|
|
@ -145,11 +151,10 @@ namespace src.player.skills
|
|||
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 Duration { get; set; } = duration;
|
||||
public float Offset { get; set; } = offsetZ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -40,7 +40,7 @@ namespace src.player.skills
|
|||
{
|
||||
if (skillInfo.LastRotations == null || skillInfo.LastPositions == null) continue;
|
||||
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"))
|
||||
{
|
||||
skillInfo.LastPositions.TryDequeue(out _);
|
||||
|
|
@ -106,7 +106,10 @@ namespace src.player.skills
|
|||
Vector? lastPosition = skillInfo.LastPositions.FirstOrDefault();
|
||||
QAngle? lastRotation = skillInfo.LastRotations.FirstOrDefault();
|
||||
if (lastPosition != null && lastRotation != null)
|
||||
playerPawn.Teleport(lastPosition, lastRotation, null);
|
||||
{
|
||||
playerPawn.Teleport(lastPosition, null, null);
|
||||
playerPawn.Look(lastRotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace src.player.skills
|
|||
public class Baseball : ISkill
|
||||
{
|
||||
private const Skills skillName = Skills.Baseball;
|
||||
private static readonly ConcurrentDictionary<CDecoyProjectile, byte> decoys = [];
|
||||
private static readonly ConcurrentDictionary<uint, byte> decoys = [];
|
||||
|
||||
public static void LoadSkill()
|
||||
{
|
||||
|
|
@ -50,7 +50,7 @@ namespace src.player.skills
|
|||
|
||||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
|
||||
if (playerInfo?.Skill != skillName) return;
|
||||
decoys.TryAdd(decoy, 0);
|
||||
decoys.TryAdd(decoy.Index, 0);
|
||||
|
||||
decoy.Collision.CollisionAttribute.InteractsWith = pawn.Collision.CollisionAttribute.InteractsWith;
|
||||
decoy.Collision.CollisionGroup = pawn.Collision.CollisionGroup;
|
||||
|
|
@ -60,25 +60,33 @@ namespace src.player.skills
|
|||
{
|
||||
var player = @event.Userid;
|
||||
if (player == null || !player.IsValid) return;
|
||||
|
||||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
|
||||
if (playerInfo?.Skill != skillName) return;
|
||||
|
||||
var decoy = decoys.FirstOrDefault(d => d.Key.Index == @event.Entityid).Key;
|
||||
if (decoy != null && decoy.IsValid)
|
||||
decoy.AcceptInput("Kill");
|
||||
if (decoys.ContainsKey((uint)@event.Entityid))
|
||||
{
|
||||
var decoy = Utilities.GetEntityFromIndex<CDecoyProjectile>(@event.Entityid);
|
||||
if (decoy != null && decoy.IsValid)
|
||||
decoy.AcceptInput("Kill");
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
decoy.Bounces = 0;
|
||||
if (Server.TickCount % 8 != 0) continue;
|
||||
|
||||
var vel = decoy.AbsVelocity;
|
||||
float speed = vel.Length();
|
||||
float targetSpeed = Math.Min(speed * SkillsInfo.GetValue<float>(skillName, "speedMultipier"), SkillsInfo.GetValue<float>(skillName, "maxSpeed"));
|
||||
|
|
|
|||
|
|
@ -45,16 +45,8 @@ namespace src.player.skills
|
|||
|
||||
if (pawn == null || !pawn.IsValid || pawn.LifeState != (int)LifeState_t.LIFE_ALIVE) return;
|
||||
|
||||
var currentPosition = pawn.AbsOrigin;
|
||||
var currentAngles = pawn.EyeAngles;
|
||||
|
||||
QAngle newAngles = new(
|
||||
currentAngles.X,
|
||||
currentAngles.Y + 180,
|
||||
currentAngles.Z
|
||||
);
|
||||
|
||||
pawn.Teleport(currentPosition, newAngles, new Vector(0, 0, 0));
|
||||
QAngle look = new(pawn.V_angle.X, pawn.V_angle.Y + 180, 0);
|
||||
pawn.Look(look);
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ namespace src.player.skills
|
|||
{
|
||||
var playerPawn = player.PlayerPawn.Value;
|
||||
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 buttons = player.Buttons;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace src.player.skills
|
|||
public class C4Camouflage : ISkill
|
||||
{
|
||||
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";
|
||||
|
||||
public static void LoadSkill()
|
||||
|
|
@ -44,16 +44,16 @@ namespace src.player.skills
|
|||
if (playerInfo?.Skill != skillName) return;
|
||||
|
||||
if (weapon == "c4")
|
||||
invisiblePlayers.TryAdd(player, 0);
|
||||
invisiblePlayers.TryAdd(player.Index, 0);
|
||||
else
|
||||
invisiblePlayers.TryRemove(player, out _);
|
||||
invisiblePlayers.TryRemove(player.Index, out _);
|
||||
}
|
||||
|
||||
public static void OnTick()
|
||||
{
|
||||
foreach (var player in Utilities.GetPlayers())
|
||||
if (!player.PawnIsAlive)
|
||||
invisiblePlayers.TryRemove(player, out _);
|
||||
invisiblePlayers.TryRemove(player.Index, out _);
|
||||
}
|
||||
|
||||
public static void CheckTransmit([CastFrom(typeof(nint))] CCheckTransmitInfoList infoList)
|
||||
|
|
@ -72,10 +72,15 @@ namespace src.player.skills
|
|||
if (targetInfo?.Skill == skillName) isObservingC4Camouflage = true;
|
||||
}
|
||||
|
||||
foreach (var _player in invisiblePlayers.Keys)
|
||||
if (player.SteamID != _player.SteamID && !isObservingC4Camouflage)
|
||||
foreach (var playerIndex in invisiblePlayers.Keys)
|
||||
{
|
||||
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;
|
||||
|
||||
var entity = Utilities.GetEntityFromIndex<CBaseEntity>((int)playerPawn.Index);
|
||||
|
|
@ -89,6 +94,7 @@ namespace src.player.skills
|
|||
if (bombEntity == null || !bombEntity.IsValid) continue;
|
||||
info.TransmitEntities.Remove(bombEntity.Index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -105,19 +111,19 @@ namespace src.player.skills
|
|||
var activeWeapon = playerPawn.WeaponServices.ActiveWeapon.Value;
|
||||
if (activeWeapon.DesignerName != "weapon_c4") return;
|
||||
|
||||
invisiblePlayers.TryAdd(player, 0);
|
||||
invisiblePlayers.TryAdd(player.Index, 0);
|
||||
}
|
||||
|
||||
public static void DisableSkill(CCSPlayerController player)
|
||||
{
|
||||
invisiblePlayers.TryRemove(player, out _);
|
||||
invisiblePlayers.TryRemove(player.Index, out _);
|
||||
}
|
||||
|
||||
public static void PlayerHurt(EventPlayerHurt @event)
|
||||
{
|
||||
var player = @event.Userid;
|
||||
if (player == null || !player.IsValid) return;
|
||||
if (!invisiblePlayers.ContainsKey(player)) return;
|
||||
if (!invisiblePlayers.ContainsKey(player.Index)) return;
|
||||
|
||||
var playerPawn = player.PlayerPawn.Value;
|
||||
if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return;
|
||||
|
|
|
|||
|
|
@ -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.Utils;
|
||||
using static src.jRandomSkills;
|
||||
using System.Collections.Concurrent;
|
||||
using src.utils;
|
||||
using CounterStrikeSharp.API;
|
||||
using System.Collections.Concurrent;
|
||||
using static src.jRandomSkills;
|
||||
|
||||
namespace src.player.skills
|
||||
{
|
||||
|
|
@ -13,6 +13,7 @@ namespace src.player.skills
|
|||
private const Skills skillName = Skills.CarefulBullets;
|
||||
private static readonly ConcurrentDictionary<ulong, byte> targetPlayers = [];
|
||||
private static readonly ConcurrentDictionary<ulong, bool> lastShot = [];
|
||||
private static readonly ConcurrentDictionary<ulong, int> hitPlayer = [];
|
||||
private static readonly object setLock = new();
|
||||
|
||||
public static void LoadSkill()
|
||||
|
|
@ -26,6 +27,7 @@ namespace src.player.skills
|
|||
{
|
||||
targetPlayers.Clear();
|
||||
lastShot.Clear();
|
||||
hitPlayer.Clear();
|
||||
}
|
||||
foreach (var player in Utilities.GetPlayers())
|
||||
{
|
||||
|
|
@ -100,48 +102,70 @@ namespace src.player.skills
|
|||
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)
|
||||
{
|
||||
CEntityInstance param = h.GetParam<CEntityInstance>(0);
|
||||
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;
|
||||
|
||||
CCSPlayerPawn attackerPawn = new(param2.Attacker.Value.Handle);
|
||||
CCSPlayerPawn victimPawn = new(param.Handle);
|
||||
|
||||
if (attackerPawn.DesignerName != "player")
|
||||
if (attackerPawn.DesignerName != "player" || victimPawn.DesignerName != "player")
|
||||
return;
|
||||
|
||||
if (attackerPawn == null || attackerPawn.Controller?.Value == null)
|
||||
if (attackerPawn == null || attackerPawn.Controller?.Value == null || victimPawn == null || victimPawn.Controller?.Value == null)
|
||||
return;
|
||||
|
||||
CCSPlayerController attacker = attackerPawn.Controller.Value.As<CCSPlayerController>();
|
||||
if (!targetPlayers.ContainsKey(attacker.SteamID)) return;
|
||||
|
||||
if (!targetPlayers.ContainsKey(attacker.SteamID) || !attacker.PawnIsAlive)
|
||||
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);
|
||||
hitPlayer.AddOrUpdate(attacker.SteamID, Server.TickCount, (_, _) => Server.TickCount);
|
||||
}
|
||||
|
||||
public static void DisableSkill(CCSPlayerController player)
|
||||
{
|
||||
targetPlayers.TryRemove(player.SteamID, out _);
|
||||
lastShot.TryRemove(player.SteamID, out _);
|
||||
hitPlayer.TryRemove(player.SteamID, out _);
|
||||
SkillUtils.CloseMenu(player);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,9 +21,9 @@ namespace src.player.skills
|
|||
"weapon_xm1014", "weapon_mag7", "weapon_sawedoff", "weapon_m249",
|
||||
"weapon_negev"
|
||||
];
|
||||
private static readonly ConcurrentDictionary<CCSPlayerController, CBaseModelEntity> chickens = [];
|
||||
private static readonly string defaultCTModel = "characters/models/ctm_sas/ctm_sas.vmdl";
|
||||
private static readonly string defaultTModel = "characters/models/tm_phoenix/tm_phoenix.vmdl";
|
||||
private static readonly ConcurrentDictionary<uint, uint> chickens = [];
|
||||
private static readonly string defaultCTModel = "agents/models/ctm_sas/ctm_sas.vmdl";
|
||||
private static readonly string defaultTModel = "agents/models/tm_phoenix/tm_phoenix.vmdl";
|
||||
private static readonly ConcurrentDictionary<ulong, string> originalModels = [];
|
||||
|
||||
public static void LoadSkill()
|
||||
|
|
@ -35,9 +35,14 @@ namespace src.player.skills
|
|||
{
|
||||
foreach (var player in Utilities.GetPlayers())
|
||||
SetWeaponAttack(player, false);
|
||||
|
||||
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();
|
||||
originalModels.Clear();
|
||||
}
|
||||
|
|
@ -96,11 +101,12 @@ namespace src.player.skills
|
|||
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)
|
||||
chicken.AcceptInput("Kill");
|
||||
chickens.TryRemove(player, out _);
|
||||
}
|
||||
|
||||
if (originalModels.TryGetValue(player.SteamID, out var model))
|
||||
|
|
@ -110,6 +116,9 @@ namespace src.player.skills
|
|||
|
||||
Server.NextFrame(() =>
|
||||
{
|
||||
if (player == null || !player.IsValid) return;
|
||||
if (pawn == null || !pawn.IsValid) return;
|
||||
|
||||
if (string.IsNullOrEmpty(model))
|
||||
model = player.Team == CsTeam.Terrorist ? defaultTModel : defaultCTModel;
|
||||
|
||||
|
|
@ -157,19 +166,27 @@ namespace src.player.skills
|
|||
|
||||
chickenModel.CBodyComponent.SceneNode.GetSkeletonInstance().Scale = 1;
|
||||
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");
|
||||
chickens.TryAdd(player, chickenModel);
|
||||
chickens.TryAdd(player.Index, chickenModel.Index);
|
||||
}
|
||||
|
||||
public static void OnTick()
|
||||
{
|
||||
foreach (var valuePair in chickens)
|
||||
{
|
||||
var player = valuePair.Key;
|
||||
var chicken = valuePair.Value;
|
||||
var playerIndex = valuePair.Key;
|
||||
var chickenIndex = valuePair.Value;
|
||||
|
||||
var player = Utilities.GetPlayerFromIndex((int)playerIndex);
|
||||
if (player == null || !player.IsValid) continue;
|
||||
|
||||
var chicken = Utilities.GetEntityFromIndex<CBaseModelEntity>((int)chickenIndex);
|
||||
if (chicken == null || !chicken.IsValid) continue;
|
||||
|
||||
var pawn = player.PlayerPawn.Value;
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@ using CounterStrikeSharp.API.Core;
|
|||
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
|
||||
using CounterStrikeSharp.API.Modules.Timers;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using CS2TraceRay.Class;
|
||||
using CS2TraceRay.Struct;
|
||||
using RayTraceAPI;
|
||||
using src.utils;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Drawing;
|
||||
|
|
@ -17,7 +16,7 @@ namespace src.player.skills
|
|||
public class Cypher : ISkill
|
||||
{
|
||||
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 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;
|
||||
if (playerPawn?.CBodyComponent == null) return;
|
||||
if (playersInfo.TryGetValue(player, out var playerSkill))
|
||||
if (playersInfo.TryGetValue(player.Index, out var playerSkill))
|
||||
ChangeCamera(playerSkill);
|
||||
}
|
||||
|
||||
public static void EnableSkill(CCSPlayerController player)
|
||||
{
|
||||
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,
|
||||
CameraView = null,
|
||||
CameraActive = false,
|
||||
|
|
@ -64,29 +63,36 @@ namespace src.player.skills
|
|||
|
||||
public static void DisableSkill(CCSPlayerController player)
|
||||
{
|
||||
if (playersInfo.TryGetValue(player, out var playerSkill))
|
||||
if (playersInfo.TryGetValue(player.Index, out var playerSkill))
|
||||
{
|
||||
ChangeCamera(playerSkill, true);
|
||||
KillCamera(playerSkill);
|
||||
}
|
||||
playersInfo.TryRemove(player, out _);
|
||||
playersInfo.TryRemove(player.Index, out _);
|
||||
}
|
||||
|
||||
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.CameraActive = false;
|
||||
}
|
||||
|
||||
if (playerSkill.CameraProp != null && playerSkill.CameraProp.IsValid)
|
||||
if (playerSkill.CameraProp != null && playerSkill.CameraProp != 0)
|
||||
{
|
||||
playerSkill.CameraProp.EmitSound("SolidMetal.BulletImpact");
|
||||
playerSkill.CameraProp.AcceptInput("Kill");
|
||||
var cameraProp = Utilities.GetEntityFromIndex<CDynamicProp>((int)playerSkill.CameraProp);
|
||||
if (cameraProp != null && cameraProp.IsValid)
|
||||
{
|
||||
cameraProp.EmitSound("SolidMetal.BulletImpact");
|
||||
cameraProp.AcceptInput("Kill");
|
||||
}
|
||||
playerSkill.CameraProp = null;
|
||||
}
|
||||
|
||||
playerSkill.CameraActive = false;
|
||||
playerSkill.NextCamera = Server.TickCount + SkillsInfo.GetValue<float>(skillName, "Cooldown") * 64;
|
||||
}
|
||||
|
||||
|
|
@ -94,65 +100,88 @@ namespace src.player.skills
|
|||
{
|
||||
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;
|
||||
if (pawn == null || !pawn.IsValid) continue;
|
||||
var enemy = Utilities.GetPlayerFromIndex((int)playerSkill.Player);
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ChangeCamera(PlayerSkill player, bool forceToDefault = false)
|
||||
private static void ChangeCamera(PlayerSkill playerInfo, bool forceToDefault = false)
|
||||
{
|
||||
player.CameraActive = forceToDefault ? false : !player.CameraActive;
|
||||
if (player.CameraProp == null && !forceToDefault)
|
||||
var player = Utilities.GetPlayerFromIndex((int)playerInfo.Player);
|
||||
if (player == null || !player.IsValid) return;
|
||||
|
||||
playerInfo.CameraActive = forceToDefault ? false : !playerInfo.CameraActive;
|
||||
if (playerInfo.CameraProp == null && !forceToDefault)
|
||||
{
|
||||
if (player.NextCamera > Server.TickCount) return;
|
||||
player.CameraProp = CreateCameraProp(player.Player);
|
||||
if (player.CameraProp == null)
|
||||
if (playerInfo.NextCamera > Server.TickCount) return;
|
||||
|
||||
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;
|
||||
}
|
||||
player.CameraView = CreateCameraView(player.Player);
|
||||
if (player.CameraView == null) return;
|
||||
else
|
||||
playerInfo.CameraView = CreateCameraView(newProp)?.Index ?? null;
|
||||
|
||||
if (playerInfo.CameraView == null) return;
|
||||
}
|
||||
|
||||
var pawn = player.Player.PlayerPawn.Value;
|
||||
if (player.PlayerCameraRaw == 0)
|
||||
var pawn = player.PlayerPawn.Value;
|
||||
if (playerInfo.PlayerCameraRaw == 0)
|
||||
return;
|
||||
|
||||
BlockWeapon(player.Player, player.CameraActive);
|
||||
BlockWeapon(player, playerInfo.CameraActive);
|
||||
|
||||
Server.NextWorldUpdate(() =>
|
||||
{
|
||||
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)
|
||||
player.LastAngle = new QAngle(pawn.AbsRotation.X, pawn.AbsRotation.Y, pawn.AbsRotation.Z);
|
||||
pawn.Teleport(null, player.CameraProp.AbsRotation);
|
||||
if (pawn.AbsRotation != null)
|
||||
playerInfo.LastAngle = new QAngle(pawn.V_angle.X, pawn.V_angle.Y, 0);
|
||||
|
||||
var cameraProp = Utilities.GetEntityFromIndex<CDynamicProp>((int)playerInfo.CameraProp);
|
||||
if (cameraProp == null || !cameraProp.IsValid) return;
|
||||
|
||||
pawn.Teleport(null, cameraProp.AbsRotation);
|
||||
}
|
||||
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;
|
||||
SkillUtils.ApplyScreenColor(player.Player, 0, 0, 255, 20, 100, 1020);
|
||||
var cameraView = Utilities.GetEntityFromIndex<CDynamicProp>((int)playerInfo.CameraView);
|
||||
if (cameraView == null || !cameraView.IsValid) return;
|
||||
|
||||
ulong? playerSteamID = player.Player?.SteamID;
|
||||
if (playerSteamID == null) return;
|
||||
pawn!.CameraServices!.ViewEntity.Raw = cameraView.EntityHandle.Raw;
|
||||
SkillUtils.ApplyScreenColor(player, 0, 0, 255, 20, 100, 1020);
|
||||
|
||||
ulong playerSteamID = player.SteamID;
|
||||
|
||||
Timer? cameraTimer = null;
|
||||
cameraTimer = jRandomSkills.Instance.AddTimer(2f, () =>
|
||||
|
|
@ -164,7 +193,7 @@ namespace src.player.skills
|
|||
return;
|
||||
}
|
||||
|
||||
if (!playersInfo.TryGetValue(target, out var playerSkill) || playerSkill.CameraActive == false)
|
||||
if (!playersInfo.TryGetValue(target.Index, out var playerSkill) || playerSkill.CameraActive == false)
|
||||
{
|
||||
cameraTimer?.Kill();
|
||||
return;
|
||||
|
|
@ -174,7 +203,7 @@ namespace src.player.skills
|
|||
}, TimerFlags.STOP_ON_MAPCHANGE | TimerFlags.REPEAT);
|
||||
}
|
||||
else
|
||||
pawn!.CameraServices!.ViewEntity.Raw = player.PlayerCameraRaw;
|
||||
pawn!.CameraServices!.ViewEntity.Raw = playerInfo.PlayerCameraRaw;
|
||||
|
||||
Utilities.SetStateChanged(pawn, "CBasePlayerPawn", "m_pCameraServices");
|
||||
});
|
||||
|
|
@ -182,6 +211,18 @@ namespace src.player.skills
|
|||
|
||||
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");
|
||||
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.Entity!.Name = camera.Globalname = $"CypherCamera_{Server.TickCount}_{player.SteamID}";
|
||||
|
||||
var playerPawn = player.PlayerPawn.Value;
|
||||
if (playerPawn == null || !playerPawn.IsValid) return null;
|
||||
|
||||
Vector? cameraVector = GetNewCameraPosition(player);
|
||||
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();
|
||||
});
|
||||
if (camera == null || !camera.IsValid) return null;
|
||||
camera.SetModel(cameraPropModel);
|
||||
camera.Teleport(cameraVector, new QAngle(0, playerPawn.V_angle.Y + 180, 0));
|
||||
camera.DispatchSpawn();
|
||||
|
||||
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");
|
||||
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(() =>
|
||||
{
|
||||
if (camera == null || !camera.IsValid) return;
|
||||
camera.SetModel(cameraViewModel);
|
||||
camera.Render = Color.FromArgb(0, 255, 255, 255);
|
||||
camera.Teleport(cameraVector, playerPawn.EyeAngles);
|
||||
|
||||
camera.Teleport(finalPos, cameraProp.AbsRotation);
|
||||
camera.DispatchSpawn();
|
||||
});
|
||||
|
||||
|
|
@ -254,7 +280,7 @@ namespace src.player.skills
|
|||
var player = Utilities.GetPlayerFromSteamId(steamID);
|
||||
if (player == null) return;
|
||||
|
||||
if (playersInfo.TryGetValue(player, out var playerSkill))
|
||||
if (playersInfo.TryGetValue(player.Index, out var playerSkill))
|
||||
{
|
||||
ChangeCamera(playerSkill, true);
|
||||
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 endPos = eyePos + SkillUtils.GetForwardVector(playerPawn.V_angle) * 4096f;
|
||||
|
||||
ulong solid = 0x1;
|
||||
ulong window = 0x1000;
|
||||
ulong passBullets = 0x2000;
|
||||
ulong mask = (ulong)(InteractionLayers.Solid | InteractionLayers.Window | InteractionLayers.PassBullets);
|
||||
var result = RayTrace.TraceShape(player, eyePos, endPos, mask);
|
||||
|
||||
ulong mask = solid | window | passBullets;
|
||||
ulong contents = playerPawn.Collision.CollisionGroup;
|
||||
CGameTrace trace = TraceRay.TraceShape(eyePos, endPos, mask, contents, player);
|
||||
|
||||
if (trace.HitWorld(out _))
|
||||
if (result.HasValue && result.Value.HitWorld(out _))
|
||||
{
|
||||
Vector3 hitPost = trace.EndPos;
|
||||
Vector3 normal = trace.Normal;
|
||||
Vector3 hitPost = result.Value.EndPos;
|
||||
Vector3 normal = result.Value.Normal;
|
||||
|
||||
float offset = 8;
|
||||
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;
|
||||
cameraVector += SkillUtils.GetForwardVector(new QAngle(0, playerPawn.V_angle.Y + 180, 0)) * 5;
|
||||
|
||||
ulong solid = 0x1;
|
||||
ulong window = 0x1000;
|
||||
ulong passBullets = 0x2000;
|
||||
ulong mask = (ulong)(InteractionLayers.Solid | InteractionLayers.Window | InteractionLayers.PassBullets);
|
||||
var result = RayTrace.TraceShape(player, cameraVector, endPos, mask);
|
||||
|
||||
ulong mask = solid | window | passBullets;
|
||||
ulong contents = playerPawn.Collision.CollisionGroup;
|
||||
CGameTrace trace = TraceRay.TraceShape(cameraVector, endPos, mask, contents, player);
|
||||
|
||||
if (trace.HitWorld(out _))
|
||||
if (result.HasValue && result.Value.HitWorld(out _))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
|
@ -336,28 +352,30 @@ namespace src.player.skills
|
|||
|
||||
private static void UpdateHUD(PlayerSkill playerSkill)
|
||||
{
|
||||
if (playerSkill == null || playerSkill.Player == null) return;
|
||||
if (playerSkill == null) return;
|
||||
|
||||
float cooldown = 0;
|
||||
float time = (playerSkill.NextCamera - Server.TickCount) / 64;
|
||||
cooldown = (int)Math.Ceiling(Math.Max(time, 0));
|
||||
var player = Utilities.GetPlayerFromIndex((int)playerSkill.Player);
|
||||
if (player == null || !player.IsValid) return;
|
||||
|
||||
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;
|
||||
|
||||
float ticksLeft = playerSkill.NextCamera - Server.TickCount;
|
||||
int secondsLeft = (int)Math.Ceiling(Math.Max(ticksLeft / 64.0f, 0));
|
||||
|
||||
if (playerSkill.NoSpace >= Server.TickCount)
|
||||
playerInfo.PrintHTML = $"<font color='#FF0000'>{playerSkill.Player.GetTranslation("cypher_nospace")}</font>";
|
||||
else if (cooldown == 0)
|
||||
playerInfo.PrintHTML = $"<font color='#FF0000'>{player.GetTranslation("cypher_nospace")}</font>";
|
||||
else if (secondsLeft > 0 && playerSkill.CameraProp == null)
|
||||
playerInfo.PrintHTML = $"{player.GetTranslation("hud_info", $"<font color='#FF0000'>{secondsLeft}</font>")}";
|
||||
else
|
||||
playerInfo.PrintHTML = null;
|
||||
else if (playerSkill?.CameraProp == null)
|
||||
playerInfo.PrintHTML = $"{playerSkill?.Player.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}";
|
||||
}
|
||||
|
||||
public class PlayerSkill
|
||||
{
|
||||
public required CCSPlayerController Player { get; set; }
|
||||
public CDynamicProp? CameraProp { get; set; }
|
||||
public CDynamicProp? CameraView { get; set; }
|
||||
public required uint Player { get; set; }
|
||||
public uint? CameraProp { get; set; }
|
||||
public uint? CameraView { get; set; }
|
||||
public uint PlayerCameraRaw { get; set; }
|
||||
public bool CameraActive { get; set; }
|
||||
public float NextCamera { get; set; }
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace src.player.skills
|
|||
public class Deaf : ISkill
|
||||
{
|
||||
private const Skills skillName = Skills.Deaf;
|
||||
private static readonly ConcurrentDictionary<CCSPlayerController, byte> deafPlayers = [];
|
||||
private static readonly ConcurrentDictionary<uint, byte> deafPlayers = [];
|
||||
|
||||
public static void LoadSkill()
|
||||
{
|
||||
|
|
@ -20,8 +20,13 @@ namespace src.player.skills
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
deafPlayers.Clear();
|
||||
foreach (var player in Utilities.GetPlayers())
|
||||
SkillUtils.CloseMenu(player);
|
||||
|
|
@ -29,8 +34,12 @@ namespace src.player.skills
|
|||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
public static void OnTick()
|
||||
|
|
@ -44,7 +53,7 @@ namespace src.player.skills
|
|||
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();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -70,7 +79,7 @@ namespace src.player.skills
|
|||
return;
|
||||
}
|
||||
|
||||
deafPlayers.TryAdd(enemy, 0);
|
||||
deafPlayers.TryAdd(enemy.Index, 0);
|
||||
playerInfo.SkillUsed = true;
|
||||
player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("deaf_player_info", enemy.PlayerName));
|
||||
enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("deaf_enemy_info"));
|
||||
|
|
@ -95,7 +104,7 @@ namespace src.player.skills
|
|||
public static void DisableSkill(CCSPlayerController 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)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace src.player.skills
|
|||
public class Distancer : ISkill
|
||||
{
|
||||
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();
|
||||
|
||||
public static void LoadSkill()
|
||||
|
|
@ -26,8 +26,11 @@ namespace src.player.skills
|
|||
public static void OnTick()
|
||||
{
|
||||
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);
|
||||
if (playerInfo == null) continue;
|
||||
|
||||
|
|
@ -56,12 +59,12 @@ namespace src.player.skills
|
|||
|
||||
public static void EnableSkill(CCSPlayerController player)
|
||||
{
|
||||
distancerPlayers.TryAdd(player, 0);
|
||||
distancerPlayers.TryAdd(player.Index, 0);
|
||||
}
|
||||
|
||||
public static void DisableSkill(CCSPlayerController player)
|
||||
{
|
||||
distancerPlayers.TryRemove(player, out _);
|
||||
distancerPlayers.TryRemove(player.Index, out _);
|
||||
SkillUtils.ResetPrintHTML(player);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Entities;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using static src.jRandomSkills;
|
||||
using System.Collections.Concurrent;
|
||||
using src.utils;
|
||||
using System.Collections.Concurrent;
|
||||
using static src.jRandomSkills;
|
||||
|
||||
namespace src.player.skills
|
||||
{
|
||||
|
|
@ -120,12 +121,18 @@ namespace src.player.skills
|
|||
bool ctSkill = Event.counterterroristSkills.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))
|
||||
{
|
||||
Instance.AddTimer(.1f, () =>
|
||||
{
|
||||
var player = Utilities.GetPlayerFromSteamId(steamID);
|
||||
if (player == null || !player.IsValid) return;
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -139,6 +146,9 @@ namespace src.player.skills
|
|||
|
||||
if (SkillsInfo.GetValue<bool>(enemySkill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime())
|
||||
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;
|
||||
Instance?.SkillAction(enemySkill.ToString(), "EnableSkill", [player]);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using src.utils;
|
||||
using static src.jRandomSkills;
|
||||
|
|
@ -24,8 +23,10 @@ namespace src.player.skills
|
|||
{
|
||||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
|
||||
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");
|
||||
playerInfo.SkillChance = 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");
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
public static void OnTakeDamage(DynamicHook h)
|
||||
public static void BulletImpact(EventBulletImpact @event)
|
||||
{
|
||||
if (lastTick == Server.TickCount) return;
|
||||
|
||||
CEntityInstance param = h.GetParam<CEntityInstance>(0);
|
||||
CTakeDamageInfo param2 = h.GetParam<CTakeDamageInfo>(1);
|
||||
var player = @event.Userid;
|
||||
if (player == null || !player.IsValid) return;
|
||||
|
||||
if (param == null || param.Entity == null || param2 == null || param2.Attacker == null || param2.Attacker.Value == null)
|
||||
return;
|
||||
var pos = new Vector(@event.X, @event.Y, @event.Z);
|
||||
|
||||
CCSPlayerPawn attackerPawn = new(param2.Attacker.Value.Handle);
|
||||
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);
|
||||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
|
||||
if (playerInfo == null || playerInfo.Skill != skillName) return;
|
||||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace src.player.skills
|
|||
public class FalconEye : ISkill
|
||||
{
|
||||
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()
|
||||
{
|
||||
|
|
@ -20,9 +20,14 @@ namespace src.player.skills
|
|||
|
||||
public static void NewRound()
|
||||
{
|
||||
foreach (var camera in cameras)
|
||||
if (camera.Value.Item2 != null && camera.Value.Item2.IsValid)
|
||||
camera.Value.Item2.AcceptInput("Kill");
|
||||
foreach (var cameraIndex in cameras.Values)
|
||||
{
|
||||
var camera = Utilities.GetEntityFromIndex<CDynamicProp>((int)cameraIndex.Item2);
|
||||
if (camera == null || !camera.IsValid) continue;
|
||||
|
||||
camera.AcceptInput("Kill");
|
||||
}
|
||||
|
||||
cameras.Clear();
|
||||
}
|
||||
|
||||
|
|
@ -56,18 +61,23 @@ namespace src.player.skills
|
|||
public static void OnTick()
|
||||
{
|
||||
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;
|
||||
if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) continue;
|
||||
|
||||
if (pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE)
|
||||
{
|
||||
ChangeCamera(player, true);
|
||||
continue;
|
||||
}
|
||||
|
||||
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);
|
||||
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;
|
||||
var pawn = player.PlayerPawn.Value;
|
||||
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;
|
||||
newCameraRaw = cameraInfo.Item2.EntityHandle.Raw;
|
||||
|
||||
var camera = Utilities.GetEntityFromIndex<CDynamicProp>((int)cameraInfo.Item2);
|
||||
if (camera == null || !camera.IsValid) return;
|
||||
|
||||
newCameraRaw = camera.EntityHandle.Raw;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -108,13 +123,14 @@ namespace src.player.skills
|
|||
|
||||
Server.NextFrame(() =>
|
||||
{
|
||||
if (camera == null || !camera.IsValid) return;
|
||||
camera.SetModel("models/actors/ghost_speaker.vmdl");
|
||||
camera.Render = Color.FromArgb(0, 255, 255, 255);
|
||||
camera.Teleport(pos, new QAngle(90, 0, 0));
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ namespace src.player.skills
|
|||
barricades.TryAdd(box.Index, SkillsInfo.GetValue<int>(skillName, "barricadeHealth"));
|
||||
Server.NextFrame(() =>
|
||||
{
|
||||
if (box == null || !box.IsValid) return;
|
||||
box.SetModel(SkillsInfo.GetValue<string>(skillName, "propModel"));
|
||||
box.Teleport(pos, angle, null);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Entities.Constants;
|
||||
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using src.utils;
|
||||
using static src.jRandomSkills;
|
||||
using Vector = CounterStrikeSharp.API.Modules.Utils.Vector;
|
||||
|
||||
namespace src.player.skills
|
||||
{
|
||||
|
|
@ -14,8 +13,8 @@ namespace src.player.skills
|
|||
private static int bombHealth = 1000;
|
||||
private static int maxBombHealth = 1000;
|
||||
|
||||
private static CPlantedC4? plantedC4;
|
||||
private static CTriggerMultiple? triggerC4;
|
||||
private static int lastTick = 0;
|
||||
private static Vector? plantedC4;
|
||||
|
||||
public static void LoadSkill()
|
||||
{
|
||||
|
|
@ -27,80 +26,42 @@ namespace src.player.skills
|
|||
bombHealth = SkillsInfo.GetValue<int>(skillName, "maxBombHealth");
|
||||
maxBombHealth = SkillsInfo.GetValue<int>(skillName, "maxBombHealth");
|
||||
plantedC4 = null;
|
||||
triggerC4 = null;
|
||||
}
|
||||
|
||||
public static void BombPlanted(EventBombPlanted _)
|
||||
{
|
||||
var plantedBomb = Utilities.FindAllEntitiesByDesignerName<CPlantedC4>("planted_c4").FirstOrDefault();
|
||||
if (plantedBomb == null) return;
|
||||
plantedC4 = plantedBomb;
|
||||
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;
|
||||
if (plantedBomb == null || !plantedBomb.IsValid || plantedBomb.AbsOrigin == null) return;
|
||||
plantedC4 = new(plantedBomb.AbsOrigin.X, plantedBomb.AbsOrigin.Y, plantedBomb.AbsOrigin.Z);
|
||||
}
|
||||
|
||||
private static void RemoveBomb()
|
||||
{
|
||||
if (plantedC4 != null && plantedC4.IsValid)
|
||||
plantedC4.AcceptInput("Kill");
|
||||
if (triggerC4 != null && triggerC4.IsValid)
|
||||
triggerC4.AcceptInput("Kill");
|
||||
plantedC4 = null;
|
||||
var plantedBomb = Utilities.FindAllEntitiesByDesignerName<CPlantedC4>("planted_c4").FirstOrDefault();
|
||||
if (plantedBomb != null && plantedBomb.IsValid)
|
||||
plantedBomb.AcceptInput("Kill");
|
||||
SkillUtils.TerminateRound(CsTeam.CounterTerrorist);
|
||||
}
|
||||
|
||||
public static void OnTakeDamage(DynamicHook h)
|
||||
public static void BulletImpact(EventBulletImpact @event)
|
||||
{
|
||||
CEntityInstance param = h.GetParam<CEntityInstance>(0);
|
||||
CTakeDamageInfo param2 = h.GetParam<CTakeDamageInfo>(1);
|
||||
if (lastTick == Server.TickCount) return;
|
||||
|
||||
if (param == null || param.Entity == null || param2 == null || param2.Attacker == null || param2.Attacker.Value == null)
|
||||
return;
|
||||
var player = @event.Userid;
|
||||
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")
|
||||
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);
|
||||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
|
||||
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)
|
||||
{
|
||||
RemoveBomb();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Cvars;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using src.utils;
|
||||
using static src.jRandomSkills;
|
||||
|
|
@ -34,6 +35,10 @@ namespace src.player.skills
|
|||
|
||||
var pawn = victim.PlayerPawn.Value;
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ namespace src.player.skills
|
|||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
|
||||
if (playerInfo?.Skill != skillName) return;
|
||||
|
||||
ulong steamID = player.SteamID;
|
||||
|
||||
if (playerInfo.SkillUsed)
|
||||
{
|
||||
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())
|
||||
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]);
|
||||
});
|
||||
else
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace src.player.skills
|
|||
"weapon_g3sg1", "weapon_nova", "weapon_xm1014", "weapon_mag7",
|
||||
"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";
|
||||
|
||||
public static void LoadSkill()
|
||||
|
|
@ -76,22 +76,31 @@ namespace src.player.skills
|
|||
if (targetInfo?.Skill == skillName) isObservingGhost = true;
|
||||
}
|
||||
|
||||
foreach (var _player in invisiblePlayers.Keys)
|
||||
if (player.SteamID != _player.SteamID && !isObservingGhost)
|
||||
foreach (var playerIndex in invisiblePlayers.Keys)
|
||||
{
|
||||
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;
|
||||
|
||||
var entity = Utilities.GetEntityFromIndex<CBaseEntity>((int)playerPawn.Index);
|
||||
if (entity == null || !entity.IsValid) continue;
|
||||
|
||||
info.TransmitEntities.Remove(entity.Index);
|
||||
|
||||
var bombIndex = GetBombIndex(_player);
|
||||
var bombIndex = GetBombIndex(playerController);
|
||||
if (bombIndex == null) continue;
|
||||
|
||||
var bombEntity = Utilities.GetEntityFromIndex<CBaseEntity>((int)bombIndex);
|
||||
if (bombEntity == null || !bombEntity.IsValid) continue;
|
||||
|
||||
info.TransmitEntities.Remove(bombEntity.Index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -99,14 +108,14 @@ namespace src.player.skills
|
|||
{
|
||||
Event.EnableTransmit();
|
||||
SetWeaponAttack(player, true);
|
||||
invisiblePlayers.TryAdd(player, 0);
|
||||
invisiblePlayers.TryAdd(player.Index, 0);
|
||||
}
|
||||
|
||||
public static void DisableSkill(CCSPlayerController player)
|
||||
{
|
||||
SkillUtils.ResetPrintHTML(player);
|
||||
SetWeaponAttack(player, false);
|
||||
invisiblePlayers.TryRemove(player, out _);
|
||||
invisiblePlayers.TryRemove(player.Index, out _);
|
||||
}
|
||||
|
||||
public static void OnTick()
|
||||
|
|
@ -116,8 +125,9 @@ namespace src.player.skills
|
|||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
|
||||
if (playerInfo?.Skill == skillName)
|
||||
UpdateHUD(player);
|
||||
|
||||
if (!player.PawnIsAlive)
|
||||
invisiblePlayers.TryRemove(player, out _);
|
||||
invisiblePlayers.TryRemove(player.Index, out _);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -125,7 +135,7 @@ namespace src.player.skills
|
|||
{
|
||||
var player = @event.Userid;
|
||||
if (player == null || !player.IsValid) return;
|
||||
if (!invisiblePlayers.ContainsKey(player)) return;
|
||||
if (!invisiblePlayers.ContainsKey(player.Index)) return;
|
||||
|
||||
var playerPawn = player.PlayerPawn.Value;
|
||||
if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Entities;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using static src.jRandomSkills;
|
||||
using System.Collections.Concurrent;
|
||||
using src.utils;
|
||||
using System.Collections.Concurrent;
|
||||
using static src.jRandomSkills;
|
||||
|
||||
namespace src.player.skills
|
||||
{
|
||||
|
|
@ -49,6 +50,10 @@ namespace src.player.skills
|
|||
{
|
||||
SkillPlayerInfo.TryRemove(player.SteamID, out _);
|
||||
SkillUtils.ResetPrintHTML(player);
|
||||
|
||||
var playerPawn = player.PlayerPawn.Value;
|
||||
if (playerPawn != null && playerPawn.IsValid)
|
||||
playerPawn.TakesDamage = true;
|
||||
}
|
||||
|
||||
private static void UpdateHUD(CCSPlayerController player, PlayerSkillInfo skillInfo)
|
||||
|
|
@ -77,7 +82,9 @@ namespace src.player.skills
|
|||
var playerPawn = player.PlayerPawn.Value;
|
||||
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 (skillInfo.CanUse)
|
||||
|
|
@ -89,8 +96,11 @@ namespace src.player.skills
|
|||
player.PlayerPawn.Value.TakesDamage = false;
|
||||
|
||||
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.PrintToChat($" {ChatColors.Red} {player.GetTranslation("godmode_off")}");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ namespace src.player.skills
|
|||
|
||||
Server.NextFrame(() =>
|
||||
{
|
||||
if (entity == null || !entity.IsValid) return;
|
||||
var smoke = entity.As<CSmokeGrenadeProjectile>();
|
||||
smoke.SmokeColor.X = 0;
|
||||
smoke.SmokeColor.Y = 255;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ namespace src.player.skills
|
|||
|
||||
Server.NextFrame(() =>
|
||||
{
|
||||
if (@event == null || !@event.IsValid) return;
|
||||
var hegrenade = @event.As<CHEGrenadeProjectile>();
|
||||
if (hegrenade == null || !hegrenade.IsValid) return;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@ using CounterStrikeSharp.API.Core;
|
|||
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
|
||||
using CounterStrikeSharp.API.Modules.Timers;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using CS2TraceRay.Class;
|
||||
using CS2TraceRay.Struct;
|
||||
using src.utils;
|
||||
using System.Collections.Concurrent;
|
||||
using Timer = CounterStrikeSharp.API.Modules.Timers.Timer;
|
||||
|
|
@ -15,7 +13,7 @@ namespace src.player.skills
|
|||
public class Iana : ISkill
|
||||
{
|
||||
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();
|
||||
|
||||
public static void LoadSkill()
|
||||
|
|
@ -35,7 +33,7 @@ namespace src.player.skills
|
|||
{
|
||||
var player = @event.Userid;
|
||||
if (player == null) return;
|
||||
if (playersInfo.TryGetValue(player, out var playerSkill))
|
||||
if (playersInfo.TryGetValue(player.Index, out var playerSkill))
|
||||
if (playerSkill.CloneProp != null)
|
||||
BlockWeapon(player, true);
|
||||
}
|
||||
|
|
@ -44,7 +42,7 @@ namespace src.player.skills
|
|||
{
|
||||
var player = @event.Userid;
|
||||
if (player == null) return;
|
||||
if (playersInfo.TryGetValue(player, out var playerSkill))
|
||||
if (playersInfo.TryGetValue(player.Index, out var playerSkill))
|
||||
if (playerSkill.CloneProp != null)
|
||||
BlockWeapon(player, true);
|
||||
}
|
||||
|
|
@ -54,9 +52,12 @@ namespace src.player.skills
|
|||
var playerPawn = player.PlayerPawn.Value;
|
||||
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)
|
||||
{
|
||||
UpdateWeapons(player, playerSkill);
|
||||
CreateClone(playerSkill);
|
||||
}
|
||||
else if (playerSkill.CloneProp != null)
|
||||
KillClone(playerSkill);
|
||||
}
|
||||
|
|
@ -64,9 +65,9 @@ namespace src.player.skills
|
|||
public static void EnableSkill(CCSPlayerController player)
|
||||
{
|
||||
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,
|
||||
NextUse = 0,
|
||||
UseTime = 0,
|
||||
|
|
@ -75,32 +76,54 @@ namespace src.player.skills
|
|||
|
||||
public static void DisableSkill(CCSPlayerController player)
|
||||
{
|
||||
if (playersInfo.TryGetValue(player, out var playerSkill))
|
||||
if (playersInfo.TryGetValue(player.Index, out var 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)
|
||||
{
|
||||
playerSkill.Player.EmitSound("SolidMetal.BulletImpact");
|
||||
if (playerSkill.CloneProp != null && playerSkill.CloneProp.IsValid && playerSkill.CloneProp.AbsOrigin != null && playerSkill.CloneProp.AbsRotation != null)
|
||||
var player = Utilities.GetPlayerFromIndex((int)playerSkill.PlayerIndex);
|
||||
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)
|
||||
{
|
||||
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);
|
||||
Vector pos = new(cloneProp.AbsOrigin.X, cloneProp.AbsOrigin.Y, cloneProp.AbsOrigin.Z);
|
||||
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;
|
||||
}
|
||||
|
||||
SkillUtils.ApplyScreenColor(playerSkill.Player, 0, 0, 0, 0, 10, 0, 2);
|
||||
BlockWeapon(playerSkill.Player, false);
|
||||
SkillUtils.ApplyScreenColor(player, 0, 0, 0, 0, 10, 0, 2);
|
||||
BlockWeapon(player, false);
|
||||
playerSkill.NextUse = Server.TickCount + SkillsInfo.GetValue<float>(skillName, "Cooldown") * 64;
|
||||
playerSkill.UseTime = 0;
|
||||
}
|
||||
|
|
@ -113,20 +136,32 @@ namespace src.player.skills
|
|||
|
||||
private static CDynamicProp? CreateClone(PlayerSkill playerSkill)
|
||||
{
|
||||
var player = playerSkill.Player;
|
||||
if (player == null) return null;
|
||||
var player = Utilities.GetPlayerFromIndex((int)playerSkill.PlayerIndex);
|
||||
if (player == null || !player.IsValid) 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))
|
||||
if (!((PlayerFlags)playerPawn.Flags).HasFlag(PlayerFlags.FL_ONGROUND))
|
||||
{
|
||||
playerSkill.InfoTime = Server.TickCount;
|
||||
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");
|
||||
if (clone == null || !clone.IsValid) return null;
|
||||
|
||||
|
|
@ -137,16 +172,21 @@ namespace src.player.skills
|
|||
|
||||
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.Teleport(playerPawn.AbsOrigin, new QAngle(0, playerPawn.V_angle.Y, 0));
|
||||
|
||||
playerPawn.Teleport(pos);
|
||||
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.NextUse = Server.TickCount + 64000;
|
||||
playerSkill.CloneProp = clone;
|
||||
playerSkill.CloneProp = clone.Index;
|
||||
|
||||
jRandomSkills.Instance.AddTimer(SkillsInfo.GetValue<float>(skillName, "Duration"), () =>
|
||||
{
|
||||
|
|
@ -167,7 +207,7 @@ namespace src.player.skills
|
|||
return;
|
||||
}
|
||||
|
||||
if (!playersInfo.TryGetValue(target, out var playerSkill) || playerSkill.CloneProp == null)
|
||||
if (!playersInfo.TryGetValue(target.Index, out var playerSkill) || playerSkill.CloneProp == null)
|
||||
{
|
||||
cloneTimer?.Kill();
|
||||
return;
|
||||
|
|
@ -183,16 +223,14 @@ namespace src.player.skills
|
|||
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;
|
||||
Vector start = new(playerPawn!.AbsOrigin!.X, playerPawn!.AbsOrigin!.Y, endPos.Z);
|
||||
var result = RayTrace.TraceHullShape(start, endPos, player);
|
||||
|
||||
ulong mask = playerPawn.Collision.CollisionAttribute.InteractsWith;
|
||||
ulong contents = playerPawn.Collision.CollisionGroup;
|
||||
CGameTrace trace = TraceRay.TraceShape(eyePos, endPos, mask, contents, player);
|
||||
if (!result.HasValue)
|
||||
return false;
|
||||
|
||||
return !trace.DidHit();
|
||||
return !result.Value.DidHit;
|
||||
}
|
||||
|
||||
private static float CalculateDamage(CCSPlayerController player, string weaponName, float damage, bool isHeadshot)
|
||||
|
|
@ -240,12 +278,16 @@ namespace src.player.skills
|
|||
|
||||
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 posCl = playerSkill.CloneProp.AbsOrigin;
|
||||
Vector posCl = cloneProp.AbsOrigin;
|
||||
|
||||
bool isHead = false;
|
||||
float viewOffset = 63.27f;
|
||||
|
|
@ -273,7 +315,7 @@ namespace src.player.skills
|
|||
var victim = @event.Userid!;
|
||||
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);
|
||||
SkillUtils.RestoreHealth(victim);
|
||||
|
|
@ -299,7 +341,10 @@ namespace src.player.skills
|
|||
|
||||
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 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;
|
||||
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 (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)
|
||||
playerInfo.PrintHTML = null;
|
||||
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)
|
||||
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 required CCSPlayerController Player { get; set; }
|
||||
public CDynamicProp? CloneProp { get; set; }
|
||||
public required uint PlayerIndex { get; set; }
|
||||
public uint? CloneProp { get; set; }
|
||||
public float NextUse { get; set; }
|
||||
public float UseTime { 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)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace src.player.skills
|
|||
{
|
||||
private const Skills skillName = Skills.Illiterate;
|
||||
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()
|
||||
{
|
||||
|
|
@ -54,8 +54,12 @@ namespace src.player.skills
|
|||
public static string? GetRandomText(string? input)
|
||||
{
|
||||
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 =>
|
||||
{
|
||||
|
|
@ -63,15 +67,14 @@ namespace src.player.skills
|
|||
if (!char.IsLetter(c)) return c;
|
||||
|
||||
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 float MaximumFuel { get; set; } = maximumFuel;
|
||||
public float FuelConsumption { get; set; } = fuelConsumption;
|
||||
public float Refuelling { get; set; } = refuelling;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,8 +11,8 @@ namespace src.player.skills
|
|||
public class Impostor : ISkill
|
||||
{
|
||||
private const Skills skillName = Skills.Impostor;
|
||||
private static readonly string defaultCTModel = "characters/models/ctm_sas/ctm_sas.vmdl";
|
||||
private static readonly string defaultTModel = "characters/models/tm_phoenix/tm_phoenix.vmdl";
|
||||
private static readonly string defaultCTModel = "agents//models/ctm_sas/ctm_sas.vmdl";
|
||||
private static readonly string defaultTModel = "agents/models/tm_phoenix/tm_phoenix.vmdl";
|
||||
private static readonly ConcurrentDictionary<ulong, string> originalModels = [];
|
||||
|
||||
public static void LoadSkill()
|
||||
|
|
@ -63,6 +63,7 @@ namespace src.player.skills
|
|||
|
||||
Server.NextFrame(() =>
|
||||
{
|
||||
if (pawn == null || !pawn.IsValid) return;
|
||||
pawn.SetModel(model);
|
||||
|
||||
var originalRender = pawn.Render;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using CounterStrikeSharp.API.Modules.Utils;
|
|||
using src.utils;
|
||||
using System.Collections.Concurrent;
|
||||
using static src.jRandomSkills;
|
||||
using Timer = CounterStrikeSharp.API.Modules.Timers.Timer;
|
||||
|
||||
namespace src.player.skills
|
||||
{
|
||||
|
|
@ -12,8 +13,8 @@ namespace src.player.skills
|
|||
{
|
||||
private const Skills skillName = Skills.Jackal;
|
||||
private static readonly ConcurrentDictionary<ulong, byte> playersInAction = [];
|
||||
private static readonly ConcurrentDictionary<CCSPlayerController, CParticleSystem?> playersStep = [];
|
||||
private static readonly string particleName = "particles/ui/hud/ui_map_def_utility_trail.vpcf";
|
||||
private static readonly ConcurrentDictionary<uint, uint?> playersStep = [];
|
||||
private static readonly ConcurrentDictionary<ulong, Timer?> activeTimers = [];
|
||||
|
||||
public static void LoadSkill()
|
||||
{
|
||||
|
|
@ -23,9 +24,15 @@ namespace src.player.skills
|
|||
|
||||
public static void NewRound()
|
||||
{
|
||||
foreach (var step in playersStep.Values)
|
||||
if (step != null && step.IsValid)
|
||||
step.AcceptInput("Kill");
|
||||
foreach (var particleIndex in playersStep.Values)
|
||||
{
|
||||
if (particleIndex == null) continue;
|
||||
var particle = Utilities.GetEntityFromIndex<CParticleSystem>((int)particleIndex);
|
||||
|
||||
if (particle != null && particle.IsValid)
|
||||
particle.AcceptInput("Kill");
|
||||
}
|
||||
|
||||
playersStep.Clear();
|
||||
playersInAction.Clear();
|
||||
}
|
||||
|
|
@ -51,11 +58,15 @@ namespace src.player.skills
|
|||
|
||||
foreach (var param in playersStep)
|
||||
{
|
||||
var enemy = param.Key;
|
||||
var step = param.Value;
|
||||
if (step == null || !step.IsValid) continue;
|
||||
var enemyIndex = param.Key;
|
||||
var particleIndex = param.Value;
|
||||
|
||||
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 (!hasSkill || enemy.Team == player.Team)
|
||||
|
|
@ -69,13 +80,17 @@ namespace src.player.skills
|
|||
if (player == null) return;
|
||||
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 (!playersStep.ContainsKey(player)) return;
|
||||
if (!playersStep.ContainsKey(player.Index)) return;
|
||||
|
||||
CParticleSystem particle = Utilities.CreateEntityByName<CParticleSystem>("info_particle_system")!;
|
||||
if (particle == null) return;
|
||||
|
||||
particle.EffectName = particleName;
|
||||
particle.EffectName = SkillsInfo.GetValue<string>(skillName, "particleName");
|
||||
particle.StartActive = true;
|
||||
|
||||
particle.Teleport(playerPawn.AbsOrigin);
|
||||
|
|
@ -84,12 +99,18 @@ namespace src.player.skills
|
|||
particle.AcceptInput("SetParent", playerPawn, particle, "!activator");
|
||||
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)
|
||||
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);
|
||||
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))
|
||||
playersStep.TryAdd(_player, null);
|
||||
if (!playersStep.ContainsKey(_player.Index))
|
||||
playersStep.TryAdd(_player.Index, null);
|
||||
CreatePlayerTrail(_player);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DisableSkill(CCSPlayerController player)
|
||||
{
|
||||
playersStep.TryRemove(player, 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)
|
||||
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)
|
||||
{
|
||||
string ParticleName { get; set; } = particleName;
|
||||
public string ParticleName { get; set; } = particleName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,7 +10,7 @@ namespace src.player.skills
|
|||
public class Jammer : ISkill
|
||||
{
|
||||
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();
|
||||
|
||||
public static void LoadSkill()
|
||||
|
|
@ -22,8 +22,12 @@ namespace src.player.skills
|
|||
{
|
||||
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);
|
||||
}
|
||||
jammedPlayers.Clear();
|
||||
}
|
||||
foreach (var player in Utilities.GetPlayers())
|
||||
|
|
@ -67,7 +71,7 @@ namespace src.player.skills
|
|||
return;
|
||||
}
|
||||
|
||||
jammedPlayers.TryAdd(enemy, 0);
|
||||
jammedPlayers.TryAdd(enemy.Index, 0);
|
||||
SetCrosshair(enemy, false);
|
||||
playerInfo.SkillUsed = true;
|
||||
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)
|
||||
{
|
||||
SetCrosshair(player, true);
|
||||
jammedPlayers.TryRemove(player, out _);
|
||||
jammedPlayers.TryRemove(player.Index, out _);
|
||||
SkillUtils.CloseMenu(player);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Entities;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using src.utils;
|
||||
using System.Collections.Concurrent;
|
||||
|
|
@ -12,7 +13,7 @@ namespace src.player.skills
|
|||
public class Jester : ISkill
|
||||
{
|
||||
private const Skills skillName = Skills.Jester;
|
||||
private static readonly ConcurrentBag<JesterInfo> jesters = [];
|
||||
private static readonly ConcurrentDictionary<ulong, JesterInfo> jesters = [];
|
||||
|
||||
public static void LoadSkill()
|
||||
{
|
||||
|
|
@ -23,7 +24,7 @@ namespace src.player.skills
|
|||
{
|
||||
Server.NextWorldUpdate(() =>
|
||||
{
|
||||
foreach (var jester in jesters.ToList())
|
||||
foreach (var jester in jesters.Values)
|
||||
{
|
||||
if (jester.Timer != null)
|
||||
{
|
||||
|
|
@ -71,7 +72,8 @@ namespace src.player.skills
|
|||
var player = @event.Userid;
|
||||
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.Timer != null)
|
||||
|
|
@ -81,8 +83,7 @@ namespace src.player.skills
|
|||
}
|
||||
|
||||
jester.Timer = Instance.AddTimer(1, () => {
|
||||
if (player != null && player.IsValid)
|
||||
ChangeMode(player.SteamID, false);
|
||||
ChangeMode(steamId, false);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -91,7 +92,8 @@ namespace src.player.skills
|
|||
var player = @event.Userid;
|
||||
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.Timer != null)
|
||||
|
|
@ -102,7 +104,7 @@ namespace src.player.skills
|
|||
|
||||
jester.Timer = Instance.AddTimer(1, () => {
|
||||
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");
|
||||
float wait = (float)Instance.Random.NextDouble() * (maxTime - minTime) + minTime;
|
||||
|
||||
jesters.Add(new JesterInfo {
|
||||
SteamId = player.SteamID,
|
||||
ulong steamId = player.SteamID;
|
||||
|
||||
jesters.TryAdd(steamId, new JesterInfo {
|
||||
SteamId = steamId,
|
||||
Active = false,
|
||||
Timer = Instance.AddTimer(wait, () => ChangeMode(player.SteamID))
|
||||
Timer = Instance.AddTimer(wait, () => ChangeMode(steamId))
|
||||
});
|
||||
}
|
||||
|
||||
private static void ChangeMode(ulong steamId, bool? forceActive = null)
|
||||
{
|
||||
var player = Utilities.GetPlayerFromSteamId(steamId);
|
||||
if (player == null || !player.IsValid || !player.PawnIsAlive) return;
|
||||
|
||||
var jester = GetJesterInfo(player.SteamID);
|
||||
if (jester == null) return;
|
||||
if (!jesters.TryGetValue(steamId, out var jester)) return;
|
||||
|
||||
if (jester.Timer != null)
|
||||
{
|
||||
|
|
@ -154,6 +154,13 @@ namespace src.player.skills
|
|||
jester.Timer = null;
|
||||
}
|
||||
|
||||
var player = Utilities.GetPlayerFromSteamId(steamId);
|
||||
if (player == null || !player.IsValid || !player.PawnIsAlive)
|
||||
{
|
||||
jesters.TryRemove(steamId, out _);
|
||||
return;
|
||||
}
|
||||
|
||||
bool previousState = jester.Active;
|
||||
jester.Active = forceActive ?? !jester.Active;
|
||||
|
||||
|
|
@ -167,7 +174,7 @@ namespace src.player.skills
|
|||
var maxTime = SkillsInfo.GetValue<float>(skillName, "maxTime");
|
||||
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)
|
||||
|
|
@ -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>";
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ namespace src.player.skills
|
|||
public class JumpBan : ISkill
|
||||
{
|
||||
private const Skills skillName = Skills.JumpBan;
|
||||
public static readonly ConcurrentDictionary<CCSPlayerPawn, int> bannedPlayers = [];
|
||||
public static readonly ConcurrentDictionary<uint, int> bannedPlayers = [];
|
||||
|
||||
public static void LoadSkill()
|
||||
{
|
||||
|
|
@ -28,19 +28,25 @@ namespace src.player.skills
|
|||
{
|
||||
var player = @event.Userid;
|
||||
if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return;
|
||||
if (!bannedPlayers.TryGetValue(player.PlayerPawn.Value, out _)) return;
|
||||
bannedPlayers.AddOrUpdate(player.PlayerPawn.Value, Server.TickCount + 10, (k, v) => Server.TickCount + 10);
|
||||
if (!bannedPlayers.TryGetValue(player.Index, out _)) return;
|
||||
bannedPlayers.AddOrUpdate(player.Index, Server.TickCount + 10, (k, v) => Server.TickCount + 10);
|
||||
}
|
||||
|
||||
public static void OnTick()
|
||||
{
|
||||
foreach (var item in bannedPlayers)
|
||||
{
|
||||
var pawn = item.Key;
|
||||
var playerIndex = item.Key;
|
||||
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 (pawn != null && pawn.IsValid)
|
||||
pawn.AbsVelocity.Z = -100;
|
||||
pawn.AbsVelocity.Z = -100;
|
||||
}
|
||||
|
||||
if (Server.TickCount % 32 != 0) return;
|
||||
|
|
@ -52,7 +58,7 @@ namespace src.player.skills
|
|||
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();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -78,7 +84,7 @@ namespace src.player.skills
|
|||
return;
|
||||
}
|
||||
|
||||
bannedPlayers.AddOrUpdate(enemy.PlayerPawn.Value, 0, (k, v) => 0);
|
||||
bannedPlayers.AddOrUpdate(enemy.Index, 0, (k, v) => 0);
|
||||
playerInfo.SkillUsed = true;
|
||||
player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("jumpban_player_info", enemy.PlayerName));
|
||||
enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("jumpban_enemy_info"));
|
||||
|
|
@ -103,7 +109,7 @@ namespace src.player.skills
|
|||
public static void DisableSkill(CCSPlayerController player)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,14 +2,9 @@
|
|||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using CS2TraceRay.Class;
|
||||
using CS2TraceRay.Enum;
|
||||
using CS2TraceRay.Struct;
|
||||
using src.utils;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Drawing;
|
||||
using static src.jRandomSkills;
|
||||
using Vector = CounterStrikeSharp.API.Modules.Utils.Vector;
|
||||
|
||||
namespace src.player.skills
|
||||
{
|
||||
|
|
@ -22,8 +17,6 @@ namespace src.player.skills
|
|||
private static readonly ConcurrentDictionary<ulong, byte> playersInAction = [];
|
||||
private static readonly MemoryFunctionVoid<IntPtr, short> Shoot_Secondary = new(GameData.GetSignature("Shoot_Secondary"));
|
||||
|
||||
private static int i = 0;
|
||||
|
||||
public static void LoadSkill()
|
||||
{
|
||||
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)
|
||||
{
|
||||
var pawn = player!.PlayerPawn.Value;
|
||||
if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) return;
|
||||
|
||||
Vector eyePos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z);
|
||||
Vector endPos = eyePos + SkillUtils.GetForwardVector(pawn.EyeAngles) * SkillsInfo.GetValue<float>(skillName, "maxDistance");
|
||||
|
||||
ulong hitboxes = 0x2;
|
||||
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}");
|
||||
}
|
||||
|
||||
CEntityInstance entityInstance = new(trace.HitEntity);
|
||||
if (string.IsNullOrEmpty(entityInstance.DesignerName))
|
||||
if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null)
|
||||
return;
|
||||
|
||||
CBaseEntity entity = entityInstance.As<CBaseEntity>();
|
||||
if (!trace.HitPlayer(out CCSPlayerController? target) || target == null)
|
||||
var result = RayTrace.EyeTrace(player);
|
||||
if (result == null || !result.HasValue)
|
||||
return;
|
||||
|
||||
if (!result.Value.HitPlayer(out CCSPlayerController? target) || target == null)
|
||||
return;
|
||||
|
||||
if (target.Handle == player.Handle || result.Value.Distance() <= 70)
|
||||
return;
|
||||
|
||||
if (target.PlayerPawn.Value == null || !target.PlayerPawn.Value.IsValid)
|
||||
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;
|
||||
|
||||
target.PlayerPawn.Value.EmitSound("Player.DamageBody.Onlooker");
|
||||
|
|
|
|||
|
|
@ -1,13 +1,8 @@
|
|||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Entities.Constants;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using CS2TraceRay.Class;
|
||||
using CS2TraceRay.Enum;
|
||||
using CS2TraceRay.Struct;
|
||||
using src.utils;
|
||||
using System.Drawing;
|
||||
using static src.jRandomSkills;
|
||||
using Vector = CounterStrikeSharp.API.Modules.Utils.Vector;
|
||||
|
||||
namespace src.player.skills
|
||||
{
|
||||
|
|
@ -34,30 +29,11 @@ namespace src.player.skills
|
|||
var activeWeapon = pawn.WeaponServices.ActiveWeapon.Value;
|
||||
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);
|
||||
Vector endPos = eyePos + SkillUtils.GetForwardVector(pawn.EyeAngles) * SkillsInfo.GetValue<float>(skillName, "maxDistance");
|
||||
var result = RayTrace.EyeTrace(player);
|
||||
if (result == null || !result.HasValue)
|
||||
return;
|
||||
|
||||
ulong hitboxes = 0x2;
|
||||
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)
|
||||
if (!result.Value.HitPlayer(out CCSPlayerController? target) || target == null)
|
||||
return;
|
||||
|
||||
if (target.Handle == player.Handle) return;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ namespace src.player.skills
|
|||
public class Magnifier : ISkill
|
||||
{
|
||||
private const Skills skillName = Skills.Magnifier;
|
||||
private static readonly ConcurrentDictionary<CCSPlayerController, uint> playersFOV = [];
|
||||
private static readonly ConcurrentDictionary<uint, uint> playersFOV = [];
|
||||
|
||||
public static void LoadSkill()
|
||||
{
|
||||
|
|
@ -19,8 +19,13 @@ namespace src.player.skills
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
playersFOV.Clear();
|
||||
foreach (var player in Utilities.GetPlayers())
|
||||
SkillUtils.CloseMenu(player);
|
||||
|
|
@ -70,8 +75,8 @@ namespace src.player.skills
|
|||
return;
|
||||
}
|
||||
|
||||
if (!playersFOV.ContainsKey(enemy))
|
||||
playersFOV.TryAdd(enemy, enemy.DesiredFOV);
|
||||
if (!playersFOV.ContainsKey(enemy.Index))
|
||||
playersFOV.TryAdd(enemy.Index, enemy.DesiredFOV);
|
||||
enemy.DesiredFOV = SkillsInfo.GetValue<uint>(skillName, "customFOV");
|
||||
Utilities.SetStateChanged(enemy, "CBasePlayerController", "m_iDesiredFOV");
|
||||
|
||||
|
|
@ -98,12 +103,12 @@ namespace src.player.skills
|
|||
|
||||
public static void DisableSkill(CCSPlayerController player)
|
||||
{
|
||||
if (playersFOV.TryGetValue(player, out uint fov))
|
||||
if (playersFOV.TryGetValue(player.Index, out uint fov))
|
||||
{
|
||||
player.DesiredFOV = fov;
|
||||
Utilities.SetStateChanged(player, "CBasePlayerController", "m_iDesiredFOV");
|
||||
}
|
||||
playersFOV.TryRemove(player, out _);
|
||||
playersFOV.TryRemove(player.Index, out _);
|
||||
SkillUtils.CloseMenu(player);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace src.player.skills
|
|||
{
|
||||
private const Skills skillName = Skills.Ninja;
|
||||
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 static readonly object setLock = new();
|
||||
|
||||
|
|
@ -68,22 +68,28 @@ namespace src.player.skills
|
|||
if (targetInfo?.Skill == skillName) isObservingNinja = true;
|
||||
}
|
||||
|
||||
foreach (var _player in invisiblePlayers.Keys)
|
||||
if (player.SteamID != _player.SteamID && !isObservingNinja)
|
||||
foreach (var playerIndex in invisiblePlayers.Keys)
|
||||
{
|
||||
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;
|
||||
|
||||
var entity = Utilities.GetEntityFromIndex<CBaseEntity>((int)playerPawn.Index);
|
||||
if (entity == null || !entity.IsValid) continue;
|
||||
info.TransmitEntities.Remove(entity.Index);
|
||||
|
||||
var bombIndex = GetBombIndex(_player);
|
||||
var bombIndex = GetBombIndex(playerController);
|
||||
if (bombIndex == null) continue;
|
||||
var bombEntity = Utilities.GetEntityFromIndex<CBaseEntity>((int)bombIndex);
|
||||
if (bombEntity == null || !bombEntity.IsValid) continue;
|
||||
info.TransmitEntities.Remove(bombEntity.Index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -95,7 +101,7 @@ namespace src.player.skills
|
|||
if (playerInfo?.Skill == skillName)
|
||||
UpdateNinja(player);
|
||||
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)
|
||||
{
|
||||
SetPlayerVisibility(player, 0);
|
||||
invisiblePlayers.TryRemove(player, out _);
|
||||
invisiblePlayers.TryRemove(player.Index, out _);
|
||||
}
|
||||
|
||||
private static void UpdateNinja(CCSPlayerController? player)
|
||||
|
|
@ -136,14 +142,14 @@ namespace src.player.skills
|
|||
if (percentInvisibility == oldInvisibility)
|
||||
return;
|
||||
|
||||
invisibilityChanged.TryAdd(player.Handle, percentInvisibility);
|
||||
invisibilityChanged.AddOrUpdate(player.Handle, percentInvisibility, (_, _) => percentInvisibility);
|
||||
|
||||
if (percentInvisibility > .9)
|
||||
invisiblePlayers.TryAdd(player, 0);
|
||||
invisiblePlayers.TryAdd(player.Index, 0);
|
||||
else
|
||||
{
|
||||
SetPlayerVisibility(player, percentInvisibility);
|
||||
invisiblePlayers.TryRemove(player, out _);
|
||||
invisiblePlayers.TryRemove(player.Index, out _);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -162,7 +168,7 @@ namespace src.player.skills
|
|||
{
|
||||
var player = @event.Userid;
|
||||
if (player == null || !player.IsValid) return;
|
||||
if (!invisiblePlayers.ContainsKey(player)) return;
|
||||
if (!invisiblePlayers.ContainsKey(player.Index)) return;
|
||||
|
||||
var playerPawn = player.PlayerPawn.Value;
|
||||
if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return;
|
||||
|
|
|
|||
|
|
@ -41,8 +41,14 @@ namespace src.player.skills
|
|||
{
|
||||
var pawn = player.PlayerPawn.Value;
|
||||
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.CsViewPunchAngleTickRatio = 0f;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Entities;
|
||||
using CounterStrikeSharp.API.Modules.Memory;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using CS2TraceRay.Class;
|
||||
using CS2TraceRay.Struct;
|
||||
using src.utils;
|
||||
using System.Collections.Concurrent;
|
||||
using static src.jRandomSkills;
|
||||
|
|
@ -93,7 +92,9 @@ namespace src.player.skills
|
|||
var playerPawn = player.PlayerPawn.Value;
|
||||
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)
|
||||
{
|
||||
|
|
@ -109,11 +110,18 @@ namespace src.player.skills
|
|||
skillInfo.IsFlying = true;
|
||||
skillInfo.Cooldown = DateTime.Now;
|
||||
skillInfo.LastPosition = playerPawn.AbsOrigin == null ? null : new Vector(playerPawn.AbsOrigin.X, playerPawn.AbsOrigin.Y, playerPawn.AbsOrigin.Z);
|
||||
|
||||
SetNoclip(player, true);
|
||||
skillInfo.Timer?.Kill();
|
||||
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
|
@ -174,54 +182,39 @@ namespace src.player.skills
|
|||
|
||||
ulong mask = playerPawn.Collision.CollisionAttribute.InteractsWith;
|
||||
ulong contents = playerPawn.Collision.CollisionGroup;
|
||||
|
||||
bool hasGround = false;
|
||||
Vector stuckVector = new(currentPos.X, currentPos.Y, currentPos.Z);
|
||||
|
||||
foreach (Vector targetPos in checkOffsets)
|
||||
{
|
||||
Vector start = new(targetPos.X, targetPos.Y, targetPos.Z + 70);
|
||||
Vector end = new(targetPos.X, targetPos.Y, targetPos.Z - 1000);
|
||||
|
||||
CGameTrace groundTrace = TraceRay.TraceShape(start, end, mask, contents, player);
|
||||
if (!groundTrace.DidHit()) continue;
|
||||
var groundResult = RayTrace.TraceShape(player, start, end, mask, contents);
|
||||
if (!groundResult.HasValue || !groundResult.Value.DidHit) continue;
|
||||
|
||||
hasGround = true;
|
||||
Vector newPos =
|
||||
groundTrace.EndPos.Z > targetPos.Z
|
||||
? new(groundTrace.EndPos.X, groundTrace.EndPos.Y, groundTrace.EndPos.Z)
|
||||
groundResult.Value.EndPos.Z > targetPos.Z
|
||||
? new(groundResult.Value.EndPos.X, groundResult.Value.EndPos.Y, groundResult.Value.EndPos.Z)
|
||||
: targetPos;
|
||||
|
||||
if (IsPositionSafe(newPos, player))
|
||||
hasGround = true;
|
||||
stuckVector = newPos;
|
||||
|
||||
var result = RayTrace.TraceHullShape(
|
||||
targetPos,
|
||||
targetPos,
|
||||
player
|
||||
);
|
||||
|
||||
if (result.HasValue && !result.Value.DidHit)
|
||||
return newPos;
|
||||
}
|
||||
|
||||
if (hasGround)
|
||||
skillInfo.Cooldown = DateTime.Now.AddSeconds(-SkillsInfo.GetValue<float>(skillName, "cooldown") + SkillsInfo.GetValue<float>(skillName, "cooldownWhenStuck"));
|
||||
return hasGround ? currentPos : 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;
|
||||
return hasGround ? stuckVector : null;
|
||||
}
|
||||
|
||||
public class PlayerSkillInfo
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Entities;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using src.utils;
|
||||
using static src.jRandomSkills;
|
||||
|
|
@ -29,7 +30,15 @@ namespace src.player.skills
|
|||
lock (setLock)
|
||||
{
|
||||
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"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,10 @@ namespace src.player.skills
|
|||
|
||||
var plantedBomb = Utilities.FindAllEntitiesByDesignerName<CPlantedC4>("planted_c4").FirstOrDefault();
|
||||
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))
|
||||
p.PrintToCenterAlert(p.GetTranslation("bombplanted", SkillsInfo.GetValue<int>(skillName, "extraC4BlowTime")));
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ namespace src.player.skills
|
|||
public class Poison : ISkill
|
||||
{
|
||||
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();
|
||||
|
||||
public static void LoadSkill()
|
||||
|
|
@ -28,10 +28,14 @@ namespace src.player.skills
|
|||
{
|
||||
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;
|
||||
if (pawn == null || !pawn.IsValid) continue;
|
||||
|
||||
if (pawn.Health <= SkillsInfo.GetValue<int>(skillName, "MinHealth")) continue;
|
||||
SkillUtils.TakeHealth(pawn, SkillsInfo.GetValue<int>(skillName, "Damage"));
|
||||
}
|
||||
|
|
@ -72,7 +76,7 @@ namespace src.player.skills
|
|||
return;
|
||||
}
|
||||
|
||||
poisonedPlayers.TryAdd(enemy, 0);
|
||||
poisonedPlayers.TryAdd(enemy.Index, 0);
|
||||
playerInfo.SkillUsed = true;
|
||||
player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("poison_player_info", enemy.PlayerName));
|
||||
enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("poison_enemy_info"));
|
||||
|
|
@ -96,7 +100,7 @@ namespace src.player.skills
|
|||
|
||||
public static void DisableSkill(CCSPlayerController player)
|
||||
{
|
||||
poisonedPlayers.TryRemove(player, out _);
|
||||
poisonedPlayers.TryRemove(player.Index, out _);
|
||||
SkillUtils.CloseMenu(player);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,14 +4,13 @@ using CounterStrikeSharp.API.Modules.Utils;
|
|||
using static src.jRandomSkills;
|
||||
using System.Collections.Concurrent;
|
||||
using src.utils;
|
||||
using CounterStrikeSharp.API.Modules.Entities.Constants;
|
||||
|
||||
namespace src.player.skills
|
||||
{
|
||||
public class PsychicDefusing : ISkill
|
||||
{
|
||||
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 readonly float tickRate = 64f;
|
||||
private static readonly object setLock = new();
|
||||
|
|
@ -35,12 +34,9 @@ namespace src.player.skills
|
|||
var player = @event.Userid;
|
||||
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);
|
||||
if (playerInfo?.Skill == skillName)
|
||||
SkillPlayerInfo.TryRemove(pawn, out _);
|
||||
SkillPlayerInfo.TryRemove(player.Index, out _);
|
||||
}
|
||||
|
||||
public static void BombPlanted(EventBombPlanted _)
|
||||
|
|
@ -55,14 +51,14 @@ namespace src.player.skills
|
|||
if (bombLocation == null) return;
|
||||
foreach (var skillInfo in SkillPlayerInfo)
|
||||
{
|
||||
var pawn = skillInfo.Key;
|
||||
var playerIndex = skillInfo.Key;
|
||||
var info = skillInfo.Value;
|
||||
|
||||
var playerController = pawn.Controller.Value;
|
||||
if (playerController == null || !pawn.Controller.IsValid) return;
|
||||
var player = Utilities.GetPlayerFromIndex((int)playerIndex);
|
||||
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"))
|
||||
{
|
||||
|
|
@ -97,7 +93,8 @@ namespace src.player.skills
|
|||
{
|
||||
var pawn = player.PlayerPawn.Value;
|
||||
if (pawn == null || !pawn.IsValid) return;
|
||||
SkillPlayerInfo.TryAdd(pawn, new PlayerSkillInfo
|
||||
|
||||
SkillPlayerInfo.TryAdd(player.Index, new PlayerSkillInfo
|
||||
{
|
||||
SteamID = player.SteamID,
|
||||
Defusing = false,
|
||||
|
|
@ -108,9 +105,7 @@ namespace src.player.skills
|
|||
public static void DisableSkill(CCSPlayerController player)
|
||||
{
|
||||
SkillUtils.ResetPrintHTML(player);
|
||||
var pawn = player.PlayerPawn.Value;
|
||||
if (pawn == null || !pawn.IsValid) return;
|
||||
SkillPlayerInfo.TryRemove(pawn, out _);
|
||||
SkillPlayerInfo.TryRemove(player.Index, out _);
|
||||
}
|
||||
|
||||
private static void UpdateHUD(CCSPlayerController player, PlayerSkillInfo skillInfo)
|
||||
|
|
|
|||
|
|
@ -44,16 +44,16 @@ namespace src.player.skills
|
|||
|
||||
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;
|
||||
|
||||
var currentPosition = player.PlayerPawn.Value.AbsOrigin;
|
||||
var currentAngles = player.PlayerPawn.Value.EyeAngles;
|
||||
var currentPosition = playerPawn.AbsOrigin;
|
||||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -31,8 +31,13 @@ namespace src.player.skills
|
|||
var weapon = weaponServices.ActiveWeapon.Value;
|
||||
if (weapon == null || !weapon.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.CsViewPunchAngleTickRatio = 0f;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using src.utils;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Immutable;
|
||||
using static src.jRandomSkills;
|
||||
using System.Collections.Concurrent;
|
||||
using src.utils;
|
||||
|
||||
namespace src.player.skills
|
||||
{
|
||||
|
|
@ -113,7 +113,7 @@ namespace src.player.skills
|
|||
|
||||
ConcurrentBag<string> weaponList = [.. pistols.Concat(rifles).Where(w => !playerWeapons.Contains(w))];
|
||||
|
||||
if (weaponList.Count == 0)
|
||||
if (weaponList.IsEmpty)
|
||||
return;
|
||||
|
||||
string weapon = weaponList.ToArray()[Instance.Random.Next(weaponList.Count)];
|
||||
|
|
@ -131,8 +131,12 @@ namespace src.player.skills
|
|||
}
|
||||
}
|
||||
|
||||
ulong steamId = player.SteamID;
|
||||
Instance.AddTimer(.1f, () =>
|
||||
{
|
||||
var player = Utilities.GetPlayerFromSteamId(steamId);
|
||||
if (player == null || !player.IsValid) return;
|
||||
|
||||
player.GiveNamedItem(weapon);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,18 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using src.utils;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Drawing;
|
||||
using static src.jRandomSkills;
|
||||
using System.Collections.Concurrent;
|
||||
using src.utils;
|
||||
|
||||
namespace src.player.skills
|
||||
{
|
||||
public class ReZombie : ISkill
|
||||
{
|
||||
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();
|
||||
|
||||
public static void LoadSkill()
|
||||
|
|
@ -21,14 +22,27 @@ namespace src.player.skills
|
|||
|
||||
public static void EnableSkill(CCSPlayerController player)
|
||||
{
|
||||
zombies.TryRemove(player, out _);
|
||||
zombies.TryRemove(player.Index, out _);
|
||||
}
|
||||
|
||||
public static void DisableSkill(CCSPlayerController player)
|
||||
{
|
||||
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);
|
||||
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)
|
||||
|
|
@ -36,46 +50,88 @@ namespace src.player.skills
|
|||
var player = @event.Userid;
|
||||
var weapon = @event.Item;
|
||||
if (player == null || !player.IsValid) return;
|
||||
if (!zombies.ContainsKey(player) || weapon == "c4") return;
|
||||
if (!zombies.ContainsKey(player.Index) || weapon == "c4") return;
|
||||
player.ExecuteClientCommand("slot3");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
zombies.Clear();
|
||||
}
|
||||
|
||||
public static void PlayerDeath(EventPlayerDeath @event)
|
||||
{
|
||||
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);
|
||||
if (playerInfo?.Skill != skillName) return;
|
||||
|
||||
var pawn = player.PlayerPawn.Value;
|
||||
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();
|
||||
|
||||
Instance.AddTimer(.2f, () => {
|
||||
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");
|
||||
|
||||
player.Respawn();
|
||||
zombies.TryAdd(player, 0);
|
||||
zombies.TryAdd(player.Index, 0);
|
||||
|
||||
SetPlayerColor(pawn, false);
|
||||
SkillUtils.AddHealth(pawn, zombieHealth - 100, zombieHealth);
|
||||
pawn.Teleport(deadPosition, deadRotation);
|
||||
|
||||
pawn.Teleport(deadPosition);
|
||||
pawn.Look(angle);
|
||||
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)
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using CounterStrikeSharp.API.Modules.Utils;
|
|||
using static src.jRandomSkills;
|
||||
using System.Collections.Concurrent;
|
||||
using src.utils;
|
||||
using CounterStrikeSharp.API.Modules.Memory;
|
||||
|
||||
namespace src.player.skills
|
||||
{
|
||||
|
|
@ -102,12 +103,12 @@ namespace src.player.skills
|
|||
private static void CreateReplica(CCSPlayerController player)
|
||||
{
|
||||
var playerPawn = player.PlayerPawn.Value;
|
||||
var replica = Utilities.CreateEntityByName<CDynamicProp>("prop_dynamic_override");
|
||||
if (replica == null || playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null || playerPawn.AbsRotation == null)
|
||||
if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null || playerPawn.AbsRotation == null)
|
||||
return;
|
||||
|
||||
float distance = 40;
|
||||
Vector pos = playerPawn.AbsOrigin + SkillUtils.GetForwardVector(playerPawn.AbsRotation) * distance;
|
||||
var replica = Utilities.CreateEntityByName<CDynamicProp>("prop_dynamic_override");
|
||||
if (replica == null || !replica.IsValid)
|
||||
return;
|
||||
|
||||
replica.Flags = playerPawn.Flags;
|
||||
replica.Flags |= (uint)Flags_t.FL_DUCKING;
|
||||
|
|
@ -116,12 +117,13 @@ namespace src.player.skills
|
|||
replica.SetModel(playerPawn!.CBodyComponent!.SceneNode!.GetSkeletonInstance().ModelState.ModelName);
|
||||
replica.Entity!.Name = replica.Globalname = $"Replica_{Server.TickCount}_{(player.Team == CsTeam.CounterTerrorist ? "CT" : "TT")}";
|
||||
|
||||
replica.UseAnimGraph = false;
|
||||
string animName = "idle_for_turns_stand_pistol";
|
||||
if (((PlayerFlags)playerPawn.Flags).HasFlag(PlayerFlags.FL_DUCKING))
|
||||
animName = "idle_for_turns_crouch_pistol";
|
||||
replica.UseAnimGraph = true;
|
||||
replica.AnimGraphUpdateEnabled = true;
|
||||
bool isDucking = ((PlayerFlags)playerPawn.Flags).HasFlag(PlayerFlags.FL_DUCKING);
|
||||
|
||||
float distance = 40;
|
||||
Vector pos = playerPawn.AbsOrigin + SkillUtils.GetForwardVector(playerPawn.AbsRotation) * distance;
|
||||
|
||||
replica.AcceptInput("SetAnimation", value: animName);
|
||||
replica.Teleport(pos, playerPawn.AbsRotation, null);
|
||||
replica.DispatchSpawn();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ namespace src.player.skills
|
|||
public class Rubber: ISkill
|
||||
{
|
||||
private const Skills skillName = Skills.Rubber;
|
||||
private static readonly ConcurrentDictionary<CCSPlayerPawn, float> playersToSlow = [];
|
||||
private static readonly ConcurrentDictionary<uint, float> playersToSlow = [];
|
||||
|
||||
public static void LoadSkill()
|
||||
{
|
||||
|
|
@ -35,25 +35,33 @@ namespace src.player.skills
|
|||
|
||||
var rubberTime = SkillsInfo.GetValue<float>(skillName, "slownessTime");
|
||||
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()
|
||||
{
|
||||
foreach(var item in playersToSlow)
|
||||
{
|
||||
var pawn = item.Key;
|
||||
var playerIndex = item.Key;
|
||||
var time = item.Value;
|
||||
|
||||
var player = Utilities.GetPlayerFromIndex((int)playerIndex);
|
||||
if (player == null || !player.IsValid) continue;
|
||||
|
||||
if (time >= Server.TickCount)
|
||||
ChangeVelocity(pawn);
|
||||
ChangeVelocity(player);
|
||||
else
|
||||
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;
|
||||
|
||||
pawn.VelocityModifier = SkillsInfo.GetValue<float>(skillName, "slownessModifier");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,10 @@ namespace src.player.skills
|
|||
{
|
||||
var plantedBomb = Utilities.FindAllEntitiesByDesignerName<CPlantedC4>("planted_c4").FirstOrDefault();
|
||||
if (plantedBomb != null)
|
||||
Server.NextFrame(() => plantedBomb.DefuseCountDown = 0);
|
||||
Server.NextFrame(() => {
|
||||
if (plantedBomb != null && plantedBomb.IsValid)
|
||||
plantedBomb.DefuseCountDown = 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ namespace src.player.skills
|
|||
|
||||
var spawnpoint = SkillUtils.GetSpawnPointVector(victim);
|
||||
if (spawnpoint == null) return;
|
||||
victimPawn.Teleport(spawnpoint, victimPawn.AbsRotation, null);
|
||||
victimPawn.Teleport(spawnpoint, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using CS2TraceRay.Class;
|
||||
using CS2TraceRay.Struct;
|
||||
using static src.jRandomSkills;
|
||||
using Vector = CounterStrikeSharp.API.Modules.Utils.Vector;
|
||||
using System.Collections.Concurrent;
|
||||
|
|
@ -13,7 +11,7 @@ namespace src.player.skills
|
|||
public class Shade : ISkill
|
||||
{
|
||||
private const Skills skillName = Skills.Shade;
|
||||
private static readonly ConcurrentDictionary<CCSPlayerController, float> noSpace = [];
|
||||
private static readonly ConcurrentDictionary<uint, float> noSpace = [];
|
||||
|
||||
public static void LoadSkill()
|
||||
{
|
||||
|
|
@ -44,25 +42,32 @@ namespace src.player.skills
|
|||
{
|
||||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
|
||||
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");
|
||||
playerInfo.SkillChance = 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");
|
||||
}
|
||||
|
||||
public static void DisableSkill(CCSPlayerController player)
|
||||
{
|
||||
noSpace.TryRemove(player, out _);
|
||||
noSpace.TryRemove(player.Index, out _);
|
||||
SkillUtils.ResetPrintHTML(player);
|
||||
}
|
||||
|
||||
public static void OnTick()
|
||||
{
|
||||
foreach (var item in noSpace)
|
||||
if (item.Value >= Server.TickCount)
|
||||
UpdateHUD(item.Key);
|
||||
foreach (var (playerIndex, time) in noSpace)
|
||||
{
|
||||
var player = Utilities.GetPlayerFromIndex((int)playerIndex);
|
||||
if (player == null || !player.IsValid) continue;
|
||||
|
||||
if (time >= Server.TickCount)
|
||||
UpdateHUD(player);
|
||||
else
|
||||
SkillUtils.ResetPrintHTML(item.Key);
|
||||
SkillUtils.ResetPrintHTML(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>";
|
||||
}
|
||||
|
||||
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;
|
||||
if (pawn == null || !pawn.IsValid) return false;
|
||||
var attackerPawn = attacker.PlayerPawn.Value;
|
||||
if (attackerPawn == null || !attackerPawn.IsValid) return false;
|
||||
|
||||
Vector s = startPos + new Vector(0, 0, pawn.ViewOffset.Z / 2);
|
||||
Vector e = endPos + new Vector(0, 0, pawn.ViewOffset.Z / 2);
|
||||
var victimPawn = attacker.PlayerPawn.Value;
|
||||
if (victimPawn == null || !victimPawn.IsValid) return false;
|
||||
|
||||
ulong mask = pawn.Collision.CollisionAttribute.InteractsWith;
|
||||
ulong contents = pawn.Collision.CollisionGroup;
|
||||
CGameTrace trace = TraceRay.TraceShape(startPos, endPos, mask, contents, player);
|
||||
var result = RayTrace.TraceHullShape(
|
||||
startPos,
|
||||
endPos,
|
||||
victim,
|
||||
attackerPawn.Collision.Mins,
|
||||
attackerPawn.Collision.Maxs,
|
||||
null,
|
||||
null,
|
||||
angle
|
||||
);
|
||||
|
||||
if (trace.DidHit()) return false;
|
||||
return IsPositionSafe(player, endPos);
|
||||
}
|
||||
if (!result.HasValue)
|
||||
return false;
|
||||
|
||||
private static bool IsPositionSafe(CCSPlayerController player, Vector pos)
|
||||
{
|
||||
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;
|
||||
return !result.Value.DidHit;
|
||||
}
|
||||
|
||||
private static void TeleportAttackerBehindVictim(CCSPlayerController attacker, CCSPlayerController victim)
|
||||
|
|
@ -133,7 +122,7 @@ namespace src.player.skills
|
|||
Vector direction = SkillUtils.GetForwardVector(targetAngle);
|
||||
Vector targetPos = victimPos - (direction * distance);
|
||||
|
||||
if (CheckTeleport(victim, victimPos, targetPos))
|
||||
if (CheckTeleport(attacker, victim, victimPos, targetPos, targetAngle))
|
||||
{
|
||||
attackerPawn.Teleport(targetPos, targetAngle, Vector.Zero);
|
||||
teleported = true;
|
||||
|
|
@ -142,7 +131,7 @@ namespace src.player.skills
|
|||
}
|
||||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -25,7 +25,10 @@ namespace src.player.skills
|
|||
|
||||
var plantedBomb = Utilities.FindAllEntitiesByDesignerName<CPlantedC4>("planted_c4").FirstOrDefault();
|
||||
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))
|
||||
p.PrintToCenterAlert(p.GetTranslation("bombplanted", SkillsInfo.GetValue<int>(skillName, "detonationTime")));
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Entities;
|
||||
using CounterStrikeSharp.API.Modules.Entities.Constants;
|
||||
using CounterStrikeSharp.API.Modules.Timers;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
|
|
@ -50,12 +51,16 @@ namespace src.player.skills
|
|||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
|
||||
if (playerInfo?.Skill != skillName) return;
|
||||
|
||||
ulong steamID = player.SteamID;
|
||||
|
||||
Vector pos = new(@event.X, @event.Y, @event.Z);
|
||||
float refillInterval = 15.5f;
|
||||
|
||||
Timer? smokeTimer = null;
|
||||
smokeTimer = Instance.AddTimer(refillInterval, () =>
|
||||
{
|
||||
var player = Utilities.GetPlayerFromSteamId(steamID);
|
||||
|
||||
if (player == null || !player.IsValid)
|
||||
{
|
||||
smokeTimer?.Kill();
|
||||
|
|
|
|||
|
|
@ -166,7 +166,10 @@ namespace src.player.skills
|
|||
}
|
||||
|
||||
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", ""));
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace src.player.skills
|
|||
public class Spectator : ISkill
|
||||
{
|
||||
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()
|
||||
{
|
||||
|
|
@ -20,9 +20,13 @@ namespace src.player.skills
|
|||
|
||||
public static void NewRound()
|
||||
{
|
||||
foreach (var camera in cameras)
|
||||
if (camera.Value.Item2 != null && camera.Value.Item2.IsValid)
|
||||
camera.Value.Item2.AcceptInput("Kill");
|
||||
foreach (var info in cameras)
|
||||
{
|
||||
var cam = Utilities.GetEntityFromIndex<CDynamicProp>((int)info.Value.Item2);
|
||||
if (cam != null && cam.IsValid)
|
||||
cam.AcceptInput("Kill");
|
||||
}
|
||||
|
||||
cameras.Clear();
|
||||
}
|
||||
|
||||
|
|
@ -54,10 +58,24 @@ namespace src.player.skills
|
|||
public static void OnTick()
|
||||
{
|
||||
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))
|
||||
ChangeCamera(player, true);
|
||||
}
|
||||
|
|
@ -70,10 +88,14 @@ namespace src.player.skills
|
|||
var pawn = player.PlayerPawn.Value;
|
||||
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;
|
||||
cameraInfo.Item2.AcceptInput("Kill");
|
||||
|
||||
var cam = Utilities.GetEntityFromIndex<CDynamicProp>((int)cameraInfo.Item2);
|
||||
if (cam != null && cam.IsValid)
|
||||
cam.AcceptInput("Kill");
|
||||
|
||||
if (!forceToDefault)
|
||||
newCameraRaw = CreateCamera(player);
|
||||
} else
|
||||
|
|
@ -109,22 +131,25 @@ namespace src.player.skills
|
|||
var pawn = enemy.PlayerPawn.Value;
|
||||
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;
|
||||
|
||||
Server.NextFrame(() =>
|
||||
{
|
||||
if (camera == null || !camera.IsValid) return;
|
||||
camera.SetModel("models/actors/ghost_speaker.vmdl");
|
||||
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.AcceptInput("SetParent", pawn, pawn, "!activator");
|
||||
});
|
||||
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -123,15 +123,18 @@ namespace src.player.skills
|
|||
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);
|
||||
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 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);
|
||||
|
||||
victimPawn.Teleport(attackerPosition, attackerAngles, attackerVelocity);
|
||||
attackerPawn.Teleport(victimPosition, victimAngles, victimVelocity);
|
||||
victimPawn.Teleport(attackerPosition, null, attackerVelocity);
|
||||
attackerPawn.Teleport(victimPosition, null, victimVelocity);
|
||||
|
||||
victimPawn.Look(attackerAngles);
|
||||
attackerPawn.Look(victimAngles);
|
||||
}
|
||||
|
||||
public class ZamianaMiejsc_PlayerInfo
|
||||
|
|
|
|||
|
|
@ -49,15 +49,18 @@ namespace src.player.skills
|
|||
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);
|
||||
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 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);
|
||||
|
||||
victimPawn.Teleport(attackerPosition, attackerAngles, attackerVelocity);
|
||||
attackerPawn.Teleport(victimPosition, victimAngles, victimVelocity);
|
||||
victimPawn.Teleport(attackerPosition, null, attackerVelocity);
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -120,10 +120,19 @@ namespace src.player.skills
|
|||
bool ctSkill = Event.counterterroristSkills.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))
|
||||
{
|
||||
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]);
|
||||
player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("thief_incorrect_skill", enemy.PlayerName));
|
||||
});
|
||||
|
|
@ -133,24 +142,42 @@ namespace src.player.skills
|
|||
SkillUtils.CloseMenu(player);
|
||||
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.SpecialSkill = skillName;
|
||||
|
||||
SkillUtils.CloseMenu(player);
|
||||
Instance.SkillAction(enemySkill.ToString(), "EnableSkill", [player]);
|
||||
|
||||
player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("thief_player_info", enemy.PlayerName));
|
||||
|
||||
if (SkillsInfo.GetValue<bool>(enemySkill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime())
|
||||
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;
|
||||
Instance?.SkillAction(enemySkill.ToString(), "EnableSkill", new[] { player });
|
||||
Instance?.SkillAction(enemySkill.ToString(), "EnableSkill", [player]);
|
||||
});
|
||||
else
|
||||
Instance?.SkillAction(enemySkill.ToString(), "EnableSkill", new[] { player });
|
||||
Instance?.SkillAction(enemySkill.ToString(), "EnableSkill", [player]);
|
||||
});
|
||||
|
||||
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]);
|
||||
|
||||
enemyInfo.SpecialSkill = enemySkill;
|
||||
enemyInfo.Skill = Skills.None;
|
||||
enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("thief_enemy_info"));
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ namespace src.player.skills
|
|||
public class ThirdEye : ISkill
|
||||
{
|
||||
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();
|
||||
|
||||
public static void LoadSkill()
|
||||
|
|
@ -20,9 +20,13 @@ namespace src.player.skills
|
|||
|
||||
public static void NewRound()
|
||||
{
|
||||
foreach (var camera in cameras)
|
||||
if (camera.Value.Item2 != null && camera.Value.Item2.IsValid)
|
||||
camera.Value.Item2.AcceptInput("Kill");
|
||||
foreach (var cameraIndex in cameras.Values)
|
||||
{
|
||||
var camera = Utilities.GetEntityFromIndex<CDynamicProp>((int)cameraIndex.Item2);
|
||||
if (camera != null && camera.IsValid)
|
||||
camera.AcceptInput("Kill");
|
||||
}
|
||||
|
||||
lock (setLock)
|
||||
cameras.Clear();
|
||||
}
|
||||
|
|
@ -42,7 +46,7 @@ namespace src.player.skills
|
|||
public static void OnTick()
|
||||
{
|
||||
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;
|
||||
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");
|
||||
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;
|
||||
cam.Teleport(pos, pawn.V_angle);
|
||||
}
|
||||
|
|
@ -66,10 +70,14 @@ namespace src.player.skills
|
|||
uint orginalCameraRaw;
|
||||
uint newCameraRaw;
|
||||
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;
|
||||
newCameraRaw = cameraInfo.Item2.EntityHandle.Raw;
|
||||
|
||||
var cam = Utilities.GetEntityFromIndex<CDynamicProp>((int)cameraInfo.Item2);
|
||||
if (cam == null || !cam.IsValid) return;
|
||||
|
||||
newCameraRaw = cam.EntityHandle.Raw;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -100,13 +108,14 @@ namespace src.player.skills
|
|||
|
||||
Server.NextFrame(() =>
|
||||
{
|
||||
if (camera == null || !camera.IsValid) return;
|
||||
camera.SetModel("models/actors/ghost_speaker.vmdl");
|
||||
camera.Render = Color.FromArgb(0, 255, 255, 255);
|
||||
camera.Teleport(pawn!.AbsOrigin, pawn.EyeAngles);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ namespace src.player.skills
|
|||
if (trigger != null && trigger.IsValid)
|
||||
Server.NextFrame(() =>
|
||||
{
|
||||
if (trigger.IsValid)
|
||||
if (trigger != null && trigger.IsValid)
|
||||
trigger.AcceptInput("Kill");
|
||||
});
|
||||
}
|
||||
|
|
@ -140,7 +140,7 @@ namespace src.player.skills
|
|||
if (glow != null && glow.IsValid)
|
||||
Server.NextFrame(() =>
|
||||
{
|
||||
if (glow.IsValid)
|
||||
if (glow != null && glow.IsValid)
|
||||
glow.AcceptInput("Kill");
|
||||
});
|
||||
}
|
||||
|
|
@ -151,7 +151,7 @@ namespace src.player.skills
|
|||
if (relay != null && relay.IsValid)
|
||||
Server.NextFrame(() =>
|
||||
{
|
||||
if (relay.IsValid)
|
||||
if (relay != null && relay.IsValid)
|
||||
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;
|
||||
|
||||
player.DropActiveWeapon();
|
||||
Server.NextFrame(() => ThrowKnife(player, weapon) );
|
||||
Server.NextFrame(() => {
|
||||
if (player == null || !player.IsValid) return;
|
||||
if (weapon == null || !weapon.IsValid) return;
|
||||
ThrowKnife(player, weapon);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ namespace src.player.skills
|
|||
|
||||
Server.NextFrame(() =>
|
||||
{
|
||||
if (entity == null || !entity.IsValid) return;
|
||||
var smoke = entity.As<CSmokeGrenadeProjectile>();
|
||||
smoke.SmokeColor.X = 255;
|
||||
smoke.SmokeColor.Y = 0;
|
||||
|
|
|
|||
|
|
@ -133,6 +133,8 @@ namespace src.player.skills
|
|||
|
||||
Server.NextFrame(() =>
|
||||
{
|
||||
if (player == null || !player.IsValid) return;
|
||||
if (enemy == null || !enemy.IsValid) return;
|
||||
player.RemoveWeapons();
|
||||
enemy.RemoveWeapons();
|
||||
GiveWeapons(player, enemyWeapon, playerWeapon.Contains("weapon_c4"));
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ namespace src.utils
|
|||
public bool DisplayAlwaysDescription { get; set; }
|
||||
public bool DisableSpectateHUD { get; set; }
|
||||
public bool FlashingHtmlHudFix { get; set; }
|
||||
public bool CS2TraceRayDebug { get; set; }
|
||||
public bool TraceRayBeam { get; set; }
|
||||
public string DisableHUDOnDeathPermission { get; set; }
|
||||
public bool DisableSkillsOnRoundEnd { get; set; }
|
||||
public LanguageSystem LanguageSystem { get; set; }
|
||||
|
|
@ -112,7 +112,7 @@ namespace src.utils
|
|||
SkillDescriptionDuration = 7;
|
||||
DisplayAlwaysDescription = false;
|
||||
FlashingHtmlHudFix = true;
|
||||
CS2TraceRayDebug = false;
|
||||
TraceRayBeam = false;
|
||||
DisableSpectateHUD = false;
|
||||
DisableHUDOnDeathPermission = "@jRandomSkills/death";
|
||||
DisableSkillsOnRoundEnd = false;
|
||||
|
|
@ -180,6 +180,7 @@ namespace src.utils
|
|||
SetStaticSkillCommand = new NormalCommand("ustawstatycznyskill, ustaw_statyczny_skill, setstaticskill, set_static_skill", "@jRandomSkills/admin"),
|
||||
ChangeLanguageCommand = new NormalCommand("lang, language, changelang, change_lang, jezyk, język", ""),
|
||||
ReloadCommand = new NormalCommand("reload, refresh", "@jRandomSkills/admin"),
|
||||
NextCommand = new NormalCommand("next_skill", "@jRandomSkills/admin"),
|
||||
};
|
||||
|
||||
VotingCommands = new VotingCommands
|
||||
|
|
@ -259,6 +260,7 @@ namespace src.utils
|
|||
public required NormalCommand SetStaticSkillCommand { get; set; }
|
||||
public required NormalCommand ChangeLanguageCommand { 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)
|
||||
|
|
|
|||
36
jRandomSkills - SRC Files/src/utils/CustomTraceResult.cs
Normal file
36
jRandomSkills - SRC Files/src/utils/CustomTraceResult.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
299
jRandomSkills - SRC Files/src/utils/RayTrace.cs
Normal file
299
jRandomSkills - SRC Files/src/utils/RayTrace.cs
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -165,7 +165,11 @@ namespace src.utils
|
|||
|
||||
skeleton.Scale = scale;
|
||||
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)
|
||||
|
|
@ -224,6 +228,7 @@ namespace src.utils
|
|||
if (pawn.Health <= 0)
|
||||
Server.NextFrame(() =>
|
||||
{
|
||||
if (pawn == null || !pawn.IsValid) return;
|
||||
pawn?.CommitSuicide(false, true);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
BIN
jRandomSkills - Server Files/gamedata.zip
Normal file
BIN
jRandomSkills - Server Files/gamedata.zip
Normal file
Binary file not shown.
|
|
@ -16,15 +16,22 @@
|
|||
"Shoot_Secondary": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "48 89 5C 24 ? 57 48 83 EC 20 44 0F BF C2",
|
||||
"linux": "55 48 89 E5 41 54 53 48 89 FB 66 83 FE 65"
|
||||
"windows": "48 89 5C 24 ? 57 48 83 EC 20 48 8B 01 48 8B F9 0F BF DA",
|
||||
"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": {
|
||||
"signatures": {
|
||||
"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",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
|
@ -13,7 +13,7 @@
|
|||
"DisplayAlwaysDescription": false,
|
||||
"DisableSpectateHUD": false,
|
||||
"FlashingHtmlHudFix": true,
|
||||
"CS2TraceRayDebug": false,
|
||||
"TraceRayBeam": false,
|
||||
"DisableHUDOnDeathPermission": "@jRandomSkills/death",
|
||||
"DisableSkillsOnRoundEnd": false,
|
||||
"LanguageSystem": {
|
||||
|
|
@ -130,6 +130,10 @@
|
|||
"ReloadCommand": {
|
||||
"Alias": "reload, refresh",
|
||||
"Permissions": "@jRandomSkills/admin"
|
||||
},
|
||||
"NextCommand": {
|
||||
"Alias": "next_skill",
|
||||
"Permissions": "@jRandomSkills/admin"
|
||||
}
|
||||
},
|
||||
"VotingCommands": {
|
||||
|
|
|
|||
|
|
@ -262,7 +262,7 @@
|
|||
"RequiredPermission": ""
|
||||
},
|
||||
{
|
||||
"ZombieHealth": 250,
|
||||
"ZombieHealth": 500,
|
||||
"NeedsTeammates": false,
|
||||
"DisableOnFreezeTime": false,
|
||||
"OnlyTeam": 0,
|
||||
|
|
@ -323,17 +323,6 @@
|
|||
"Name": "ReactiveArmor",
|
||||
"RequiredPermission": ""
|
||||
},
|
||||
{
|
||||
"Cooldown": 30.0,
|
||||
"Duration": 10.0,
|
||||
"NeedsTeammates": false,
|
||||
"DisableOnFreezeTime": true,
|
||||
"OnlyTeam": 0,
|
||||
"Color": "#d0d930",
|
||||
"Active": false,
|
||||
"Name": "RCMelon",
|
||||
"RequiredPermission": ""
|
||||
},
|
||||
{
|
||||
"Cooldown": 15.0,
|
||||
"NeedsTeammates": false,
|
||||
|
|
@ -706,6 +695,7 @@
|
|||
"RequiredPermission": ""
|
||||
},
|
||||
{
|
||||
"ParticleName": "particles/ui/hud/ui_map_def_utility_trail.vpcf",
|
||||
"NeedsTeammates": false,
|
||||
"DisableOnFreezeTime": false,
|
||||
"OnlyTeam": 0,
|
||||
|
|
@ -747,9 +737,6 @@
|
|||
"RequiredPermission": ""
|
||||
},
|
||||
{
|
||||
"MaximumFuel": 150.0,
|
||||
"FuelConsumption": 0.64,
|
||||
"Refuelling": 0.1,
|
||||
"NeedsTeammates": false,
|
||||
"DisableOnFreezeTime": true,
|
||||
"OnlyTeam": 0,
|
||||
|
|
@ -1307,7 +1294,6 @@
|
|||
{
|
||||
"Cooldown": 20.0,
|
||||
"Duration": 0.3,
|
||||
"Offset": 0.0,
|
||||
"NeedsTeammates": false,
|
||||
"DisableOnFreezeTime": true,
|
||||
"OnlyTeam": 0,
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue