Skip to content

Commit

Permalink
draft: spectators are planes
Browse files Browse the repository at this point in the history
  • Loading branch information
derkalle4 committed Nov 20, 2024
1 parent 349efc1 commit a375977
Show file tree
Hide file tree
Showing 5 changed files with 195 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/Cosmetics+Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public class MapConfig
{
[JsonPropertyName("enable_coloredsmokegrenades")] public bool EnableColoredSmokeGrenades { get; set; } = true;
[JsonPropertyName("enable_deathbeam")] public bool EnableDeathBeam { get; set; } = true;
[JsonPropertyName("enable_lighting")] public bool EnableLighting { get; set; } = true;
[JsonPropertyName("enable_specatormodel")] public bool EnableSpectatorModel { get; set; } = true;
}

public class PluginConfig : BasePluginConfig
Expand All @@ -18,6 +20,8 @@ public class PluginConfig : BasePluginConfig
[JsonPropertyName("enabled")] public bool Enabled { get; set; } = true;
[JsonPropertyName("enable_coloredsmokegrenades")] public bool EnableColoredSmokeGrenades { get; set; } = true;
[JsonPropertyName("enable_deathbeam")] public bool EnableDeathBeam { get; set; } = true;
[JsonPropertyName("enable_lighting")] public bool EnableLighting { get; set; } = true;
[JsonPropertyName("enable_specatormodel")] public bool EnableSpectatorModel { get; set; } = true;
// map configurations
[JsonPropertyName("maps")] public Dictionary<string, MapConfig> MapConfigs { get; set; } = new Dictionary<string, MapConfig>();
}
Expand Down
1 change: 1 addition & 0 deletions src/Cosmetics+Precache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public partial class Cosmetics : BasePlugin
{
private readonly List<string> _precacheModels = new List<string>
{
"models/vehicles/airplane_medium_01/airplane_medium_01_landed.vmdl"
};

private void OnServerPrecacheResources(ResourceManifest manifest)
Expand Down
97 changes: 97 additions & 0 deletions src/Cosmetics+SpectatorModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;

namespace Cosmetics
{
public partial class Cosmetics : BasePlugin
{
private Dictionary<CCSPlayerController, int> _spectatorModelPlayers = new();
private readonly string _spectatorModel = "models/vehicles/airplane_medium_01/airplane_medium_01_landed.vmdl";

private void InitializeSpectatorModel()
{
if (!Config.EnableSpectatorModel) return;
if (_currentMap == "") return;
var mapConfig = Config.MapConfigs[_currentMap];
if (!mapConfig.EnableSpectatorModel) return;
RegisterListener<Listeners.OnTick>(EventSpectatorModelOnTick);
}

private void ResetSpectatorModel()
{
RemoveListener<Listeners.OnTick>(EventSpectatorModelOnTick);
RemoveListener<Listeners.CheckTransmit>(EventSpectatorModelCheckTransmit);
}
private void EventSpectatorModelOnTick()
{
foreach (CCSPlayerController player in Utilities.GetPlayers())
{
try
{
// sanity checks
if (player == null
|| player.Pawn == null
|| player.Pawn.Value == null
|| !player.Pawn.IsValid) continue;
if (!_spectatorModelPlayers.ContainsKey(player) && player.Pawn.Value.LifeState == (byte)LifeState_t.LIFE_DEAD
&& player.Pawn.Value.ObserverServices != null
&& player.Pawn.Value.ObserverServices.ObserverMode == (byte)ObserverMode_t.OBS_MODE_ROAMING)
{
Console.WriteLine("Spawning spectator model for player: " + player.PlayerName);
if (_spectatorModelPlayers.Count == 0) RegisterListener<Listeners.CheckTransmit>(EventSpectatorModelCheckTransmit);
_spectatorModelPlayers.Add(player,
SpawnProp(
player,
_spectatorModel,
0.01f
));
}
else if (_spectatorModelPlayers.ContainsKey(player)
&& (player.Pawn.Value.LifeState != (byte)LifeState_t.LIFE_DEAD
|| (player.Pawn.Value.ObserverServices != null && player.Pawn.Value.ObserverServices.ObserverMode != (byte)ObserverMode_t.OBS_MODE_ROAMING)))
{
Console.WriteLine("Removing spectator model for player: " + player.PlayerName);
RemoveProp(
_spectatorModelPlayers[player],
true
);
_spectatorModelPlayers.Remove(player);
}
else if (_spectatorModelPlayers.ContainsKey(player) && player.Pawn.Value.LifeState == (byte)LifeState_t.LIFE_DEAD)
{
UpdateProp(
player,
_spectatorModelPlayers[player],
0,
0
);
}
}
catch (Exception e)
{
// log error
Console.WriteLine(Localizer["core.error"].Value.Replace("{error}", e.Message));
}
}
}

private void EventSpectatorModelCheckTransmit(CCheckTransmitInfoList infoList)
{
// remove listener if no players to save resources
if (_spectatorModelPlayers.Count() == 0)
{
RemoveListener<Listeners.CheckTransmit>(EventSpectatorModelCheckTransmit);
return;
}
// worker
foreach ((CCheckTransmitInfo info, CCSPlayerController? player) in infoList)
{
if (player == null) continue;
if (!_spectatorModelPlayers.ContainsKey(player)) continue;
var prop = Utilities.GetEntityFromIndex<CDynamicProp>(_spectatorModelPlayers[player]);
if (prop == null) continue;
info.TransmitEntities.Remove(prop);
}
}
}
}
91 changes: 91 additions & 0 deletions src/Cosmetics+Utilities.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Utils;
using CounterStrikeSharp.API.Modules.Entities.Constants;
using System.Drawing;

namespace Cosmetics
{
public partial class Cosmetics : BasePlugin
{
private int SpawnProp(CCSPlayerController player, string model, float scale = 1.0f)
{
// sanity checks
if (player == null
|| player.PlayerPawn == null || !player.PlayerPawn.IsValid || player.PlayerPawn.Value == null) return -1;
// create dynamic prop
CDynamicProp prop;
prop = Utilities.CreateEntityByName<CDynamicProp>("prop_dynamic_override")!;
// set attributes
prop.MoveType = MoveType_t.MOVETYPE_NOCLIP;
prop.Collision.SolidType = SolidType_t.SOLID_NONE;
prop.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_NONE;
prop.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_NONE;
// spawn it
prop.DispatchSpawn();
prop.SetModel(model);
prop.Teleport(new Vector(-999, -999, -999));
// set random color
prop.Render = Color.FromArgb(
255,
(byte)_random.Next(0, 255),
(byte)_random.Next(0, 255),
(byte)_random.Next(0, 255)
);
prop.AnimGraphUpdateEnabled = false;
prop.CBodyComponent!.SceneNode!.Scale = scale;
return (int)prop.Index;
}

private void UpdateProp(CCSPlayerController player, int index, int offset_z = 0, int offset_angle = 0)
{
var prop = Utilities.GetEntityFromIndex<CDynamicProp>((int)index);
// sanity checks
if (prop == null
|| player == null
|| player.Pawn == null
|| player.Pawn.Value == null
|| !player.Pawn.IsValid) return;
// get player pawn
var playerPawn = player!.Pawn!.Value;
// teleport it to player
Vector playerOrigin = new Vector(
(float)Math.Round(playerPawn.AbsOrigin!.X, 5),
(float)Math.Round(playerPawn.AbsOrigin!.Y, 5),
(float)Math.Round(playerPawn.AbsOrigin!.Z, 5) + offset_z
);
Vector propOrigin = new Vector(
(float)Math.Round(prop.AbsOrigin!.X, 5),
(float)Math.Round(prop.AbsOrigin!.Y, 5),
(float)Math.Round(prop.AbsOrigin!.Z, 5)
);
QAngle playerRotation = new QAngle(
(float)Math.Round(playerPawn.V_angle!.X, 5),
(float)Math.Round(playerPawn.V_angle!.Y, 5) + offset_angle,
0
);
QAngle propRotation = new QAngle(
0,
(float)Math.Round(prop.AbsRotation!.Y, 5),
0
);
if (playerOrigin.X == propOrigin.X
&& playerOrigin.Y == propOrigin.Y
&& playerOrigin.Z == propOrigin.Z
&& playerRotation.Y == propRotation.Y) return;
prop.Teleport(playerOrigin, playerRotation);
}

private void RemoveProp(int index, bool softRemove = false)
{
var prop = Utilities.GetEntityFromIndex<CDynamicProp>((int)index);
// remove plant entity
if (prop == null)
return;
if (softRemove)
prop.Teleport(new Vector(-999, -999, -999));
else
prop.Remove();
}
}
}
2 changes: 2 additions & 0 deletions src/Cosmetics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public void RegisterListeners(bool complete = false)
}
InitializeColoredSmokeGrenades();
InitializeDeathBeams();
InitializeSpectatorModel();
}

public void RemoveListeners(bool complete = false)
Expand All @@ -57,6 +58,7 @@ public void RemoveListeners(bool complete = false)
}
ResetColoredSmokeGrenades();
ResetDeathBeams();
ResetSpectatorModel();
}

private void OnMapStart(string mapName)
Expand Down

0 comments on commit a375977

Please sign in to comment.