diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1c9a181 --- /dev/null +++ b/.gitignore @@ -0,0 +1,242 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +[Xx]64/ +[Xx]86/ +[Bb]uild/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml + +# TODO: Un-comment the next line if you do not want to checkin +# your web deploy settings because they may include unencrypted +# passwords +#*.pubxml +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directory +AppPackages/ +BundleArtifacts/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# LightSwitch generated files +GeneratedArtifacts/ +ModelManifest.xml + +# Paket dependency manager +.paket/paket.exe + +# FAKE - F# Make +.fake/ diff --git a/CS2Retake.sln b/CS2Retake.sln new file mode 100644 index 0000000..9186ced --- /dev/null +++ b/CS2Retake.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33213.308 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CS2Retake", "CS2Retake\CS2Retake.csproj", "{3B202901-0697-40CE-AD55-FC18A891A1F3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3B202901-0697-40CE-AD55-FC18A891A1F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3B202901-0697-40CE-AD55-FC18A891A1F3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B202901-0697-40CE-AD55-FC18A891A1F3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3B202901-0697-40CE-AD55-FC18A891A1F3}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {CE98A4EE-5C9E-4FB8-99F9-4E5DF57D3DF7} + EndGlobalSection +EndGlobal diff --git a/CS2Retake/CS2Retake.cs b/CS2Retake/CS2Retake.cs new file mode 100644 index 0000000..22499b6 --- /dev/null +++ b/CS2Retake/CS2Retake.cs @@ -0,0 +1,105 @@ +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core.Attributes; +using CounterStrikeSharp.API.Core.Attributes.Registration; +using CounterStrikeSharp.API.Modules.Commands; +using CounterStrikeSharp.API.Modules.Entities; +using CounterStrikeSharp.API.Modules.Utils; +using CS2Retake.Entity; + +namespace CS2Retake +{ + public class CS2Retake : BasePlugin + { + public override string ModuleName => "CS2Retake"; + public override string ModuleVersion => "0.0.1"; + public override string ModuleAuthor => "LordFetznschaedl"; + public override string ModuleDescription => "Retake Plugin implementation for CS2"; + + private MapEntity _currentMap { get; set; } = null; + + + public override void Load(bool hotReload) + { + this.Log(PluginInfo()); + this.Log(this.ModuleDescription); + + this.RegisterEventHandler(OnPlayerSpawn); + + if(this._currentMap == null) + { + this._currentMap = new MapEntity(Server.MapName, this.ModuleDirectory); + } + + this.RegisterListener((mapName) => + { + this._currentMap = new MapEntity(mapName, this.ModuleDirectory); + }); + } + + [ConsoleCommand("css_retakeinfo", "This command prints the plugin information")] + public void OnCommandInfo(CCSPlayerController? player, CommandInfo command) + { + if (player == null) + { + Console.WriteLine("Command has been called by the server."); + return; + } + + player.PrintToChat(PluginInfo()); + player.PrintToConsole(PluginInfo()); + } + + [ConsoleCommand("css_retakewrite", "This command writes the spawns")] + public void OnCommandWrite(CCSPlayerController? player, CommandInfo command) + { + this._currentMap.WriteSpawns(); + } + + [GameEventHandler] + public HookResult OnPlayerSpawn(EventPlayerSpawn @event, GameEventInfo info) + { + return HookResult.Continue; + + if (@event == null) + { + return HookResult.Continue; + } + if(@event.Userid.IsValid) + { + return HookResult.Continue; + } + + + var spawnPoint = this._currentMap.GetRandomSpawn((CsTeam)@event.Userid.TeamNum); + + var absOrigin = @event.Userid.CBodyComponent!.SceneNode!.AbsOrigin; + absOrigin.X = 0; + absOrigin.Y = 0; + absOrigin.Z = 0; + + var absRotation = @event.Userid.CBodyComponent!.SceneNode!.AbsRotation; + absRotation.X = 0; + absRotation.Y = 0; + absRotation.Z = 0; + + //@event.Userid.Teleport(); + + this.Log(@event.Userid.TeamNum.ToString()); + + return HookResult.Continue; + } + + private string PluginInfo() + { + return $"Plugin: {ModuleName} - Version: {ModuleVersion}"; + } + + private void Log(string message) + { + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine(message); + Console.ResetColor(); + } + } +} \ No newline at end of file diff --git a/CS2Retake/CS2Retake.csproj b/CS2Retake/CS2Retake.csproj new file mode 100644 index 0000000..406eb10 --- /dev/null +++ b/CS2Retake/CS2Retake.csproj @@ -0,0 +1,15 @@ + + + + net7.0 + enable + enable + + + + + C:/Source/CS2Plugins/lib/counterstrikesharp-with-runtime/addons/counterstrikesharp/api/CounterStrikeSharp.API.dll + + + + diff --git a/CS2Retake/Entity/MapEntity.cs b/CS2Retake/Entity/MapEntity.cs new file mode 100644 index 0000000..99e1f6a --- /dev/null +++ b/CS2Retake/Entity/MapEntity.cs @@ -0,0 +1,83 @@ +using CounterStrikeSharp.API.Modules.Utils; +using CS2Retake.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace CS2Retake.Entity +{ + public class MapEntity + { + public string MapName { get; set; } + + public List _spawnPoints { get; set; } = new List(); + + private string _moduleDirectory { get; set; } + + + public MapEntity(string mapName, string moduleDirectoy) + { + this.MapName = mapName; + this._moduleDirectory = moduleDirectoy; + + this._spawnPoints.Add(new SpawnPointEntity(new Vector(1485.635986f, 1799.516846f, - 9.545544f), new QAngle(1.386139f, 134.525223f, 0.000000f), CsTeam.Terrorist, BombSiteEnum.A, SpawnTypeEnum.Normal)); + this._spawnPoints.Add(new SpawnPointEntity(new Vector(-439.763672f, 2293.371826f, - 119.998161f), new QAngle(3.124207f, - 18.375731f, 0.000000f), CsTeam.CounterTerrorist, BombSiteEnum.A, SpawnTypeEnum.Normal)); + } + + public SpawnPointEntity GetRandomSpawn(CsTeam team) + { + if(!this._spawnPoints.Any()) + { + this.ReadSpawns(); + } + + var spawnChoices = this._spawnPoints.Where(x => x.Team == team && !x.SpawnIsInUse).ToList(); + + if(!spawnChoices.Any()) + { + throw new Exception("No spawns are available"); + } + + var random = new Random(); + + + return spawnChoices.ElementAt(random.Next(spawnChoices.Count - 1)); + } + + public void ReadSpawns() + { + var jsonSpawnPoints = File.ReadAllText(this.GetPath()); + + if(string.IsNullOrEmpty(jsonSpawnPoints)) + { + return; + } + + this._spawnPoints = JsonSerializer.Deserialize>(jsonSpawnPoints) ?? new List(); + } + + public void WriteSpawns() + { + File.WriteAllText(this.GetPath(), JsonSerializer.Serialize(this._spawnPoints)); + } + + private string GetPath() + { + var path = Path.Join(this._moduleDirectory, $"spawns"); + + if(!Path.Exists(path)) + { + Directory.CreateDirectory(path); + } + + path = Path.Join(path, $"{this.MapName}.json"); + + return path; + } + } +} diff --git a/CS2Retake/Entity/SpawnPointEntity.cs b/CS2Retake/Entity/SpawnPointEntity.cs new file mode 100644 index 0000000..55dbf92 --- /dev/null +++ b/CS2Retake/Entity/SpawnPointEntity.cs @@ -0,0 +1,70 @@ +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Entities; +using CounterStrikeSharp.API.Modules.Memory; +using CounterStrikeSharp.API.Modules.Utils; +using CS2Retake.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +namespace CS2Retake.Entity +{ + public class SpawnPointEntity + { + public SpawnTypeEnum SpawnType { get; set; } = SpawnTypeEnum.Undefined; + public CsTeam Team { get; set; } = CsTeam.None; + public BombSiteEnum BombSite { get; set; } = BombSiteEnum.Undefined; + + + public float VectorX { get; set; } + public float VectorY { get; set; } + public float VectorZ { get; set; } + + public float QAngleX { get; set; } + public float QAngleY { get; set; } + public float QAngleZ { get; set; } + + [JsonIgnore] + public Vector Vector => new Vector(this.VectorX, this.VectorY, this.VectorZ); + [JsonIgnore] + public QAngle QAngle => new QAngle(this.QAngleX, this.QAngleY, this.QAngleZ); + + [JsonIgnore] + public bool SpawnIsInUse { get; set; } = false; + + + public SpawnPointEntity(Vector vector, QAngle qAngle, CsTeam team, BombSiteEnum bombSite, SpawnTypeEnum spawnType = SpawnTypeEnum.Normal) + { + this.VectorX = vector.X; + this.VectorY = vector.Y; + this.VectorZ = vector.Z; + + this.QAngleX = qAngle.X; + this.QAngleY = qAngle.Y; + this.QAngleZ = qAngle.Z; + + this.Team = team; + this.BombSite = bombSite; + this.SpawnType = spawnType; + } + + public SpawnPointEntity(float vectorX, float vectorY, float vectorZ, float qAngleX, float qAngleY, float qAngleZ, CsTeam team, BombSiteEnum bombSite, SpawnTypeEnum spawnType = SpawnTypeEnum.Normal) + { + this.VectorX = vectorX; + this.VectorY = vectorY; + this.VectorZ = vectorZ; + + this.QAngleX = qAngleX; + this.QAngleY = qAngleY; + this.QAngleZ = qAngleZ; + + this.Team = team; + this.BombSite = bombSite; + this.SpawnType = spawnType; + } + } +} diff --git a/CS2Retake/Utils/BombSiteEnum.cs b/CS2Retake/Utils/BombSiteEnum.cs new file mode 100644 index 0000000..b717da1 --- /dev/null +++ b/CS2Retake/Utils/BombSiteEnum.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CS2Retake.Utils +{ + public enum BombSiteEnum + { + Undefined = -1, + A = 0, + B = 1, + } +} diff --git a/CS2Retake/Utils/SpawnTypeEnum.cs b/CS2Retake/Utils/SpawnTypeEnum.cs new file mode 100644 index 0000000..73cd88f --- /dev/null +++ b/CS2Retake/Utils/SpawnTypeEnum.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CS2Retake.Utils +{ + public enum SpawnTypeEnum + { + Undefined = -1, + Normal = 0, + OnlyWithBomb = 1, + NeverWithBomb = 2, + } +}