Created
August 27, 2024 15:39
-
-
Save 21Joakim/b5eb46bd9acb117349e9d76d3971f34e to your computer and use it in GitHub Desktop.
CS2: Fog example (env_fog_controller)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using CounterStrikeSharp.API; | |
| using CounterStrikeSharp.API.Core; | |
| using CounterStrikeSharp.API.Core.Attributes.Registration; | |
| using CounterStrikeSharp.API.Core.Attributes; | |
| using CounterStrikeSharp.API.Modules.Commands; | |
| using CounterStrikeSharp.API.Modules.Memory; | |
| using System.Drawing; | |
| using System.Reflection; | |
| namespace CS2Plugin; | |
| // Example of how to use env_fog_controller | |
| // to set the fog on a per player basis. | |
| public class FogPlugin : BasePlugin | |
| { | |
| public override string ModuleName => "FogPlugin"; | |
| public override string ModuleVersion => "0.0.1"; | |
| public override void Load(bool hotReload) | |
| { | |
| RegisterListener<Listeners.OnTick>(OnTick); | |
| } | |
| public void OnTick() | |
| { | |
| foreach (CCSPlayerController player in Utilities.GetPlayers()) | |
| { | |
| CCSPlayerPawn? pawn = player.PlayerPawn.Value; | |
| if (pawn == null) | |
| { | |
| continue; | |
| } | |
| CFogController? fogController = pawn.CameraServices?.PlayerFog?.Ctrl.Value; | |
| if (fogController == null) | |
| { | |
| continue; | |
| } | |
| // We have to set this every tick, I am not sure why it always gets reset | |
| CopyValues(pawn.Skybox3d.Fog, fogController.Fog); | |
| SetStateChangeFogparams(pawn, "CBasePlayerPawn", "m_skybox3d", Schema.GetSchemaOffset("sky3dparams_t", "fog")); | |
| } | |
| } | |
| [ConsoleCommand("fog")] | |
| public void FogCommand(CCSPlayerController? player, CommandInfo command) | |
| { | |
| CCSPlayerPawn? pawn = player?.PlayerPawn.Value; | |
| if (player == null || pawn == null) | |
| { | |
| command.ReplyToCommand("Only a player can run this command"); | |
| return; | |
| } | |
| // Re-use the fog controller because it does not get removed after each round, | |
| // we don't want a fog controller leak :^) | |
| CFogController? GetOrCreateFogController() | |
| { | |
| string fogControllerName = $"PlayerFogController{player.Slot}"; | |
| foreach (CFogController? fogController in Utilities.FindAllEntitiesByDesignerName<CFogController>("env_fog_controller")) | |
| { | |
| if (fogController.Entity!.Name == fogControllerName) | |
| { | |
| return fogController; | |
| } | |
| } | |
| CFogController? newFogController = Utilities.CreateEntityByName<CFogController>("env_fog_controller"); | |
| if (newFogController == null) | |
| { | |
| return null; | |
| } | |
| newFogController.Entity!.Name = fogControllerName; | |
| newFogController.DispatchSpawn(); | |
| return newFogController; | |
| } | |
| CFogController? fogController = GetOrCreateFogController(); | |
| if (fogController == null) | |
| { | |
| return; | |
| } | |
| // The fog properties you want | |
| fogparams_t fog = fogController.Fog; | |
| fog.Enable = true; | |
| fog.ColorPrimary = Color.DarkOrange; | |
| fog.Exponent = 0.30f; | |
| fog.Maxdensity = 0.9f; | |
| fog.End = 10000; | |
| // If you want players to be affected by the fog you need to set the FogMaxDensityMultiplier value | |
| bool updatePlayerVisibility = true; | |
| if (updatePlayerVisibility) | |
| { | |
| CPlayerVisibility? playerVisibility = Utilities.FindAllEntitiesByDesignerName<CPlayerVisibility>("env_player_visibility") | |
| .FirstOrDefault(); | |
| if (playerVisibility != null) | |
| { | |
| playerVisibility.FogMaxDensityMultiplier = 0.9f; // Default 0 | |
| Utilities.SetStateChanged(playerVisibility, "CPlayerVisibility", "m_flFogMaxDensityMultiplier"); | |
| } | |
| } | |
| // Set the active fog controller | |
| pawn.AcceptInput("SetFogController", activator: fogController, value: "!activator"); | |
| // State change the values to make sure they are updated properly | |
| SetStateChangeFogparams(fogController, "CFogController", "m_fog"); | |
| } | |
| public static void SetStateChangeFogparams(CBaseEntity entity, string className, string fieldName, int extraOffset = 0) | |
| { | |
| // These are all the fogparam values except for the ones related to lerp | |
| string[] fogparamFields = [ | |
| "dirPrimary", "colorPrimary", "colorSecondary", | |
| "start", "end", "farz", "maxdensity", "exponent", | |
| "HDRColorScale", "skyboxFogFactor", "blendtobackground", | |
| "scattering", "locallightscale", "enable", "blend", | |
| "m_bNoReflectionFog" | |
| ]; | |
| foreach (string fogparamField in fogparamFields) | |
| { | |
| Utilities.SetStateChanged(entity, className, fieldName, extraOffset + Schema.GetSchemaOffset("fogparams_t", fogparamField)); | |
| } | |
| } | |
| public static void CopyValues<T>(T self, T other) where T : NativeObject | |
| { | |
| foreach (PropertyInfo property in self.GetType().GetProperties()) | |
| { | |
| if (property.CanRead && property.CanWrite) | |
| { | |
| property.SetValue(self, property.GetValue(other)); | |
| continue; | |
| } | |
| Type propertyType = property.PropertyType; | |
| if (!propertyType.IsByRef) | |
| { | |
| continue; | |
| } | |
| SchemaMemberAttribute? schemaAttribute = property.GetCustomAttribute<SchemaMemberAttribute>(); | |
| if (schemaAttribute == null) | |
| { | |
| continue; | |
| } | |
| ref object selfValue = ref Schema.GetRef<object>(self.Handle, schemaAttribute.ClassName, schemaAttribute.MemberName); | |
| ref object otherValue = ref Schema.GetRef<object>(other.Handle, schemaAttribute.ClassName, schemaAttribute.MemberName); | |
| selfValue = otherValue; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment