From 0bba89a7858ce091f485e04284f853e1f7f304af Mon Sep 17 00:00:00 2001 From: Leonardo Bishop Date: Sun, 6 Aug 2023 17:21:45 +0100 Subject: Reformat --- code/Game.cs | 34 +- code/entity/DroppedWeapon.cs | 68 ++- code/entity/Footprint.cs | 36 +- code/pawn/Player.Character.cs | 9 +- code/pawn/Player.Use.cs | 48 +- code/pawn/Player.cs | 84 ++- code/pawn/Ragdoll.cs | 2 +- code/pawn/component/AnimatorComponent.cs | 7 +- code/pawn/component/FallDamageComponent.cs | 16 +- code/pawn/component/FootprintTrackerComponent.cs | 41 +- code/pawn/component/InventoryComponent.cs | 53 +- code/pawn/component/camera/BaseCameraComponent.cs | 16 +- .../pawn/component/camera/PlayerCameraComponent.cs | 11 +- .../component/camera/SpectatorCameraComponent.cs | 45 +- .../component/movement/BaseControllerComponent.cs | 63 ++- .../component/movement/WalkControllerComponent.cs | 580 +++++++++++++-------- code/phase/AssignPhase.cs | 100 ++-- code/phase/BasePhase.cs | 14 +- code/phase/EndPhase.cs | 12 +- code/phase/PlayPhase.cs | 85 +-- code/phase/WaitPhase.cs | 37 +- code/team/Team.cs | 53 +- code/ui/Hud.razor | 6 +- code/ui/Hud.razor.scss | 30 +- code/ui/PlayerInfo.razor | 44 +- code/ui/character/LookingAtInfo.razor | 45 +- code/ui/character/NameInfo.razor | 10 +- code/ui/component/Box.razor | 7 +- code/ui/component/SmallBox.razor | 7 +- code/ui/health/Health.razor | 8 +- code/ui/mainmenu/LoadingScreen.razor | 19 +- code/ui/mainmenu/LoadingScreen.razor.scss | 161 +++--- code/ui/mainmenu/MainMenu.razor | 9 +- code/ui/mainmenu/MainMenu.razor.scss | 403 +++++++------- code/ui/overlay/BlindedOverlay.Network.cs | 24 +- code/ui/overlay/BlindedOverlay.razor | 9 +- code/ui/overlay/DeathOverlay.Network.cs | 26 +- code/ui/overlay/DeathOverlay.razor | 29 +- code/ui/overlay/RoleOverlay.Network.cs | 24 +- code/ui/overlay/RoleOverlay.razor | 13 +- code/ui/overlay/TabListEntry.cs | 20 +- code/ui/overlay/TabListOverlay.razor | 61 ++- code/ui/phase/PhaseInfo.razor | 14 +- code/ui/phase/PhaseTimer.razor | 28 +- code/ui/spectator/Spectator.razor | 55 +- code/ui/team/TeamInfo.razor | 10 +- code/ui/weapon/Crosshair.razor | 8 +- code/ui/weapon/Reload.razor | 65 ++- code/weapon/Knife.cs | 16 +- code/weapon/Pistol.cs | 8 +- code/weapon/Weapon.cs | 103 ++-- code/weapon/WeaponViewModel.cs | 8 +- 52 files changed, 1425 insertions(+), 1259 deletions(-) (limited to 'code') diff --git a/code/Game.cs b/code/Game.cs index 356cd38..8903155 100644 --- a/code/Game.cs +++ b/code/Game.cs @@ -1,13 +1,11 @@ - +using System; +using System.Linq; using Sandbox; using Sandbox.UI; -using System; -using System.Collections.Generic; -using System.Linq; namespace MurderGame; -public partial class MurderGame : Sandbox.GameManager +public partial class MurderGame : GameManager { public MurderGame() { @@ -17,10 +15,7 @@ public partial class MurderGame : Sandbox.GameManager } } - public static MurderGame Instance - { - get => Current as MurderGame; - } + public static MurderGame Instance => Current as MurderGame; [ConVar.Server( "mu_min_players", Help = "The minimum number of players required to start a round." )] @@ -31,23 +26,23 @@ public partial class MurderGame : Sandbox.GameManager [ConVar.Server( "mu_round_time", Help = "The amount of time, in seconds, in a round." )] public static int RoundTime { get; set; } = 600; - - [ConVar.Client( "mu_max_footprint_time", Help = "The amount of time, in seconds, footprints are visible for. Max 30 seconds." )] + + [ConVar.Client( "mu_max_footprint_time", + Help = "The amount of time, in seconds, footprints are visible for. Max 30 seconds." )] public static int MaxFootprintTime { get; set; } = 30; - [Net] - public BasePhase CurrentPhase { get; set; } = new WaitPhase() { CountIn = true }; + [Net] public BasePhase CurrentPhase { get; set; } = new WaitPhase { CountIn = true }; [GameEvent.Tick.Server] public void TickServer() { CurrentPhase.Tick(); - - if (CurrentPhase.NextPhase != null && CurrentPhase.IsFinished) + + if ( CurrentPhase.NextPhase != null && CurrentPhase.IsFinished ) { CurrentPhase.Deactivate(); CurrentPhase = CurrentPhase.NextPhase; - Log.Info("Advancing phase to " + CurrentPhase.ToString()); + Log.Info( "Advancing phase to " + CurrentPhase ); CurrentPhase.Activate(); } } @@ -61,7 +56,7 @@ public partial class MurderGame : Sandbox.GameManager client.Pawn = pawn; pawn.Spawn(); - var spawnpoints = Entity.All.OfType(); + var spawnpoints = All.OfType(); var randomSpawnPoint = spawnpoints.OrderBy( x => Guid.NewGuid() ).FirstOrDefault(); if ( randomSpawnPoint != null ) { @@ -75,9 +70,8 @@ public partial class MurderGame : Sandbox.GameManager public override void ClientDisconnect( IClient client, NetworkDisconnectionReason reason ) { - base.ClientDisconnect(client, reason ); + base.ClientDisconnect( client, reason ); - ChatBox.Say( client.Name + " left the game (" + reason.ToString() + ")" ); + ChatBox.Say( client.Name + " left the game (" + reason + ")" ); } } - diff --git a/code/entity/DroppedWeapon.cs b/code/entity/DroppedWeapon.cs index c540759..46cf67d 100644 --- a/code/entity/DroppedWeapon.cs +++ b/code/entity/DroppedWeapon.cs @@ -1,14 +1,12 @@ -using MurderGame; +using System; +using MurderGame; using Sandbox; -using System; using Sandbox.Component; +using Player = MurderGame.Player; -public partial class DroppedWeapon : AnimatedEntity, IUse +public class DroppedWeapon : AnimatedEntity, IUse { - private int Ammo { get; } - private Type WeaponType { get; } - - public DroppedWeapon(Weapon weapon) : this() + public DroppedWeapon( Weapon weapon ) : this() { Ammo = weapon.Ammo; WeaponType = weapon.GetType(); @@ -16,49 +14,63 @@ public partial class DroppedWeapon : AnimatedEntity, IUse public DroppedWeapon() { - Tags.Add("droppedweapon"); - + Tags.Add( "droppedweapon" ); + var glow = Components.GetOrCreate(); glow.Enabled = true; glow.Width = 0.25f; - glow.Color = new Color( 4f, 50.0f, 70.0f, 1.0f ); - glow.ObscuredColor = new Color( 0, 0, 0, 0); - + glow.Color = new Color( 4f, 50.0f, 70.0f ); + glow.ObscuredColor = new Color( 0, 0, 0, 0 ); + PhysicsEnabled = true; UsePhysicsCollision = true; EnableSelfCollisions = true; EnableSolidCollisions = true; } + private int Ammo { get; } + private Type WeaponType { get; } + + public bool OnUse( Entity user ) + { + if ( user is not Player player ) + { + return false; + } + + Pickup( player ); + return false; + } + + public bool IsUsable( Entity user ) + { + return user is Player { Inventory: { PrimaryWeapon: null, AllowPickup: true } }; + } + public override void StartTouch( Entity other ) { - if ( !Game.IsServer ) return; - if ( !other.Tags.Has( "livingplayer" ) ) return; + if ( !Game.IsServer ) + { + return; + } - var player = (MurderGame.Player)other; + if ( !other.Tags.Has( "livingplayer" ) ) + { + return; + } + + var player = (Player)other; if ( IsUsable( player ) ) { Pickup( player ); } } - public void Pickup( MurderGame.Player player ) + public void Pickup( Player player ) { var instance = TypeLibrary.Create( WeaponType ); instance.Ammo = Ammo; player.Inventory.SetPrimaryWeapon( instance ); Delete(); } - - public bool OnUse( Entity user ) - { - if ( user is not MurderGame.Player player ) return false; - Pickup( player ); - return false; - } - - public bool IsUsable( Entity user ) - { - return user is MurderGame.Player { Inventory: { PrimaryWeapon: null, AllowPickup: true } }; - } } diff --git a/code/entity/Footprint.cs b/code/entity/Footprint.cs index 8941e95..f4b988d 100644 --- a/code/entity/Footprint.cs +++ b/code/entity/Footprint.cs @@ -1,25 +1,24 @@ using System; +using Sandbox; namespace MurderGame; -using Sandbox; // It's just a square with a material slapped onto it. public class Footprint : RenderEntity { + private readonly TimeSince TimeSinceCreated = 0; public Material SpriteMaterial { get; set; } public float SpriteScale { get; set; } = 18f; public bool Enabled { get; set; } = true; - + public Color Color { get; set; } - private TimeSince TimeSinceCreated = 0; - [GameEvent.Tick.Client] public void OnTick() { - if ( !(TimeSinceCreated > Math.Clamp(MurderGame.MaxFootprintTime, 0, 30)) ) + if ( !(TimeSinceCreated > Math.Clamp( MurderGame.MaxFootprintTime, 0, 30 )) ) { return; } @@ -27,28 +26,31 @@ public class Footprint : RenderEntity Enabled = false; Delete(); } - - public override void DoRender(SceneObject obj) + + public override void DoRender( SceneObject obj ) { - if (!Enabled) return; + if ( !Enabled ) + { + return; + } // Allow lights to affect the sprite - Graphics.SetupLighting(obj); + Graphics.SetupLighting( obj ); // Create the vertex buffer for the sprite var vb = new VertexBuffer(); - vb.Init(true); + vb.Init( true ); // Vertex buffers are in local space, so we need the camera position in local space too var normal = new Vector3( 0, 0.01f, 100 ); - var w = normal.Cross(Vector3.Down).Normal; - var h = normal.Cross(w).Normal; - float halfSpriteSize = SpriteScale / 2; + var w = normal.Cross( Vector3.Down ).Normal; + var h = normal.Cross( w ).Normal; + var halfSpriteSize = SpriteScale / 2; // Add a single quad to our vertex buffer - vb.AddQuad(new Ray(default, normal), halfSpriteSize*w, h*halfSpriteSize); - - Graphics.Attributes.Set( "color", Color); - + vb.AddQuad( new Ray( default, normal ), halfSpriteSize * w, h * halfSpriteSize ); + + Graphics.Attributes.Set( "color", Color ); + // Draw the sprite vb.Draw( SpriteMaterial ); } diff --git a/code/pawn/Player.Character.cs b/code/pawn/Player.Character.cs index 579107a..0297014 100644 --- a/code/pawn/Player.Character.cs +++ b/code/pawn/Player.Character.cs @@ -9,13 +9,8 @@ public partial class Player [Net] public string CharacterName { get; set; } [Net] public Color Color { get; set; } = Color.White; - - public string HexColor { - get - { - return Color.Hex; - } - } + + public string HexColor => Color.Hex; public string GetTeamName() { diff --git a/code/pawn/Player.Use.cs b/code/pawn/Player.Use.cs index 3f35052..8c3cce9 100644 --- a/code/pawn/Player.Use.cs +++ b/code/pawn/Player.Use.cs @@ -9,7 +9,10 @@ public partial class Player protected virtual void TickPlayerUse() { // This is serverside only - if ( !Game.IsServer ) return; + if ( !Game.IsServer ) + { + return; + } // Turn prediction off using ( Prediction.Off() ) @@ -32,7 +35,9 @@ public partial class Player } if ( !Using.IsValid() ) + { return; + } // If we move too far away or something we should probably ClearUse()? @@ -40,15 +45,17 @@ public partial class Player // If use returns true then we can keep using it // if ( Using is IUse use && use.OnUse( this ) ) + { return; + } StopUsing(); } } /// - /// Player tried to use something but there was nothing there. - /// Tradition is to give a disappointed boop. + /// Player tried to use something but there was nothing there. + /// Tradition is to give a disappointed boop. /// protected virtual void UseFail() { @@ -56,7 +63,7 @@ public partial class Player } /// - /// If we're using an entity, stop using it + /// If we're using an entity, stop using it /// protected virtual void StopUsing() { @@ -64,19 +71,30 @@ public partial class Player } /// - /// Returns if the entity is a valid usable entity + /// Returns if the entity is a valid usable entity /// protected bool IsValidUseEntity( Entity e ) { - if ( e == null ) return false; - if ( e is not IUse use ) return false; - if ( !use.IsUsable( this ) ) return false; + if ( e == null ) + { + return false; + } + + if ( e is not IUse use ) + { + return false; + } + + if ( !use.IsUsable( this ) ) + { + return false; + } return true; } /// - /// Find a usable entity for this player to use + /// Find a usable entity for this player to use /// protected virtual Entity FindUsable() { @@ -96,9 +114,9 @@ public partial class Player if ( !IsValidUseEntity( ent ) ) { tr = Trace.Ray( EyePosition, EyePosition + EyeRotation.Forward * 85 ) - .Radius( 2 ) - .Ignore( this ) - .Run(); + .Radius( 2 ) + .Ignore( this ) + .Run(); // See if any of the parent entities are usable if we ain't. ent = tr.Entity; @@ -109,9 +127,11 @@ public partial class Player } // Still no good? Bail. - if ( !IsValidUseEntity( ent ) ) return null; + if ( !IsValidUseEntity( ent ) ) + { + return null; + } return ent; } } - diff --git a/code/pawn/Player.cs b/code/pawn/Player.cs index 3d92008..0c05132 100644 --- a/code/pawn/Player.cs +++ b/code/pawn/Player.cs @@ -1,16 +1,13 @@ -using Sandbox; -using Sandbox.UI; -using System.ComponentModel; +using System.ComponentModel; +using Sandbox; namespace MurderGame; public partial class Player : AnimatedEntity { - [ClientInput] - public Vector3 InputDirection { get; set; } - - [ClientInput] - public Angles ViewAngles { get; set; } + [ClientInput] public Vector3 InputDirection { get; set; } + + [ClientInput] public Angles ViewAngles { get; set; } [Browsable( false )] public Vector3 EyePosition @@ -19,8 +16,7 @@ public partial class Player : AnimatedEntity set => EyeLocalPosition = Transform.PointToLocal( value ); } - [Net, Predicted, Browsable( false )] - public Vector3 EyeLocalPosition { get; set; } + [Net] [Predicted] [Browsable( false )] public Vector3 EyeLocalPosition { get; set; } [Browsable( false )] public Rotation EyeRotation @@ -29,17 +25,14 @@ public partial class Player : AnimatedEntity set => EyeLocalRotation = Transform.RotationToLocal( value ); } - [Net, Predicted, Browsable( false )] - public Rotation EyeLocalRotation { get; set; } + [Net] [Predicted] [Browsable( false )] public Rotation EyeLocalRotation { get; set; } - public BBox Hull - { - get => new + public BBox Hull => + new ( new Vector3( -16, -16, 0 ), new Vector3( 16, 16, 72 ) ); - } public BaseCameraComponent Camera => Components.Get(); @@ -49,20 +42,19 @@ public partial class Player : AnimatedEntity [BindComponent] public FallDamageComponent FallDamage { get; } [BindComponent] public FootprintTrackerComponent FootprintTracker { get; } - [Net] - public Ragdoll PlayerRagdoll { get; set; } + [Net] public Ragdoll PlayerRagdoll { get; set; } + public ClothingContainer PlayerClothingContainer { get; set; } public Vector3 LastAttackForce { get; set; } public int LastHitBone { get; set; } - public override Ray AimRay => new Ray( EyePosition, EyeRotation.Forward ); + public override Ray AimRay => new(EyePosition, EyeRotation.Forward); + + [Net] [Predicted] public TimeSince TimeSinceDeath { get; set; } = 0; - [Net, Predicted] - public TimeSince TimeSinceDeath { get; set; } = 0; - public Player LookingAt { get; set; } - + public override void Spawn() { SetModel( "models/citizen/citizen.vmdl" ); @@ -106,7 +98,7 @@ public partial class Player : AnimatedEntity public void DeleteRagdoll() { - if (PlayerRagdoll != null) + if ( PlayerRagdoll != null ) { PlayerRagdoll.Delete(); PlayerRagdoll = null; @@ -129,17 +121,17 @@ public partial class Player : AnimatedEntity { TimeSinceDeath = 0; - Inventory?.SpillContents(EyePosition, new Vector3(0,0,0)); + Inventory?.SpillContents( EyePosition, new Vector3( 0, 0, 0 ) ); DisablePlayer(); - + Event.Run( MurderEvent.Kill, LastAttacker, this ); var ragdoll = new Ragdoll(); ragdoll.Position = Position; ragdoll.Rotation = Rotation; - ragdoll.CopyFrom(this); - ragdoll.PhysicsGroup.AddVelocity(LastAttackForce / 100); + ragdoll.CopyFrom( this ); + ragdoll.PhysicsGroup.AddVelocity( LastAttackForce / 100 ); PlayerClothingContainer.DressEntity( ragdoll ); PlayerRagdoll = ragdoll; @@ -152,10 +144,10 @@ public partial class Player : AnimatedEntity LastAttackerWeapon = info.Weapon; LastAttackForce = info.Force; LastHitBone = info.BoneIndex; - if (Game.IsServer && Health > 0f && LifeState == LifeState.Alive) + if ( Game.IsServer && Health > 0f && LifeState == LifeState.Alive ) { Health -= info.Damage; - if (Health <= 0f) + if ( Health <= 0f ) { Health = 0f; OnKilled(); @@ -169,12 +161,12 @@ public partial class Player : AnimatedEntity PlayerClothingContainer.LoadFromClient( cl ); PlayerClothingContainer.DressEntity( this ); } - + public void Dress() { PlayerClothingContainer = new ClothingContainer(); - var trousers = new Clothing() { Model = "models/citizen_clothes/trousers/cargopants/models/cargo_pants.vmdl" }; - var tshirt = new Clothing() { Model = "models/citizen_clothes/shirt/Tshirt/Models/tshirt.vmdl" }; + var trousers = new Clothing { Model = "models/citizen_clothes/trousers/cargopants/models/cargo_pants.vmdl" }; + var tshirt = new Clothing { Model = "models/citizen_clothes/shirt/Tshirt/Models/tshirt.vmdl" }; PlayerClothingContainer.Clothing.Add( trousers ); PlayerClothingContainer.Clothing.Add( tshirt ); PlayerClothingContainer.DressEntity( this ); @@ -192,7 +184,8 @@ public partial class Player : AnimatedEntity FallDamage?.Simulate( cl ); FootprintTracker?.Simulate( cl ); - if (Game.IsServer && Camera is not SpectatorCameraComponent && LifeState == LifeState.Dead && TimeSinceDeath > 3.5) + if ( Game.IsServer && Camera is not SpectatorCameraComponent && LifeState == LifeState.Dead && + TimeSinceDeath > 3.5 ) { DeathOverlay.Hide( To.Single( Client ) ); Components.Remove( Controller ); @@ -207,13 +200,13 @@ public partial class Player : AnimatedEntity { var start = AimRay.Position; var end = AimRay.Position + AimRay.Forward * 5000; - + var trace = Trace.Ray( start, end ) - .UseHitboxes() - .WithAnyTags( "solid", "livingplayer" ) - .Ignore( this ) - .Size( 1f ); - + .UseHitboxes() + .WithAnyTags( "solid", "livingplayer" ) + .Ignore( this ) + .Size( 1f ); + var tr = trace.Run(); if ( tr.Hit && tr.Entity.IsValid() && tr.Entity is Player player ) { @@ -224,8 +217,6 @@ public partial class Player : AnimatedEntity LookingAt = null; } } - - } public override void BuildInput() @@ -254,10 +245,10 @@ public partial class Player : AnimatedEntity } var tr = Trace.Ray( start, end ) - .Size( mins, maxs ) - .WithAnyTags( "solid", "player", "passbullets" ) - .Ignore( this ) - .Run(); + .Size( mins, maxs ) + .WithAnyTags( "solid", "player", "passbullets" ) + .Ignore( this ) + .Run(); return tr; } @@ -267,5 +258,4 @@ public partial class Player : AnimatedEntity EyeRotation = ViewAngles.ToRotation(); Rotation = ViewAngles.WithPitch( 0f ).ToRotation(); } - } diff --git a/code/pawn/Ragdoll.cs b/code/pawn/Ragdoll.cs index 9948946..1b7a6d8 100644 --- a/code/pawn/Ragdoll.cs +++ b/code/pawn/Ragdoll.cs @@ -1,6 +1,6 @@ using Sandbox; -public partial class Ragdoll : AnimatedEntity +public class Ragdoll : AnimatedEntity { public Ragdoll() { diff --git a/code/pawn/component/AnimatorComponent.cs b/code/pawn/component/AnimatorComponent.cs index 6b27b15..11eb67a 100644 --- a/code/pawn/component/AnimatorComponent.cs +++ b/code/pawn/component/AnimatorComponent.cs @@ -13,8 +13,11 @@ public class AnimatorComponent : EntityComponent, ISingletonComponent helper.WithLookAt( Entity.EyePosition + Entity.EyeRotation.Forward * 100 ); helper.HoldType = CitizenAnimationHelper.HoldTypes.None; helper.IsGrounded = Entity.GroundEntity.IsValid(); - helper.DuckLevel = MathX.Lerp( helper.DuckLevel, player.Controller.HasTag( "ducked" ) ? 1 : 0, Time.Delta * 10.0f ); - helper.VoiceLevel = (Game.IsClient && player.Client.IsValid()) ? player.Client.Voice.LastHeard < 0.5f ? player.Client.Voice.CurrentLevel : 0.0f : 0.0f; + helper.DuckLevel = MathX.Lerp( helper.DuckLevel, player.Controller.HasTag( "ducked" ) ? 1 : 0, + Time.Delta * 10.0f ); + helper.VoiceLevel = Game.IsClient && player.Client.IsValid() + ? player.Client.Voice.LastHeard < 0.5f ? player.Client.Voice.CurrentLevel : 0.0f + : 0.0f; helper.IsClimbing = player.Controller.HasTag( "climbing" ); helper.IsSwimming = player.GetWaterLevel() >= 0.5f; diff --git a/code/pawn/component/FallDamageComponent.cs b/code/pawn/component/FallDamageComponent.cs index 59e75d3..97d24a4 100644 --- a/code/pawn/component/FallDamageComponent.cs +++ b/code/pawn/component/FallDamageComponent.cs @@ -2,22 +2,24 @@ namespace MurderGame; -public partial class FallDamageComponent : EntityComponent, ISingletonComponent +public class FallDamageComponent : EntityComponent, ISingletonComponent { - float PreviousZVelocity = 0; - const float LethalFallSpeed = 1024; - const float SafeFallSpeed = 580; - const float DamageForSpeed = (float)100 / (LethalFallSpeed - SafeFallSpeed); // damage per unit per second. + private const float LethalFallSpeed = 1024; + private const float SafeFallSpeed = 580; + private const float DamageForSpeed = 100 / (LethalFallSpeed - SafeFallSpeed); // damage per unit per second. + private float PreviousZVelocity; + public void Simulate( IClient cl ) { var FallSpeed = -PreviousZVelocity; - if ( FallSpeed > (SafeFallSpeed * Entity.Scale) && Entity.GroundEntity != null ) + if ( FallSpeed > SafeFallSpeed * Entity.Scale && Entity.GroundEntity != null ) { - var FallDamage = (FallSpeed - (SafeFallSpeed * Entity.Scale)) * (DamageForSpeed * Entity.Scale); + var FallDamage = (FallSpeed - SafeFallSpeed * Entity.Scale) * (DamageForSpeed * Entity.Scale); var info = DamageInfo.Generic( FallDamage ).WithTag( "fall" ); Entity.TakeDamage( info ); Entity.PlaySound( "fall" ); } + PreviousZVelocity = Entity.Velocity.z; } } diff --git a/code/pawn/component/FootprintTrackerComponent.cs b/code/pawn/component/FootprintTrackerComponent.cs index 7a396d1..bc5fdc6 100644 --- a/code/pawn/component/FootprintTrackerComponent.cs +++ b/code/pawn/component/FootprintTrackerComponent.cs @@ -4,27 +4,39 @@ using Sandbox; namespace MurderGame; public class FootprintTrackerComponent : EntityComponent, ISingletonComponent -{ - private TimeSince TimeSinceFootstep = 0; +{ private bool FootstepLeft = true; + private TimeSince TimeSinceFootstep = 0; public void Simulate( IClient cl ) { - if (!Game.IsClient || TimeSinceFootstep < 0.25) return; + if ( !Game.IsClient || TimeSinceFootstep < 0.25 ) + { + return; + } + TimeSinceFootstep = 0; FootstepLeft = !FootstepLeft; - - var bystanders = Game.Clients.Where(c => (c.Pawn as Player)?.Team is Team.Bystander or Team.Detective); - - foreach (var bystander in bystanders) + + var bystanders = Game.Clients.Where( c => (c.Pawn as Player)?.Team is Team.Bystander or Team.Detective ); + + foreach ( var bystander in bystanders ) { - if (bystander.Pawn is not Player player) continue; - if (player.Velocity.Length < 1) continue; + if ( bystander.Pawn is not Player player ) + { + continue; + } + + if ( player.Velocity.Length < 1 ) + { + continue; + } + var start = player.Position + Vector3.Up; var end = start + Vector3.Down * 20; - + var tr = Trace.Ray( start, end ) - .Size( 2) + .Size( 2 ) .WithAnyTags( "solid" ) .Ignore( Entity ) .Run(); @@ -39,13 +51,12 @@ public class FootprintTrackerComponent : EntityComponent, ISingletonComp : "materials/right_shoe_footprint.vmat"; var _ = new Footprint { - SpriteMaterial = Material.Load(material), + SpriteMaterial = Material.Load( material ), SpriteScale = 24f, - Position = player.Position + (Vector3.Up * 1f), - Rotation = Rotation.LookAt(player.Velocity, tr.Normal).RotateAroundAxis( tr.Normal, 270 ), + Position = player.Position + Vector3.Up * 1f, + Rotation = Rotation.LookAt( player.Velocity, tr.Normal ).RotateAroundAxis( tr.Normal, 270 ), Color = player.Color }; } } - } diff --git a/code/pawn/component/InventoryComponent.cs b/code/pawn/component/InventoryComponent.cs index 6383aa8..cec897c 100644 --- a/code/pawn/component/InventoryComponent.cs +++ b/code/pawn/component/InventoryComponent.cs @@ -1,31 +1,27 @@ using Sandbox; -using System; namespace MurderGame; public partial class InventoryComponent : EntityComponent, ISingletonComponent { - const int MIN_SLOT = 1; - const int MAX_SLOT = 2; + private const int MIN_SLOT = 1; + private const int MAX_SLOT = 2; - const int UNARMED_SLOT = 1; - const int PRIMARY_SLOT = 2; + private const int UNARMED_SLOT = 1; + private const int PRIMARY_SLOT = 2; - [Net] - public Weapon PrimaryWeapon { get; private set; } + [Net] public Weapon PrimaryWeapon { get; private set; } - [Net] - public int ActiveSlot { get; set; } + [Net] public int ActiveSlot { get; set; } - [Net] - public bool AllowPickup { get; set; } = true; + [Net] public bool AllowPickup { get; set; } = true; public Weapon GetCurrentWeapon() { return ActiveSlot switch { PRIMARY_SLOT => PrimaryWeapon, - _ => null, + _ => null }; } @@ -34,11 +30,12 @@ public partial class InventoryComponent : EntityComponent, ISingletonCom PrimaryWeapon?.OnHolster(); PrimaryWeapon?.Delete(); PrimaryWeapon = weapon; - if (weapon != null) + if ( weapon != null ) { weapon.ChangeOwner( Entity ); } - if (ActiveSlot == PRIMARY_SLOT) + + if ( ActiveSlot == PRIMARY_SLOT ) { weapon?.OnEquip( Entity ); } @@ -46,7 +43,7 @@ public partial class InventoryComponent : EntityComponent, ISingletonCom private void PrevSlot() { - if (ActiveSlot > MIN_SLOT) + if ( ActiveSlot > MIN_SLOT ) { --ActiveSlot; } @@ -55,9 +52,10 @@ public partial class InventoryComponent : EntityComponent, ISingletonCom ActiveSlot = MAX_SLOT; } } + private void NextSlot() { - if (ActiveSlot < MAX_SLOT) + if ( ActiveSlot < MAX_SLOT ) { ++ActiveSlot; } @@ -67,39 +65,40 @@ public partial class InventoryComponent : EntityComponent, ISingletonCom } } - public void Simulate(IClient cl) + public void Simulate( IClient cl ) { var currentWeapon = GetCurrentWeapon(); var currentSlot = ActiveSlot; - if (Input.Released("SlotPrev")) + if ( Input.Released( "SlotPrev" ) ) { PrevSlot(); } - else if (Input.Released("SlotNext")) + else if ( Input.Released( "SlotNext" ) ) { NextSlot(); } - else if (Input.Down("Slot1")) + else if ( Input.Down( "Slot1" ) ) { ActiveSlot = 1; } - else if (Input.Down("Slot2")) + else if ( Input.Down( "Slot2" ) ) { ActiveSlot = 2; } - if (ActiveSlot != currentSlot) + if ( ActiveSlot != currentSlot ) { currentWeapon?.OnHolster(); GetCurrentWeapon()?.OnEquip( Entity ); } + GetCurrentWeapon()?.Simulate( cl ); } public void Holster() { - Weapon weapon = GetCurrentWeapon(); + var weapon = GetCurrentWeapon(); weapon?.OnHolster(); } @@ -109,18 +108,18 @@ public partial class InventoryComponent : EntityComponent, ISingletonCom SetPrimaryWeapon( null ); } - public void SpillContents(Vector3 location, Vector3 velocity) + public void SpillContents( Vector3 location, Vector3 velocity ) { Holster(); - if (PrimaryWeapon is not null and Pistol ) + if ( PrimaryWeapon is not null and Pistol ) { PrimaryWeapon.ChangeOwner( null ); - DroppedWeapon droppedWeapon = new( (Pistol)PrimaryWeapon ); + DroppedWeapon droppedWeapon = new((Pistol)PrimaryWeapon); droppedWeapon.CopyFrom( PrimaryWeapon ); droppedWeapon.Position = location; droppedWeapon.Velocity = velocity; } + Clear(); } - } diff --git a/code/pawn/component/camera/BaseCameraComponent.cs b/code/pawn/component/camera/BaseCameraComponent.cs index 401d702..b19b2f9 100644 --- a/code/pawn/component/camera/BaseCameraComponent.cs +++ b/code/pawn/component/camera/BaseCameraComponent.cs @@ -4,25 +4,23 @@ namespace MurderGame; public class BaseCameraComponent : EntityComponent, ISingletonComponent { - public virtual void Simulate( IClient cl ) { - } + public virtual void FrameSimulate( IClient cl ) { - } + public virtual void BuildInput() { - } public virtual InventoryComponent GetObservedInventory() { return Entity.Inventory; } - + public virtual float GetObservedHealth() { return Entity.Health; @@ -30,17 +28,17 @@ public class BaseCameraComponent : EntityComponent, ISingletonComponent public virtual Team GetObservedTeam() { - return Entity.Team; + return Entity.Team; } - + public virtual string GetObservedName() { var characterName = Entity.CharacterName; return string.IsNullOrWhiteSpace( characterName ) ? Entity.Client.Name : characterName; } - + public virtual string GetObservedColour() { - return Entity.HexColor; + return Entity.HexColor; } } diff --git a/code/pawn/component/camera/PlayerCameraComponent.cs b/code/pawn/component/camera/PlayerCameraComponent.cs index 5ec9f7b..4ac0e2d 100644 --- a/code/pawn/component/camera/PlayerCameraComponent.cs +++ b/code/pawn/component/camera/PlayerCameraComponent.cs @@ -10,13 +10,13 @@ public class PlayerCameraComponent : BaseCameraComponent // Set field of view to whatever the user chose in options Camera.FieldOfView = Screen.CreateVerticalFieldOfView( Game.Preferences.FieldOfView ); } + public override void FrameSimulate( IClient cl ) { - - var pl = Entity as Player; + var pl = Entity; // Update rotation every frame, to keep things smooth - if (pl.PlayerRagdoll != null && pl.LifeState == LifeState.Dead) + if ( pl.PlayerRagdoll != null && pl.LifeState == LifeState.Dead ) { Camera.Position = pl.PlayerRagdoll.Position; Camera.FirstPersonViewer = pl.PlayerRagdoll; @@ -35,12 +35,15 @@ public class PlayerCameraComponent : BaseCameraComponent Camera.ZNear = 8 * pl.Scale; } + public override void BuildInput() { if ( Game.LocalClient.Components.TryGet( out var _ ) ) + { return; + } - var pl = Entity as Player; + var pl = Entity; var viewAngles = (pl.ViewAngles + Input.AnalogLook).Normal; pl.ViewAngles = viewAngles.WithPitch( viewAngles.pitch.Clamp( -89f, 89f ) ); } diff --git a/code/pawn/component/camera/SpectatorCameraComponent.cs b/code/pawn/component/camera/SpectatorCameraComponent.cs index 215b9ca..9dce4c3 100644 --- a/code/pawn/component/camera/SpectatorCameraComponent.cs +++ b/code/pawn/component/camera/SpectatorCameraComponent.cs @@ -1,6 +1,6 @@ -using Sandbox; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; +using Sandbox; namespace MurderGame; @@ -17,7 +17,8 @@ public partial class SpectatorCameraComponent : BaseCameraComponent Target = null; return; } - if (Target == null || !Target.IsValid() || Target.LifeState == LifeState.Dead) + + if ( Target == null || !Target.IsValid() || Target.LifeState == LifeState.Dead ) { FindNextTarget( targets, false ); return; @@ -36,7 +37,10 @@ public partial class SpectatorCameraComponent : BaseCameraComponent public override void FrameSimulate( IClient cl ) { - if ( Target == null || !Target.IsValid() || Target.LifeState == LifeState.Dead ) return; + if ( Target == null || !Target.IsValid() || Target.LifeState == LifeState.Dead ) + { + return; + } Camera.Rotation = Target.EyeRotation; Camera.FieldOfView = Screen.CreateVerticalFieldOfView( Game.Preferences.FieldOfView ); @@ -47,27 +51,36 @@ public partial class SpectatorCameraComponent : BaseCameraComponent private List GetTargets() { - return Game.Clients.Where(c => c.Pawn is Player player && player.Team != Team.Spectator && player.LifeState == LifeState.Alive).ToList(); + return Game.Clients.Where( c => + c.Pawn is Player player && player.Team != Team.Spectator && player.LifeState == LifeState.Alive ).ToList(); } - - private void FindNextTarget(List targets, bool backwards) + + private void FindNextTarget( List targets, bool backwards ) { if ( !backwards ) { - if ( ++TargetIndex >= targets.Count ) TargetIndex = 0; - } - else { - if ( --TargetIndex < 0 ) TargetIndex = targets.Count - 1; + if ( ++TargetIndex >= targets.Count ) + { + TargetIndex = 0; + } + } + else + { + if ( --TargetIndex < 0 ) + { + TargetIndex = targets.Count - 1; + } } + var nextTarget = targets[TargetIndex]; Target = (Player)nextTarget.Pawn; } - + public override InventoryComponent GetObservedInventory() { return Target?.Inventory; } - + public override float GetObservedHealth() { return Target?.Health ?? base.GetObservedHealth(); @@ -77,13 +90,13 @@ public partial class SpectatorCameraComponent : BaseCameraComponent { return Target?.Team ?? base.GetObservedTeam(); } - + public override string GetObservedName() { var characterName = Target?.CharacterName ?? ""; - return string.IsNullOrWhiteSpace( characterName ) ? (Target?.Client.Name ?? "Unknown") : characterName; + return string.IsNullOrWhiteSpace( characterName ) ? Target?.Client.Name ?? "Unknown" : characterName; } - + public override string GetObservedColour() { return Target?.HexColor ?? base.GetObservedColour(); diff --git a/code/pawn/component/movement/BaseControllerComponent.cs b/code/pawn/component/movement/BaseControllerComponent.cs index d9b24c6..a9bed5f 100644 --- a/code/pawn/component/movement/BaseControllerComponent.cs +++ b/code/pawn/component/movement/BaseControllerComponent.cs @@ -1,38 +1,40 @@ -using Sandbox; -using System; +using System; using System.Collections.Generic; +using Sandbox; namespace MurderGame; /// -/// Component designed for movement, only 1 per pawn. +/// Component designed for movement, only 1 per pawn. /// public class BaseControllerComponent : EntityComponent, ISingletonComponent { + internal HashSet Events = new(StringComparer.OrdinalIgnoreCase); + + internal HashSet Tags; + public Vector3 WishVelocity { get; set; } public virtual void Simulate( IClient cl ) { - } + public virtual void FrameSimulate( IClient cl ) { - } + public virtual void BuildInput() { - } - public Vector3 WishVelocity { get; set; } - internal HashSet Events = new( StringComparer.OrdinalIgnoreCase ); - - internal HashSet Tags; /// - /// Call OnEvent for each event + /// Call OnEvent for each event /// public virtual void RunEvents( BaseControllerComponent additionalController ) { - if ( Events == null ) return; + if ( Events == null ) + { + return; + } foreach ( var e in Events ) { @@ -42,19 +44,22 @@ public class BaseControllerComponent : EntityComponent, ISingletonCompon } /// - /// An event has been triggered - maybe handle it + /// An event has been triggered - maybe handle it /// public virtual void OnEvent( string name ) { - } /// - /// Returns true if we have this event + /// Returns true if we have this event /// public bool HasEvent( string eventName ) { - if ( Events == null ) return false; + if ( Events == null ) + { + return false; + } + return Events.Contains( eventName ); } @@ -62,26 +67,35 @@ public class BaseControllerComponent : EntityComponent, ISingletonCompon /// public bool HasTag( string tagName ) { - if ( Tags == null ) return false; + if ( Tags == null ) + { + return false; + } + return Tags.Contains( tagName ); } /// - /// Allows the controller to pass events to other systems - /// while staying abstracted. - /// For example, it could pass a "jump" event, which could then - /// be picked up by the playeranimator to trigger a jump animation, - /// and picked up by the player to play a jump sound. + /// Allows the controller to pass events to other systems + /// while staying abstracted. + /// For example, it could pass a "jump" event, which could then + /// be picked up by the playeranimator to trigger a jump animation, + /// and picked up by the player to play a jump sound. /// public void AddEvent( string eventName ) { // TODO - shall we allow passing data with the event? - if ( Events == null ) Events = new HashSet(); + if ( Events == null ) + { + Events = new HashSet(); + } if ( Events.Contains( eventName ) ) + { return; + } Events.Add( eventName ); } @@ -96,9 +110,10 @@ public class BaseControllerComponent : EntityComponent, ISingletonCompon Tags ??= new HashSet(); if ( Tags.Contains( tagName ) ) + { return; + } Tags.Add( tagName ); } } - diff --git a/code/pawn/component/movement/WalkControllerComponent.cs b/code/pawn/component/movement/WalkControllerComponent.cs index da4ad5b..3446c19 100644 --- a/code/pawn/component/movement/WalkControllerComponent.cs +++ b/code/pawn/component/movement/WalkControllerComponent.cs @@ -1,18 +1,48 @@ -using Sandbox; -using System; +using System; using System.Collections.Generic; +using Sandbox; namespace MurderGame; public partial class WalkControllerComponent : BaseControllerComponent { - public bool CanSprint - { - get - { - return TeamCapabilities.CanSprint( Entity.Team ); - } - } + public Transform? GroundTransform; + + public Transform? GroundTransformViewAngles; + + private bool IsTouchingLadder; + private Vector3 LadderNormal; + + private Vector3 LastNonZeroWishLadderVelocity; + private Vector3 LastNonZeroWishVelocity; + public Vector3 maxs; + + + // Duck body height 32 + // Eye Height 64 + // Duck Eye Height 28 + + public Vector3 mins; + public Entity? OldGroundEntity; + private Transform OldTransform; + [SkipHotload] private Dictionary OldTransforms; + + private Entity PreviousGroundEntity; + public Angles? PreviousViewAngles; + private readonly bool PushDebug = false; + + protected float SurfaceFriction; + + /// + /// Any bbox traces we do will be offset by this amount. + /// todo: this needs to be predicted + /// + public Vector3 TraceOffset; + + private int TryLatchNextTickCounter; + + public bool CanSprint => TeamCapabilities.CanSprint( Entity.Team ); + [Net] public float SprintSpeed { get; set; } = 320.0f; [Net] public float WalkSpeed { get; set; } = 150.0f; [Net] public float CrouchSpeed { get; set; } = 80.0f; @@ -37,62 +67,76 @@ public partial class WalkControllerComponent : BaseControllerComponent [Net] public float Gravity { get; set; } = 800.0f; [Net] public float AirControl { get; set; } = 30.0f; [Net] public float SpeedMultiplier { get; set; } = 1f; - [ConVar.Replicated( "walkcontroller_showbbox" )] public bool ShowBBox { get; set; } = false; - public bool Swimming { get; set; } = false; + + [ConVar.Replicated( "walkcontroller_showbbox" )] + public bool ShowBBox { get; set; } = false; + + public bool Swimming { get; set; } [Net] public bool AutoJump { get; set; } = false; public TimeSince TimeSinceFootstep { get; set; } public bool FootstepFoot { get; set; } - public WalkControllerComponent() - { - } + [Net] [Predicted] public bool IsDucking { get; set; } // replicate + [Net] [Predicted] public float DuckAmount { get; set; } + public float LocalDuckAmount { get; set; } + protected float WaterJumpTime { get; set; } + protected Vector3 WaterJumpVelocity { get; set; } + protected bool IsJumpingFromWater => WaterJumpTime > 0; + protected TimeSince TimeSinceSwimSound { get; set; } + protected float LastWaterLevel { get; set; } + + public virtual float WaterJumpHeight => 8; + + [ConVar.Replicated( "sv_ladderlatchdebug" )] + public static bool LatchDebug { get; set; } = false; + + public Vector3 GroundNormal { get; set; } /// - /// This is temporary, get the hull size for the player's collision + /// This is temporary, get the hull size for the player's collision /// public BBox GetHull() { var girth = BodyGirth * 0.5f; var height = BodyHeight; - if ( IsDucking ) height = 32; + if ( IsDucking ) + { + height = 32; + } + var mins = new Vector3( -girth, -girth, 0 ); var maxs = new Vector3( +girth, +girth, BodyHeight ); return new BBox( mins, maxs ); } - - // Duck body height 32 - // Eye Height 64 - // Duck Eye Height 28 - - public Vector3 mins; - public Vector3 maxs; - - /// - /// Any bbox traces we do will be offset by this amount. - /// todo: this needs to be predicted - /// - public Vector3 TraceOffset; - public virtual void SetBBox( Vector3 mins, Vector3 maxs ) { if ( this.mins == mins && this.maxs == maxs ) + { return; + } this.mins = mins; this.maxs = maxs; } /// - /// Update the size of the bbox. We should really trigger some shit if this changes. + /// Update the size of the bbox. We should really trigger some shit if this changes. /// public virtual void UpdateBBox( int forceduck = 0 ) { var girth = BodyGirth * 0.5f; - var height = (EyeHeight + DuckAmount) + (BodyHeight - EyeHeight); - if ( forceduck == 1 ) height = DuckHeight; - if ( forceduck == -1 ) height = BodyHeight; + var height = EyeHeight + DuckAmount + (BodyHeight - EyeHeight); + if ( forceduck == 1 ) + { + height = DuckHeight; + } + + if ( forceduck == -1 ) + { + height = BodyHeight; + } var mins = new Vector3( -girth, -girth, 0 ) * Entity.Scale; var maxs = new Vector3( +girth, +girth, height ) * Entity.Scale; @@ -100,27 +144,29 @@ public partial class WalkControllerComponent : BaseControllerComponent SetBBox( mins, maxs ); } - protected float SurfaceFriction; - public override void FrameSimulate( IClient cl ) { - if ( ShowBBox ) DebugOverlay.Box( Entity.Position, mins, maxs, Color.Yellow ); + if ( ShowBBox ) + { + DebugOverlay.Box( Entity.Position, mins, maxs, Color.Yellow ); + } + RestoreGroundAngles(); - var pl = Entity as Player; + var pl = Entity; SaveGroundAngles(); DuckFrameSimulate(); } public override void BuildInput() { - - var pl = Entity as Player; + var pl = Entity; pl.InputDirection = Input.AnalogMove; } + public override void Simulate( IClient cl ) { - var pl = Entity as Player; + var pl = Entity; Events?.Clear(); Tags?.Clear(); @@ -162,7 +208,7 @@ public partial class WalkControllerComponent : BaseControllerComponent // if ( !Swimming && !IsTouchingLadder ) { - Entity.Velocity -= new Vector3( 0, 0, (Gravity * Entity.Scale) * 0.5f ) * Time.Delta; + Entity.Velocity -= new Vector3( 0, 0, Gravity * Entity.Scale * 0.5f ) * Time.Delta; Entity.Velocity += new Vector3( 0, 0, Entity.BaseVelocity.z ) * Time.Delta; Entity.BaseVelocity = Entity.BaseVelocity.WithZ( 0 ); @@ -185,15 +231,14 @@ public partial class WalkControllerComponent : BaseControllerComponent { WaterSimulate(); } - else - if ( AutoJump ? Input.Down( "Jump" ) : Input.Pressed( "Jump" ) ) + else if ( AutoJump ? Input.Down( "Jump" ) : Input.Pressed( "Jump" ) ) { CheckJumpButton(); } // Fricion is handled before we add in any base velocity. That way, if we are on a conveyor, // we don't slow when standing still, relative to the conveyor. - bool bStartOnGround = Entity.GroundEntity != null; + var bStartOnGround = Entity.GroundEntity != null; //bool bDropSound = false; if ( bStartOnGround ) { @@ -216,12 +261,10 @@ public partial class WalkControllerComponent : BaseControllerComponent if ( Swimming || IsTouchingLadder ) { - WishVelocity *= pl.ViewAngles.ToRotation(); } else { - WishVelocity *= pl.ViewAngles.WithPitch( 0 ).ToRotation(); } @@ -237,10 +280,10 @@ public partial class WalkControllerComponent : BaseControllerComponent WishVelocity *= SpeedMultiplier; - bool bStayOnGround = false; + var bStayOnGround = false; if ( Swimming ) { - ApplyFriction( 1 ); + ApplyFriction(); WaterMove(); } else if ( IsTouchingLadder ) @@ -263,7 +306,7 @@ public partial class WalkControllerComponent : BaseControllerComponent // FinishGravity if ( !Swimming && !IsTouchingLadder ) { - Entity.Velocity -= new Vector3( 0, 0, (Gravity * Entity.Scale) * 0.5f ) * Time.Delta; + Entity.Velocity -= new Vector3( 0, 0, Gravity * Entity.Scale * 0.5f ) * Time.Delta; } @@ -271,8 +314,12 @@ public partial class WalkControllerComponent : BaseControllerComponent { Entity.Velocity = Entity.Velocity.WithZ( 0 ); } + DoPushingStuff(); - if ( Entity == null ) return; + if ( Entity == null ) + { + return; + } // CheckFalling(); // fall damage etc @@ -283,34 +330,51 @@ public partial class WalkControllerComponent : BaseControllerComponent LatchOntoLadder(); PreviousGroundEntity = Entity.GroundEntity; - bool Debug = false; + var Debug = false; if ( Debug ) { DebugOverlay.Box( Entity.Position + TraceOffset, mins, maxs, Color.Red ); DebugOverlay.Box( Entity.Position, mins, maxs, Color.Blue ); var lineOffset = 0; - if ( Game.IsServer ) lineOffset = 10; + if ( Game.IsServer ) + { + lineOffset = 10; + } DebugOverlay.ScreenText( $" Position: {Entity.Position}", lineOffset + 0 ); DebugOverlay.ScreenText( $" Velocity: {Entity.Velocity}", lineOffset + 1 ); DebugOverlay.ScreenText( $" BaseVelocity: {Entity.BaseVelocity}", lineOffset + 2 ); - DebugOverlay.ScreenText( $" GroundEntity: {Entity.GroundEntity} [{Entity.GroundEntity?.Velocity}]", lineOffset + 3 ); + DebugOverlay.ScreenText( $" GroundEntity: {Entity.GroundEntity} [{Entity.GroundEntity?.Velocity}]", + lineOffset + 3 ); DebugOverlay.ScreenText( $" SurfaceFriction: {SurfaceFriction}", lineOffset + 4 ); DebugOverlay.ScreenText( $" WishVelocity: {WishVelocity}", lineOffset + 5 ); DebugOverlay.ScreenText( $" Speed: {Entity.Velocity.Length}", lineOffset + 6 ); } - } public virtual float GetWishSpeed() { - var ws = -1;// Duck.GetWishSpeed(); - if ( ws >= 0 ) return ws; + var ws = -1; // Duck.GetWishSpeed(); + if ( ws >= 0 ) + { + return ws; + } - if ( Input.Down( "Duck" ) || IsDucking ) return CrouchSpeed; - if ( Input.Down( "Run" ) && CanSprint ) return SprintSpeed; - if ( Input.Down( "Walk" ) ) return WalkSpeed; + if ( Input.Down( "Duck" ) || IsDucking ) + { + return CrouchSpeed; + } + + if ( Input.Down( "Run" ) && CanSprint ) + { + return SprintSpeed; + } + + if ( Input.Down( "Walk" ) ) + { + return WalkSpeed; + } return DefaultSpeed; } @@ -336,22 +400,23 @@ public partial class WalkControllerComponent : BaseControllerComponent // DebugOverlay.Text( 0, Pos + Vector3.Up * 100, $"forward: {Input.Forward}\nsideward: {Input.Right}" ); // Add in any base velocity to the current velocity. - if (Entity.Velocity.Length != 0) + if ( Entity.Velocity.Length != 0 ) { var footstepTimeThreshold = 60f / Entity.Velocity.Length; - if (TimeSinceFootstep > footstepTimeThreshold) + if ( TimeSinceFootstep > footstepTimeThreshold ) { var trace = Trace.Ray( Entity.Position, Entity.Position + Vector3.Down * 20f ) .Radius( 1f ) .Ignore( Entity ) .Run(); - if (trace.Hit) + if ( trace.Hit ) { FootstepFoot = !FootstepFoot; - trace.Surface.DoFootstep( Entity, trace, FootstepFoot ? 1 : 0, 35f * (Entity.Velocity.Length / SprintSpeed) ); + trace.Surface.DoFootstep( Entity, trace, FootstepFoot ? 1 : 0, + 35f * (Entity.Velocity.Length / SprintSpeed) ); TimeSinceFootstep = 0; } @@ -380,23 +445,21 @@ public partial class WalkControllerComponent : BaseControllerComponent } StepMove(); - } finally { - // Now pull the base velocity back out. Base velocity is set if you are on a moving object, like a conveyor (or maybe another monster?) Entity.Velocity -= Entity.BaseVelocity; } StayOnGround(); - Entity.Velocity = Entity.Velocity.Normal * MathF.Min( Entity.Velocity.Length, (GetWishSpeed() * Entity.Scale) ); + Entity.Velocity = Entity.Velocity.Normal * MathF.Min( Entity.Velocity.Length, GetWishSpeed() * Entity.Scale ); } public virtual void StepMove() { - MoveHelper mover = new MoveHelper( Entity.Position, Entity.Velocity ); + var mover = new MoveHelper( Entity.Position, Entity.Velocity ); mover.Trace = mover.Trace.Size( mins, maxs ).Ignore( Entity ); mover.MaxStandableAngle = GroundAngle; @@ -408,7 +471,7 @@ public partial class WalkControllerComponent : BaseControllerComponent public virtual void Move() { - MoveHelper mover = new MoveHelper( Entity.Position, Entity.Velocity ); + var mover = new MoveHelper( Entity.Position, Entity.Velocity ); mover.Trace = mover.Trace.Size( mins, maxs ).Ignore( Entity ); mover.MaxStandableAngle = GroundAngle; @@ -419,7 +482,7 @@ public partial class WalkControllerComponent : BaseControllerComponent } /// - /// Add our wish direction and speed onto our velocity + /// Add our wish direction and speed onto our velocity /// public virtual void Accelerate( Vector3 wishdir, float wishspeed, float speedLimit, float acceleration ) { @@ -430,7 +493,9 @@ public partial class WalkControllerComponent : BaseControllerComponent speedLimit *= Entity.Scale; acceleration /= Entity.Scale; if ( speedLimit > 0 && wishspeed > speedLimit ) + { wishspeed = speedLimit; + } // See if we are changing direction a bit var currentspeed = Entity.Velocity.Dot( wishdir ); @@ -440,20 +505,24 @@ public partial class WalkControllerComponent : BaseControllerComponent // If not going to add any speed, done. if ( addspeed <= 0 ) + { return; + } // Determine amount of acceleration. - var accelspeed = (acceleration * Entity.Scale) * Time.Delta * wishspeed * SurfaceFriction; + var accelspeed = acceleration * Entity.Scale * Time.Delta * wishspeed * SurfaceFriction; // Cap at addspeed if ( accelspeed > addspeed ) + { accelspeed = addspeed; + } Entity.Velocity += wishdir * accelspeed; } /// - /// Remove ground friction from velocity + /// Remove ground friction from velocity /// public virtual void ApplyFriction( float frictionAmount = 1.0f ) { @@ -463,18 +532,24 @@ public partial class WalkControllerComponent : BaseControllerComponent // Not on ground - no friction // Calculate speed var speed = Entity.Velocity.Length; - if ( speed < 0.1f ) return; + if ( speed < 0.1f ) + { + return; + } // Bleed off some speed, but if we have less than the bleed // threshold, bleed the threshold amount. - float control = (speed < StopSpeed * Entity.Scale) ? (StopSpeed * Entity.Scale) : speed; + var control = speed < StopSpeed * Entity.Scale ? StopSpeed * Entity.Scale : speed; // Add the amount to the drop amount. var drop = control * Time.Delta * frictionAmount; // scale the velocity - float newspeed = speed - drop; - if ( newspeed < 0 ) newspeed = 0; + var newspeed = speed - drop; + if ( newspeed < 0 ) + { + newspeed = 0; + } if ( newspeed != speed ) { @@ -485,17 +560,21 @@ public partial class WalkControllerComponent : BaseControllerComponent // mv->m_outWishVel -= (1.f-newspeed) * mv->m_vecVelocity; } - [Net, Predicted] public bool IsDucking { get; set; } // replicate - [Net, Predicted] public float DuckAmount { get; set; } = 0; public virtual void CheckDuck() { - var pl = Entity as Player; - bool wants = Input.Down( "Duck" ); + var pl = Entity; + var wants = Input.Down( "Duck" ); if ( wants != IsDucking ) { - if ( wants ) TryDuck(); - else TryUnDuck(); + if ( wants ) + { + TryDuck(); + } + else + { + TryUnDuck(); + } } if ( IsDucking ) @@ -513,6 +592,7 @@ public partial class WalkControllerComponent : BaseControllerComponent pl.Position -= Vector3.Up * (delta * Entity.Scale); } } + FixPlayerCrouchStuck( true ); CategorizePosition( false ); } @@ -532,16 +612,16 @@ public partial class WalkControllerComponent : BaseControllerComponent pl.Position -= Vector3.Up * (delta * Entity.Scale); } } + CategorizePosition( false ); } - pl.EyeLocalPosition = pl.EyeLocalPosition.WithZ( EyeHeight + (DuckAmount) ); + pl.EyeLocalPosition = pl.EyeLocalPosition.WithZ( EyeHeight + DuckAmount ); } - public float LocalDuckAmount { get; set; } = 0; - void DuckFrameSimulate() - { - var pl = Entity as Player; + private void DuckFrameSimulate() + { + var pl = Entity; if ( IsDucking ) { LocalDuckAmount = LocalDuckAmount.LerpTo( (EyeHeight - DuckEyeHeight) * -1, 8 * Time.Delta ); @@ -550,8 +630,10 @@ public partial class WalkControllerComponent : BaseControllerComponent { LocalDuckAmount = LocalDuckAmount.LerpTo( 0, 8 * Time.Delta ); } + pl.EyeLocalPosition = pl.EyeLocalPosition.WithZ( EyeHeight + LocalDuckAmount ); } + public virtual void TryDuck() { IsDucking = true; @@ -566,19 +648,22 @@ public partial class WalkControllerComponent : BaseControllerComponent UpdateBBox(); return; } + IsDucking = false; } public virtual void FixPlayerCrouchStuck( bool upward ) { - int direction = upward ? 1 : 0; + var direction = upward ? 1 : 0; var trace = TraceBBox( Entity.Position, Entity.Position ); if ( trace.Entity == null ) + { return; + } var test = Entity.Position; - for ( int i = 0; i < (DuckHeight - 4); i++ ) + for ( var i = 0; i < DuckHeight - 4; i++ ) { var org = Entity.Position; org.z += direction; @@ -586,11 +671,14 @@ public partial class WalkControllerComponent : BaseControllerComponent Entity.Position = org; trace = TraceBBox( Entity.Position, Entity.Position ); if ( trace.Entity == null ) + { return; + } } Entity.Position = test; } + public virtual void CheckJumpButton() { //if ( !player->CanJump() ) @@ -608,7 +696,6 @@ public partial class WalkControllerComponent : BaseControllerComponent }*/ - // If we are in the water most of the way... if ( Swimming ) { @@ -629,7 +716,9 @@ public partial class WalkControllerComponent : BaseControllerComponent } if ( Entity.GroundEntity == null ) + { return; + } /* if ( player->m_Local.m_bDucking && (player->GetFlags() & FL_DUCKING) ) @@ -648,18 +737,18 @@ public partial class WalkControllerComponent : BaseControllerComponent // MoveHelper()->PlayerSetAnimation( PLAYER_JUMP ); - float flGroundFactor = 1.0f; + var flGroundFactor = 1.0f; //if ( player->m_pSurfaceData ) { // flGroundFactor = g_pPhysicsQuery->GetGameSurfaceproperties( player->m_pSurfaceData )->m_flJumpFactor; } - float flMul = (268.3281572999747f * Entity.Scale) * 1.2f; - float startz = Entity.Velocity.z; + var flMul = 268.3281572999747f * Entity.Scale * 1.2f; + var startz = Entity.Velocity.z; Entity.Velocity = Entity.Velocity.WithZ( startz + flMul * flGroundFactor ); - Entity.Velocity -= new Vector3( 0, 0, (Gravity * Entity.Scale) * 0.5f ) * Time.Delta; + Entity.Velocity -= new Vector3( 0, 0, Gravity * Entity.Scale * 0.5f ) * Time.Delta; // mv->m_outJumpVel.z += mv->m_vecVelocity[2] - startz; // mv->m_outStepHeight += 0.15f; @@ -668,8 +757,8 @@ public partial class WalkControllerComponent : BaseControllerComponent //mv->m_nOldButtons |= IN_JUMP; AddEvent( "jump" ); - } + public virtual void WaterSimulate() { if ( Entity.GetWaterLevel() > 0.4 ) @@ -678,7 +767,7 @@ public partial class WalkControllerComponent : BaseControllerComponent } // If we are falling again, then we must not trying to jump out of water any more. - if ( (Entity.Velocity.z < 0.0f) && IsJumpingFromWater ) + if ( Entity.Velocity.z < 0.0f && IsJumpingFromWater ) { WaterJumpTime = 0.0f; } @@ -688,25 +777,24 @@ public partial class WalkControllerComponent : BaseControllerComponent { CheckJumpButton(); } + SetTag( "swimming" ); } - protected float WaterJumpTime { get; set; } - protected Vector3 WaterJumpVelocity { get; set; } - protected bool IsJumpingFromWater => WaterJumpTime > 0; - protected TimeSince TimeSinceSwimSound { get; set; } - protected float LastWaterLevel { get; set; } - public virtual float WaterJumpHeight => 8; protected void CheckWaterJump() { // Already water jumping. if ( IsJumpingFromWater ) + { return; + } // Don't hop out if we just jumped in // only hop out if we are moving up if ( Entity.Velocity.z < -180 ) + { return; + } // See if we are backing up var flatvelocity = Entity.Velocity.WithZ( 0 ); @@ -720,14 +808,18 @@ public partial class WalkControllerComponent : BaseControllerComponent // Are we backing into water from steps or something? If so, don't pop forward if ( curspeed != 0 && Vector3.Dot( flatvelocity, flatforward ) < 0 ) + { return; + } var vecStart = Entity.Position + (mins + maxs) * .5f; var vecEnd = vecStart + flatforward * 24; var tr = TraceBBox( vecStart, vecEnd ); if ( tr.Fraction == 1 ) + { return; + } vecStart.z = Entity.Position.z + EyeHeight + WaterJumpHeight; vecEnd = vecStart + flatforward * 24; @@ -735,7 +827,9 @@ public partial class WalkControllerComponent : BaseControllerComponent tr = TraceBBox( vecStart, vecEnd ); if ( tr.Fraction < 1.0 ) + { return; + } // Now trace down to see if we would actually land on a standable surface. vecStart = vecEnd; @@ -749,6 +843,7 @@ public partial class WalkControllerComponent : BaseControllerComponent WaterJumpTime = 2000; } } + public virtual void AirMove() { var wishdir = WishVelocity.Normal; @@ -779,20 +874,21 @@ public partial class WalkControllerComponent : BaseControllerComponent Entity.Velocity -= Entity.BaseVelocity; } - bool IsTouchingLadder = false; - Vector3 LadderNormal; - - Vector3 LastNonZeroWishLadderVelocity; public virtual void CheckLadder() { - var pl = Entity as Player; + var pl = Entity; var wishvel = new Vector3( pl.InputDirection.x.Clamp( -1f, 1f ), pl.InputDirection.y.Clamp( -1f, 1f ), 0 ); if ( wishvel.Length > 0 ) { LastNonZeroWishLadderVelocity = wishvel; } - if ( TryLatchNextTickCounter > 0 ) wishvel = LastNonZeroWishLadderVelocity * -1; + + if ( TryLatchNextTickCounter > 0 ) + { + wishvel = LastNonZeroWishLadderVelocity * -1; + } + wishvel *= pl.ViewAngles.WithPitch( 0 ).ToRotation(); wishvel = wishvel.Normal; @@ -810,13 +906,13 @@ public partial class WalkControllerComponent : BaseControllerComponent Eject.y = LadderNormal.y * sidem; Eject.z = (3 * upm).Clamp( 0, 1 ); - Entity.Velocity += (Eject * 180.0f) * Entity.Scale; + Entity.Velocity += Eject * 180.0f * Entity.Scale; IsTouchingLadder = false; return; - } - else if ( Entity.GroundEntity != null && LadderNormal.Dot( wishvel ) > 0 ) + + if ( Entity.GroundEntity != null && LadderNormal.Dot( wishvel ) > 0 ) { IsTouchingLadder = false; @@ -826,13 +922,13 @@ public partial class WalkControllerComponent : BaseControllerComponent const float ladderDistance = 1.0f; var start = Entity.Position; - Vector3 end = start + (IsTouchingLadder ? (LadderNormal * -1.0f) : wishvel) * ladderDistance; + var end = start + (IsTouchingLadder ? LadderNormal * -1.0f : wishvel) * ladderDistance; var pm = Trace.Ray( start, end ) - .Size( mins, maxs ) - .WithTag( "ladder" ) - .Ignore( Entity ) - .Run(); + .Size( mins, maxs ) + .WithTag( "ladder" ) + .Ignore( Entity ) + .Run(); IsTouchingLadder = false; @@ -842,58 +938,70 @@ public partial class WalkControllerComponent : BaseControllerComponent LadderNormal = pm.Normal; } } + public virtual void LadderMove() { var velocity = WishVelocity; - float normalDot = velocity.Dot( LadderNormal ); + var normalDot = velocity.Dot( LadderNormal ); var cross = LadderNormal * normalDot; - Entity.Velocity = (velocity - cross) + (-normalDot * LadderNormal.Cross( Vector3.Up.Cross( LadderNormal ).Normal )); + Entity.Velocity = velocity - cross + -normalDot * LadderNormal.Cross( Vector3.Up.Cross( LadderNormal ).Normal ); Move(); } - Entity PreviousGroundEntity; - int TryLatchNextTickCounter = 0; - Vector3 LastNonZeroWishVelocity; - [ConVar.Replicated( "sv_ladderlatchdebug" )] - public static bool LatchDebug { get; set; } = false; public virtual void LatchOntoLadder() { if ( !WishVelocity.Normal.IsNearlyZero( 0.001f ) ) { LastNonZeroWishVelocity = WishVelocity; } + if ( TryLatchNextTickCounter > 0 ) { - Entity.Velocity = (LastNonZeroWishVelocity.Normal * -100).WithZ( Entity.Velocity.z ); TryLatchNextTickCounter++; } + if ( TryLatchNextTickCounter >= 10 ) { TryLatchNextTickCounter = 0; } - if ( Entity.GroundEntity != null ) return; - if ( PreviousGroundEntity == null ) return; - var pos = Entity.Position + (Vector3.Down * 16); + if ( Entity.GroundEntity != null ) + { + return; + } + + if ( PreviousGroundEntity == null ) + { + return; + } + + var pos = Entity.Position + Vector3.Down * 16; //var tr = TraceBBox( pos, pos ); - var tr = Trace.Ray( pos, pos - (LastNonZeroWishVelocity.Normal * 8) ) - .Size( mins, maxs ) - .WithTag( "ladder" ) - .Ignore( Entity ) - .Run(); + var tr = Trace.Ray( pos, pos - LastNonZeroWishVelocity.Normal * 8 ) + .Size( mins, maxs ) + .WithTag( "ladder" ) + .Ignore( Entity ) + .Run(); + + if ( LatchDebug ) + { + DebugOverlay.Line( Entity.Position, pos, 10 ); + } + + if ( LatchDebug ) + { + DebugOverlay.Line( tr.StartPosition, tr.EndPosition, 10 ); + } - if ( LatchDebug ) DebugOverlay.Line( Entity.Position, pos, 10 ); - if ( LatchDebug ) DebugOverlay.Line( tr.StartPosition, tr.EndPosition, 10 ); if ( tr.Hit ) { Entity.Velocity = Vector3.Zero.WithZ( Entity.Velocity.z ); TryLatchNextTickCounter++; } - } @@ -914,10 +1022,10 @@ public partial class WalkControllerComponent : BaseControllerComponent // // Shooting up really fast. Definitely not on ground trimed until ladder shit // - bool bMovingUpRapidly = Entity.Velocity.z > MaxNonJumpVelocity; - bool bMovingUp = Entity.Velocity.z > 0; + var bMovingUpRapidly = Entity.Velocity.z > MaxNonJumpVelocity; + var bMovingUp = Entity.Velocity.z > 0; - bool bMoveToEndPos = false; + var bMoveToEndPos = false; if ( Entity.GroundEntity != null ) // and not underwater { @@ -944,7 +1052,9 @@ public partial class WalkControllerComponent : BaseControllerComponent bMoveToEndPos = false; if ( Entity.Velocity.z > 0 ) + { SurfaceFriction = 0.25f; + } } else { @@ -955,12 +1065,10 @@ public partial class WalkControllerComponent : BaseControllerComponent { Entity.Position = pm.EndPosition; } - } - public Vector3 GroundNormal { get; set; } /// - /// We have a new ground entity + /// We have a new ground entity /// public virtual void UpdateGroundEntity( TraceResult tr ) { @@ -970,14 +1078,20 @@ public partial class WalkControllerComponent : BaseControllerComponent // A value of 0.8f feels pretty normal for vphysics, whereas 1.0f is normal for players. // This scaling trivially makes them equivalent. REVISIT if this affects low friction surfaces too much. SurfaceFriction = tr.Surface.Friction * 1.25f; - if ( SurfaceFriction > 1 ) SurfaceFriction = 1; + if ( SurfaceFriction > 1 ) + { + SurfaceFriction = 1; + } //if ( tr.Entity == GroundEntity ) return; Vector3 oldGroundVelocity = default; - if ( Entity.GroundEntity != null ) oldGroundVelocity = Entity.GroundEntity.Velocity; + if ( Entity.GroundEntity != null ) + { + oldGroundVelocity = Entity.GroundEntity.Velocity; + } - bool wasOffGround = Entity.GroundEntity == null; + var wasOffGround = Entity.GroundEntity == null; Entity.GroundEntity = tr.Entity; @@ -988,11 +1102,14 @@ public partial class WalkControllerComponent : BaseControllerComponent } /// - /// We're no longer on the ground, remove it + /// We're no longer on the ground, remove it /// public virtual void ClearGroundEntity() { - if ( Entity.GroundEntity == null ) return; + if ( Entity.GroundEntity == null ) + { + return; + } Entity.GroundEntity = null; GroundNormal = Vector3.Up; @@ -1000,9 +1117,9 @@ public partial class WalkControllerComponent : BaseControllerComponent } /// - /// Traces the current bbox and returns the result. - /// liftFeet will move the start position up by this amount, while keeping the top of the bbox at the same - /// position. This is good when tracing down because you won't be tracing through the ceiling above. + /// Traces the current bbox and returns the result. + /// liftFeet will move the start position up by this amount, while keeping the top of the bbox at the same + /// position. This is good when tracing down because you won't be tracing through the ceiling above. /// public virtual TraceResult TraceBBox( Vector3 start, Vector3 end, float liftFeet = 0.0f ) { @@ -1010,11 +1127,12 @@ public partial class WalkControllerComponent : BaseControllerComponent } /// - /// Traces the bbox and returns the trace result. - /// LiftFeet will move the start position up by this amount, while keeping the top of the bbox at the same - /// position. This is good when tracing down because you won't be tracing through the ceiling above. + /// Traces the bbox and returns the trace result. + /// LiftFeet will move the start position up by this amount, while keeping the top of the bbox at the same + /// position. This is good when tracing down because you won't be tracing through the ceiling above. /// - public virtual TraceResult TraceBBox( Vector3 start, Vector3 end, Vector3 mins, Vector3 maxs, float liftFeet = 0.0f ) + public virtual TraceResult TraceBBox( Vector3 start, Vector3 end, Vector3 mins, Vector3 maxs, + float liftFeet = 0.0f ) { if ( liftFeet > 0 ) { @@ -1024,17 +1142,17 @@ public partial class WalkControllerComponent : BaseControllerComponent } var tr = Trace.Ray( start + TraceOffset, end + TraceOffset ) - .Size( mins, maxs ) - .WithAnyTags( "solid", "playerclip", "passbullets", "player" ) - .Ignore( Entity ) - .Run(); + .Size( mins, maxs ) + .WithAnyTags( "solid", "playerclip", "passbullets", "player" ) + .Ignore( Entity ) + .Run(); tr.EndPosition -= TraceOffset; return tr; } /// - /// Try to keep a walking player on the ground when running down slopes etc + /// Try to keep a walking player on the ground when running down slopes etc /// public virtual void StayOnGround() { @@ -1048,10 +1166,25 @@ public partial class WalkControllerComponent : BaseControllerComponent // Now trace down from a known safe position trace = TraceBBox( start, end ); - if ( trace.Fraction <= 0 ) return; - if ( trace.Fraction >= 1 ) return; - if ( trace.StartedSolid ) return; - if ( Vector3.GetAngle( Vector3.Up, trace.Normal ) > GroundAngle ) return; + if ( trace.Fraction <= 0 ) + { + return; + } + + if ( trace.Fraction >= 1 ) + { + return; + } + + if ( trace.StartedSolid ) + { + return; + } + + if ( Vector3.GetAngle( Vector3.Up, trace.Normal ) > GroundAngle ) + { + return; + } // This is incredibly hacky. The real problem is that trace returning that strange value we can't network over. // float flDelta = fabs( mv->GetAbsOrigin().z - trace.m_vEndPos.z ); @@ -1060,24 +1193,25 @@ public partial class WalkControllerComponent : BaseControllerComponent Entity.Position = trace.EndPosition; } - public Transform? GroundTransform; - public Sandbox.Entity? OldGroundEntity; - void RestoreGroundPos() + private void RestoreGroundPos() { - if ( Entity.GroundEntity == null || Entity.GroundEntity.IsWorld || GroundTransform == null || Entity.GroundEntity != OldGroundEntity ) + if ( Entity.GroundEntity == null || Entity.GroundEntity.IsWorld || GroundTransform == null || + Entity.GroundEntity != OldGroundEntity ) + { return; + } var worldTrns = Entity.GroundEntity.Transform.ToWorld( GroundTransform.Value ); if ( Prediction.FirstTime ) { - Entity.BaseVelocity = ((Entity.Position - worldTrns.Position) * -1) / Time.Delta; + Entity.BaseVelocity = (Entity.Position - worldTrns.Position) * -1 / Time.Delta; } //Entity.Position = (Entity.Position.WithZ( worldTrns.Position.z )); } - void SaveGroundPos() + private void SaveGroundPos() { - var ply = Entity as Player; + var ply = Entity; if ( Entity.GroundEntity == null || Entity.GroundEntity.IsWorld ) { OldGroundEntity = null; @@ -1094,60 +1228,66 @@ public partial class WalkControllerComponent : BaseControllerComponent GroundTransform = null; GroundTransformViewAngles = null; } + OldGroundEntity = Entity.GroundEntity; } - public Transform? GroundTransformViewAngles; - public Angles? PreviousViewAngles; - void RestoreGroundAngles() + private void RestoreGroundAngles() { - if ( Entity.GroundEntity == null || Entity.GroundEntity.IsWorld || GroundTransformViewAngles == null || PreviousViewAngles == null ) + if ( Entity.GroundEntity == null || Entity.GroundEntity.IsWorld || GroundTransformViewAngles == null || + PreviousViewAngles == null ) + { return; + } - var ply = Entity as Player; + var ply = Entity; var worldTrnsView = Entity.GroundEntity.Transform.ToWorld( GroundTransformViewAngles.Value ); - ply.ViewAngles -= (PreviousViewAngles.Value.ToRotation() * worldTrnsView.Rotation.Inverse).Angles().WithPitch( 0 ).WithRoll( 0 ); + ply.ViewAngles -= (PreviousViewAngles.Value.ToRotation() * worldTrnsView.Rotation.Inverse).Angles() + .WithPitch( 0 ).WithRoll( 0 ); } - void SaveGroundAngles() - { + private void SaveGroundAngles() + { if ( Entity.GroundEntity == null || Entity.GroundEntity.IsWorld ) { GroundTransformViewAngles = null; return; } - var ply = Entity as Player; - GroundTransformViewAngles = Entity.GroundEntity.Transform.ToLocal( new Transform( Vector3.Zero, ply.ViewAngles.ToRotation() ) ); + var ply = Entity; + GroundTransformViewAngles = + Entity.GroundEntity.Transform.ToLocal( new Transform( Vector3.Zero, ply.ViewAngles.ToRotation() ) ); PreviousViewAngles = ply.ViewAngles; } - bool PushDebug = false; - [SkipHotload] Dictionary OldTransforms; - Transform OldTransform; - void DoPushingStuff() + + private void DoPushingStuff() { var tr = TraceBBox( Entity.Position, Entity.Position ); if ( tr.StartedSolid - && tr.Entity != null - && tr.Entity != OldGroundEntity - && tr.Entity != Entity.GroundEntity - && !tr.Entity.IsWorld - && OldTransforms != null - && OldTransforms.TryGetValue( tr.Entity.NetworkIdent, out var oldTransform ) ) - { - if ( tr.Entity is BasePhysics ) return; + && tr.Entity != null + && tr.Entity != OldGroundEntity + && tr.Entity != Entity.GroundEntity + && !tr.Entity.IsWorld + && OldTransforms != null + && OldTransforms.TryGetValue( tr.Entity.NetworkIdent, out var oldTransform ) ) + { + if ( tr.Entity is BasePhysics ) + { + return; + } + var oldPosition = Entity.Position; var oldTransformLocal = oldTransform.ToLocal( Entity.Transform ); var newTransform = tr.Entity.Transform.ToWorld( oldTransformLocal ); // this used to be just the direction of the tr delta however pushing outwards a llittle seems more appropriate - var direction = ((Entity.Position - newTransform.Position) * -1); + var direction = (Entity.Position - newTransform.Position) * -1; direction += (Entity.Position - tr.Entity.Position).Normal.WithZ( 0 ) * 0.8f; FindIdealMovementDirection( newTransform.Position, direction, out var outOffset, out var outDirection ); - var newPosition = newTransform.Position + (outDirection * outOffset) + (outDirection * 0.1f); + var newPosition = newTransform.Position + outDirection * outOffset + outDirection * 0.1f; // Check if we're being crushed, if not we set our position. if ( IsBeingCrushed( newPosition ) ) @@ -1156,11 +1296,10 @@ public partial class WalkControllerComponent : BaseControllerComponent } else { - Entity.Velocity += (outDirection / Time.Delta); + Entity.Velocity += outDirection / Time.Delta; // insurance we dont instantly get stuck again add a little extra. Entity.Position = newPosition; - } } @@ -1169,7 +1308,8 @@ public partial class WalkControllerComponent : BaseControllerComponent GetPossibleTransforms(); } - void FindIdealMovementDirection( Vector3 Position, Vector3 Direction, out float OutOffset, out Vector3 OutDirection ) + private void FindIdealMovementDirection( Vector3 Position, Vector3 Direction, out float OutOffset, + out Vector3 OutDirection ) { OutDirection = Direction; OutOffset = 0; @@ -1177,55 +1317,72 @@ public partial class WalkControllerComponent : BaseControllerComponent // look into doing this nicer at somepoint // ------------------------------------------------------ // brute force our way into finding how much extra we need to be pushed in the case of AABB edges being still inside of the object - for ( int i = 0; i < 512; i++ ) + for ( var i = 0; i < 512; i++ ) { - var possibleoffset = (float)(i) / 16f; - var pos = Position + (Direction * possibleoffset); + var possibleoffset = i / 16f; + var pos = Position + Direction * possibleoffset; var offsettr = TraceBBox( pos, pos ); if ( !offsettr.StartedSolid ) { - if ( PushDebug ) DebugOverlay.Line( Entity.Position, pos, Color.Green, 5 ); + if ( PushDebug ) + { + DebugOverlay.Line( Entity.Position, pos, Color.Green, 5 ); + } + OutDirection = Direction; OutOffset = possibleoffset; break; } //sidewards test, for things moving sideways and upwards or downwards - var posside = Position + (Direction.WithZ( 0 ) * possibleoffset); + var posside = Position + Direction.WithZ( 0 ) * possibleoffset; var offsettrside = TraceBBox( posside, posside ); if ( !offsettrside.StartedSolid ) { - if ( PushDebug ) DebugOverlay.Line( Entity.Position, pos, Color.Green, 5 ); + if ( PushDebug ) + { + DebugOverlay.Line( Entity.Position, pos, Color.Green, 5 ); + } + OutDirection = Direction.WithZ( 0 ); OutOffset = possibleoffset; break; } - if ( PushDebug ) DebugOverlay.Line( Entity.Position, pos, Color.Red, 5 ); + if ( PushDebug ) + { + DebugOverlay.Line( Entity.Position, pos, Color.Red, 5 ); + } } // ------------------------------------------------------ } - bool IsBeingCrushed( Vector3 NewPosition ) + private bool IsBeingCrushed( Vector3 NewPosition ) { //do a trace that will decide whether or not we're being crushed var crushtrace = Trace.Ray( Entity.Position, NewPosition ) - .Ignore( Entity ) - .Run(); + .Ignore( Entity ) + .Run(); - if ( PushDebug ) DebugOverlay.Line( crushtrace.StartPosition, crushtrace.EndPosition, Color.Blue, 5 ); + if ( PushDebug ) + { + DebugOverlay.Line( crushtrace.StartPosition, crushtrace.EndPosition, Color.Blue, 5 ); + } return crushtrace.Fraction != 1; } - void OnCrushed( Entity CurshingEntity ) + private void OnCrushed( Entity CurshingEntity ) { // deal crush damage! - if ( !Game.IsServer ) return; + if ( !Game.IsServer ) + { + return; + } //if ( CurshingEntity is DoorEntity || CurshingEntity is PlatformEntity || CurshingEntity is PathPlatformEntity ) //{ // Entity.TakeDamage( DamageInfo.Generic( 5 ).WithTag( "crush" ) ); @@ -1352,17 +1509,16 @@ public partial class WalkControllerComponent : BaseControllerComponent GetPossibleTransforms(); }*/ - void GetPossibleTransforms() + private void GetPossibleTransforms() { - var a = Sandbox.Entity.FindInSphere( Entity.Position, 512 + Entity.Velocity.Length ); var b = new Dictionary(); foreach ( var i in a ) { b.Add( i.NetworkIdent, i.Transform ); } + OldTransforms = b; OldTransform = Entity.Transform; } } - diff --git a/code/phase/AssignPhase.cs b/code/phase/AssignPhase.cs index 90a8000..15891dc 100644 --- a/code/phase/AssignPhase.cs +++ b/code/phase/AssignPhase.cs @@ -1,20 +1,31 @@ -using Sandbox; -using Sandbox.UI; -using System; +using System; using System.Collections.Generic; using System.Linq; +using Sandbox; +using Sandbox.UI; namespace MurderGame; public partial class AssignPhase : BasePhase { - public override string Title => "Assigning teams"; - public int TicksElapsed; - - private List NatoNames = new() + private readonly List Colors = new() { - "Alpha", - "Bravo", + 0x0074D9, // blue + 0x7FDBFF, // aqua + 0x39CCCC, // teal + 0xF012BE, // fuchsia + 0xFF4136, // red + 0xFF851B, // orange + 0xFFDC00, // yellow + 0x3D9970, // olive + 0x2ECC40, // lime + 0x01FF70 // green + }; + + private readonly List NatoNames = new() + { + "Alpha", + "Bravo", "Charlie", "Delta", "Echo", @@ -40,77 +51,69 @@ public partial class AssignPhase : BasePhase "Yankee", "Zulu" }; - - private List Colors = new() - { - 0x0074D9, // blue - 0x7FDBFF, // aqua - 0x39CCCC, // teal - 0xF012BE, // fuchsia - 0xFF4136, // red - 0xFF851B, // orange - 0xFFDC00, // yellow - 0x3D9970, // olive - 0x2ECC40, // lime - 0x01FF70 // green - }; + + public int TicksElapsed; + public override string Title => "Assigning teams"; public override void Activate() { // cleanup -- start - foreach (var entity in Entity.All.OfType()) + foreach ( var entity in Entity.All.OfType() ) { entity.Delete(); } + DeleteFootprints(); // cleanup -- end var detectivesNeeded = 1; var murderersNeeded = 1; - + Random random = new(Guid.NewGuid().GetHashCode()); - + var spawnPoints = Entity.All.OfType().OrderBy( _ => random.Next() ).ToList(); var clients = Game.Clients.ToList().OrderBy( _ => random.Next() ); - var natoNamesRemaining = new List(NatoNames.OrderBy( _ => random.Next() )); - var colorsRemaining = new List(Colors.OrderBy( _ => random.Next() )); + var natoNamesRemaining = new List( NatoNames.OrderBy( _ => random.Next() ) ); + var colorsRemaining = new List( Colors.OrderBy( _ => random.Next() ) ); foreach ( var client in clients ) { - if (client.Pawn != null) + if ( client.Pawn != null ) { - ((Player) client.Pawn).Cleanup(); + ((Player)client.Pawn).Cleanup(); client.Pawn.Delete(); } - + Player pawn = new(); client.Pawn = pawn; - - if (spawnPoints.Count == 0) + + if ( spawnPoints.Count == 0 ) { ChatBox.Say( "Could not spawn " + client.Name + " as there are not enough spawn points." ); pawn.Team = Team.Spectator; continue; } - pawn.Dress( ); + + pawn.Dress(); // re-use names and colours if needed - if (natoNamesRemaining.Count == 0) + if ( natoNamesRemaining.Count == 0 ) { - natoNamesRemaining = new List(NatoNames); + natoNamesRemaining = new List( NatoNames ); } - if (colorsRemaining.Count == 0) + + if ( colorsRemaining.Count == 0 ) { - colorsRemaining = new List(Colors); + colorsRemaining = new List( Colors ); } // assign team - if (murderersNeeded > 0) + if ( murderersNeeded > 0 ) { pawn.Team = Team.Murderer; --murderersNeeded; } - else if (detectivesNeeded > 0) + else if ( detectivesNeeded > 0 ) { pawn.Team = Team.Detective; --detectivesNeeded; @@ -119,6 +122,7 @@ public partial class AssignPhase : BasePhase { pawn.Team = Team.Bystander; } + Log.Info( "Assigning " + client.Name + " to team " + pawn.GetTeamName() ); // position pawn @@ -127,26 +131,27 @@ public partial class AssignPhase : BasePhase var tx = spawnPoint.Transform; tx.Position += Vector3.Up * 10.0f; pawn.Transform = tx; - + // assign nato name var natoName = natoNamesRemaining[0]; natoNamesRemaining.RemoveAt( 0 ); pawn.CharacterName = natoName; - + // assign nato name var hexColor = colorsRemaining[0]; colorsRemaining.RemoveAt( 0 ); - pawn.Color = Color.FromRgb(hexColor); + pawn.Color = Color.FromRgb( hexColor ); RoleOverlay.Show( To.Single( client ) ); } - base.TimeLeft = 5; + + TimeLeft = 5; } [ClientRpc] public static void DeleteFootprints() { - foreach (var entity in Entity.All.OfType()) + foreach ( var entity in Entity.All.OfType() ) { entity.Delete(); } @@ -154,7 +159,7 @@ public partial class AssignPhase : BasePhase public override void Deactivate() { - foreach (var client in Game.Clients) + foreach ( var client in Game.Clients ) { RoleOverlay.Hide( To.Single( client ) ); } @@ -163,7 +168,7 @@ public partial class AssignPhase : BasePhase public override void Tick() { ++TicksElapsed; - if ( TimeLeft == -1 || TicksElapsed % Game.TickRate != 0 || --base.TimeLeft != 0 ) + if ( TimeLeft == -1 || TicksElapsed % Game.TickRate != 0 || --TimeLeft != 0 ) { return; } @@ -171,5 +176,4 @@ public partial class AssignPhase : BasePhase IsFinished = true; NextPhase = new PlayPhase(); } - } diff --git a/code/phase/BasePhase.cs b/code/phase/BasePhase.cs index 8f3d044..2ce7955 100644 --- a/code/phase/BasePhase.cs +++ b/code/phase/BasePhase.cs @@ -1,9 +1,4 @@ using Sandbox; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace MurderGame; @@ -11,11 +6,10 @@ public abstract partial class BasePhase : BaseNetworkable { public virtual string Title => "Name"; - [Net] - public int TimeLeft { get; set; } = -1; + [Net] public int TimeLeft { get; set; } = -1; + + public BasePhase NextPhase { get; set; } - public BasePhase NextPhase { get; set;} - public bool IsFinished { get; set; } public abstract void Tick(); @@ -24,5 +18,5 @@ public abstract partial class BasePhase : BaseNetworkable public virtual void Deactivate() { } - public virtual void HandleClientJoin(ClientJoinedEvent e) { } + public virtual void HandleClientJoin( ClientJoinedEvent e ) { } } diff --git a/code/phase/EndPhase.cs b/code/phase/EndPhase.cs index 904dc81..ada988d 100644 --- a/code/phase/EndPhase.cs +++ b/code/phase/EndPhase.cs @@ -1,26 +1,24 @@ using Sandbox; -using System.Linq; namespace MurderGame; public class EndPhase : BasePhase { - public override string Title => "Game over"; public int TicksElapsed; + public override string Title => "Game over"; public override void Activate() { - base.TimeLeft = 7; + TimeLeft = 7; } public override void Tick() { ++TicksElapsed; - if (base.TimeLeft != -1 && TicksElapsed % Game.TickRate == 0 && --base.TimeLeft == 0) + if ( TimeLeft != -1 && TicksElapsed % Game.TickRate == 0 && --TimeLeft == 0 ) { - base.NextPhase = new WaitPhase() { CountIn = false }; - base.IsFinished = true; - return; + NextPhase = new WaitPhase { CountIn = false }; + IsFinished = true; } } } diff --git a/code/phase/PlayPhase.cs b/code/phase/PlayPhase.cs index 682cfe7..895c305 100644 --- a/code/phase/PlayPhase.cs +++ b/code/phase/PlayPhase.cs @@ -1,23 +1,21 @@ -using Sandbox; -using Sandbox.UI; -using System; -using System.Buffers; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; +using Sandbox; +using Sandbox.UI; namespace MurderGame; public class PlayPhase : BasePhase { - public override string Title => "Play"; public IDictionary Blinded = new Dictionary(); public int TicksElapsed; + public override string Title => "Play"; private string MurdererNames { get; set; } public override void Activate() { - base.TimeLeft = MurderGame.RoundTime; - Event.Register(this); + TimeLeft = MurderGame.RoundTime; + Event.Register( this ); foreach ( var client in Game.Clients ) { if ( client.Pawn is not Player pawn || pawn.Team == Team.Spectator ) @@ -28,21 +26,24 @@ public class PlayPhase : BasePhase pawn.Respawn(); TeamCapabilities.GiveLoadouts( pawn ); } - MurdererNames = string.Join( ',', Game.Clients.Where( c => ((Player)c.Pawn).Team == Team.Murderer ).Select(c => c.Name)); + + MurdererNames = string.Join( ',', + Game.Clients.Where( c => ((Player)c.Pawn).Team == Team.Murderer ).Select( c => c.Name ) ); } public override void Deactivate() { - base.TimeLeft = MurderGame.RoundTime; - Event.Unregister(this); - foreach(var item in Blinded) + TimeLeft = MurderGame.RoundTime; + Event.Unregister( this ); + foreach ( var item in Blinded ) { ClearDebuffs( item.Key ); } + Blinded.Clear(); } - public void ClearDebuffs(Entity entity ) + public void ClearDebuffs( Entity entity ) { Log.Info( "Removing blind from " + entity.Name ); BlindedOverlay.Hide( To.Single( entity ) ); @@ -52,30 +53,38 @@ public class PlayPhase : BasePhase return; } - if (pawn.Controller is WalkControllerComponent controller) controller.SpeedMultiplier = 1; - if (pawn.Inventory!= null) pawn.Inventory.AllowPickup = true; + if ( pawn.Controller is WalkControllerComponent controller ) + { + controller.SpeedMultiplier = 1; + } + if ( pawn.Inventory != null ) + { + pawn.Inventory.AllowPickup = true; + } } public override void Tick() { ++TicksElapsed; - if (base.TimeLeft != -1 && TicksElapsed % Game.TickRate == 0 && --base.TimeLeft == 0) + if ( TimeLeft != -1 && TicksElapsed % Game.TickRate == 0 && --TimeLeft == 0 ) { TriggerEndOfGame(); return; } - var bystandersAlive = Game.Clients.Any(c =>((Player)c.Pawn).Team == Team.Bystander || ((Player)c.Pawn).Team == Team.Detective); - var murderersAlive = Game.Clients.Any(c =>((Player)c.Pawn).Team == Team.Murderer); - if (!bystandersAlive || !murderersAlive) + + var bystandersAlive = Game.Clients.Any( c => + ((Player)c.Pawn).Team == Team.Bystander || ((Player)c.Pawn).Team == Team.Detective ); + var murderersAlive = Game.Clients.Any( c => ((Player)c.Pawn).Team == Team.Murderer ); + if ( !bystandersAlive || !murderersAlive ) { TriggerEndOfGame(); } - foreach(var item in Blinded) + foreach ( var item in Blinded ) { var blindLeft = item.Value - 1; - if (blindLeft < 0) + if ( blindLeft < 0 ) { Blinded.Remove( item.Key ); ClearDebuffs( item.Key ); @@ -90,24 +99,25 @@ public class PlayPhase : BasePhase public void TriggerEndOfGame() { - var bystandersWin = Game.Clients.Any(c =>((Player)c.Pawn).Team is Team.Bystander or Team.Detective); - ChatBox.Say( (bystandersWin ? "Bystanders" : "Murderers") +" win! The murderers were: " + MurdererNames ); - base.NextPhase = new EndPhase(); - base.IsFinished = true; + var bystandersWin = Game.Clients.Any( c => ((Player)c.Pawn).Team is Team.Bystander or Team.Detective ); + ChatBox.Say( (bystandersWin ? "Bystanders" : "Murderers") + " win! The murderers were: " + MurdererNames ); + NextPhase = new EndPhase(); + IsFinished = true; } [MurderEvent.Kill] - public void OnKill(Entity killer, Entity victim) + public void OnKill( Entity killer, Entity victim ) { - if (killer is not Player && victim is not Player ) + if ( killer is not Player && victim is not Player ) { return; } + var victimPlayer = (Player)victim; var victimTeam = victimPlayer.Team; victimPlayer.Team = Team.Spectator; - if (killer == null) + if ( killer == null ) { Log.Info( victimPlayer + " died mysteriously" ); return; @@ -118,28 +128,31 @@ public class PlayPhase : BasePhase Log.Info( victimPlayer + " died to " + killerPlayer ); - if (victimTeam != Team.Murderer && killerTeam != Team.Murderer) + if ( victimTeam != Team.Murderer && killerTeam != Team.Murderer ) { - Log.Info( killerPlayer + " shot a bystander"); + Log.Info( killerPlayer + " shot a bystander" ); ChatBox.Say( killerPlayer.Client.Name + " killed an innocent bystander" ); BlindedOverlay.Show( To.Single( killer ) ); - if (killerPlayer.Controller is WalkControllerComponent controller) controller.SpeedMultiplier = 0.3f; - if (killerPlayer.Inventory != null) + if ( killerPlayer.Controller is WalkControllerComponent controller ) + { + controller.SpeedMultiplier = 0.3f; + } + + if ( killerPlayer.Inventory != null ) { killerPlayer.Inventory.AllowPickup = false; - killerPlayer.Inventory.SpillContents(killerPlayer.EyePosition, killerPlayer.AimRay.Forward); + killerPlayer.Inventory.SpillContents( killerPlayer.EyePosition, killerPlayer.AimRay.Forward ); } Blinded[killer] = 30 * Game.TickRate; } - else if (victimTeam == Team.Murderer ) + else if ( victimTeam == Team.Murderer ) { - Log.Info( killerPlayer + " killed a murderer"); + Log.Info( killerPlayer + " killed a murderer" ); ChatBox.Say( killerPlayer.Client.Name + " killed a murderer" ); } } - } diff --git a/code/phase/WaitPhase.cs b/code/phase/WaitPhase.cs index e52c91c..c284e10 100644 --- a/code/phase/WaitPhase.cs +++ b/code/phase/WaitPhase.cs @@ -1,9 +1,6 @@ -using Sandbox; -using System; -using System.Collections.Generic; +using System; using System.Linq; -using System.Text; -using System.Threading.Tasks; +using Sandbox; namespace MurderGame; @@ -17,28 +14,30 @@ public class WaitPhase : BasePhase public override void Tick() { - if (Game.Clients.Count >= MurderGame.MinPlayers) + if ( Game.Clients.Count >= MurderGame.MinPlayers ) { - if (!CountIn || (_isCountDown && ++TicksElapsed % Game.TickRate == 0 && --base.TimeLeft == 0)) + if ( !CountIn || (_isCountDown && ++TicksElapsed % Game.TickRate == 0 && --TimeLeft == 0) ) { - base.NextPhase = new AssignPhase(); - base.IsFinished = true; + NextPhase = new AssignPhase(); + IsFinished = true; return; } - else if (CountIn && !_isCountDown) + + if ( CountIn && !_isCountDown ) { _isCountDown = true; - base.TimeLeft = 10; + TimeLeft = 10; } - } else if (CountIn && _isCountDown) + } + else if ( CountIn && _isCountDown ) { _isCountDown = false; - base.TimeLeft = -1; + TimeLeft = -1; } - foreach (var client in Game.Clients) + foreach ( var client in Game.Clients ) { - if (client.Pawn == null) + if ( client.Pawn == null ) { var pawn = new Player(); client.Pawn = pawn; @@ -54,10 +53,11 @@ public class WaitPhase : BasePhase pawn.Spawn(); RespawnPlayer( pawn ); - } else + } + else { var pawn = (Player)client.Pawn; - if (pawn.LifeState == LifeState.Dead && pawn.TimeSinceDeath > 5) + if ( pawn.LifeState == LifeState.Dead && pawn.TimeSinceDeath > 5 ) { RespawnPlayer( pawn ); } @@ -65,7 +65,7 @@ public class WaitPhase : BasePhase } } - private void RespawnPlayer(Player pawn) + private void RespawnPlayer( Player pawn ) { pawn.Team = Team.Spectator; pawn.DressFromClient( pawn.Client ); @@ -74,6 +74,5 @@ public class WaitPhase : BasePhase public override void HandleClientJoin( ClientJoinedEvent e ) { - } } diff --git a/code/team/Team.cs b/code/team/Team.cs index ef065a4..05723c2 100644 --- a/code/team/Team.cs +++ b/code/team/Team.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace MurderGame; +namespace MurderGame; public enum Team : ushort { @@ -17,25 +11,27 @@ public enum Team : ushort // why are c# enums so bad public static class TeamCapabilities { - public static bool CanSprint(Team team) + public static bool CanSprint( Team team ) { return team switch { Team.Murderer => true, - _ => false, + _ => false }; } - - public static void GiveLoadouts(Player pawn) + + public static void GiveLoadouts( Player pawn ) { pawn.Inventory.Clear(); - - switch (pawn.Team) + + switch ( pawn.Team ) { case Team.Detective: - GiveDetectiveWeapon(pawn); break; + GiveDetectiveWeapon( pawn ); + break; case Team.Murderer: - GiveMurdererWeapon(pawn); break; + GiveMurdererWeapon( pawn ); + break; case Team.Spectator: case Team.Bystander: default: break; @@ -44,23 +40,20 @@ public static class TeamCapabilities private static void GiveDetectiveWeapon( Player pawn ) { - Pistol pistol = new() - { - Ammo = 1 - }; + Pistol pistol = new() { Ammo = 1 }; pawn.Inventory.SetPrimaryWeapon( pistol ); } - private static void GiveMurdererWeapon(Player pawn) + private static void GiveMurdererWeapon( Player pawn ) { pawn.Inventory.SetPrimaryWeapon( new Knife() ); pawn.Components.Create(); } } + public static class TeamOperations { - - public static string GetTeamName(Team team) + public static string GetTeamName( Team team ) { return team switch { @@ -68,29 +61,31 @@ public static class TeamOperations Team.Murderer => "Murderer", Team.Bystander => "Bystander", Team.Spectator => "Spectator", - _ => "None", + _ => "None" }; } - public static string GetTeamColour(Team team) + public static string GetTeamColour( Team team ) { return team switch { Team.Detective => "#33A0FF", Team.Murderer => "#FF4136", Team.Bystander => "#33A0FF", - _ => "#AAAAAA", + _ => "#AAAAAA" }; } - public static string GetTeamDescription(Team team) + public static string GetTeamDescription( Team team ) { return team switch { - Team.Detective => "There is a murderer on the loose! Find out who they are and shoot them before they kill everybody else.", + Team.Detective => + "There is a murderer on the loose! Find out who they are and shoot them before they kill everybody else.", Team.Murderer => "Kill everybody else in time and avoid detection. At least one other player is armed.", - Team.Bystander => "There is a murderer on the loose! Avoid getting killed and work with others to establish who the murderer is.", - _ => "None", + Team.Bystander => + "There is a murderer on the loose! Avoid getting killed and work with others to establish who the murderer is.", + _ => "None" }; } } diff --git a/code/ui/Hud.razor b/code/ui/Hud.razor index d5e3a40..c7d1ffa 100644 --- a/code/ui/Hud.razor +++ b/code/ui/Hud.razor @@ -1,8 +1,6 @@ -@using Sandbox; -@using Sandbox.UI; - @namespace MurderGame -@inherits RootPanel +@using Sandbox.UI +@inherits Sandbox.UI.RootPanel @attribute [StyleSheet] - - + + - + @code @@ -38,25 +36,25 @@ playerinfo { var clientPawn = Game.LocalPawn; if (clientPawn is Player {Camera: not null } player) { - var colour = player.Camera.GetObservedColour(); - return string.IsNullOrWhiteSpace(colour) ? "white" : colour; + var colour = player.Camera.GetObservedColour(); + return string.IsNullOrWhiteSpace(colour) ? "white" : colour; + } + return "white"; + } + + public string GetTeamColour() + { + var clientPawn = Game.LocalPawn; + if (clientPawn is Player {Camera: not null } player) + { + var colour = TeamOperations.GetTeamColour(player.Camera.GetObservedTeam()); + return string.IsNullOrWhiteSpace(colour) ? "white" : colour; } return "white"; } - - public string GetTeamColour() - { - var clientPawn = Game.LocalPawn; - if (clientPawn is Player {Camera: not null } player) - { - var colour = TeamOperations.GetTeamColour(player.Camera.GetObservedTeam()); - return string.IsNullOrWhiteSpace(colour) ? "white" : colour; - } - return "white"; - } protected override int BuildHash() { - return HashCode.Combine(GetTeamColour().GetHashCode(), GetTeamColour().GetHashCode()); + return HashCode.Combine(GetTeamColour().GetHashCode(), GetTeamColour().GetHashCode()); } -} +} \ No newline at end of file diff --git a/code/ui/character/LookingAtInfo.razor b/code/ui/character/LookingAtInfo.razor index ab43527..3c9bbab 100644 --- a/code/ui/character/LookingAtInfo.razor +++ b/code/ui/character/LookingAtInfo.razor @@ -1,9 +1,6 @@ -@using Sandbox; -@using Sandbox.UI; -@using System; - @namespace MurderGame -@inherits Panel +@using Sandbox +@inherits Sandbox.UI.Panel
-@GetName() + @GetName()
@code @@ -35,4 +33,4 @@ { return GetName().GetHashCode(); } -} +} \ No newline at end of file diff --git a/code/ui/component/Box.razor b/code/ui/component/Box.razor index a1a88d3..ee0b1e4 100644 --- a/code/ui/component/Box.razor +++ b/code/ui/component/Box.razor @@ -1,8 +1,5 @@ -@using Sandbox.Razor -@using Sandbox.UI; - @namespace MurderGame -@inherits Panel +@inherits Sandbox.UI.Panel + \ No newline at end of file diff --git a/code/ui/component/SmallBox.razor b/code/ui/component/SmallBox.razor index f5775aa..2149da2 100644 --- a/code/ui/component/SmallBox.razor +++ b/code/ui/component/SmallBox.razor @@ -1,8 +1,5 @@ -@using Sandbox.Razor -@using Sandbox.UI; - @namespace MurderGame -@inherits Panel +@inherits Sandbox.UI.Panel + \ No newline at end of file diff --git a/code/ui/health/Health.razor b/code/ui/health/Health.razor index d350756..4ec7f67 100644 --- a/code/ui/health/Health.razor +++ b/code/ui/health/Health.razor @@ -1,8 +1,6 @@ -@using Sandbox; -@using Sandbox.UI; - @namespace MurderGame -@inherits Panel +@using Sandbox +@inherits Sandbox.UI.Panel
-You shot a bystander! + You shot a bystander!
@code @@ -52,7 +49,7 @@ You shot a bystander! public BlindedOverlay() { - SetClass( "hidden", true ); + SetClass("hidden", true); Instance = this; } diff --git a/code/ui/overlay/DeathOverlay.Network.cs b/code/ui/overlay/DeathOverlay.Network.cs index f1f3bb2..33e354c 100644 --- a/code/ui/overlay/DeathOverlay.Network.cs +++ b/code/ui/overlay/DeathOverlay.Network.cs @@ -4,15 +4,21 @@ namespace MurderGame; public partial class DeathOverlay { - [ClientRpc] - public static void Show( ) - { - if (Instance != null) Instance.ShowOverlay = true; - } + [ClientRpc] + public static void Show() + { + if ( Instance != null ) + { + Instance.ShowOverlay = true; + } + } - [ClientRpc] - public static void Hide() - { - if (Instance != null) Instance.ShowOverlay = false; - } + [ClientRpc] + public static void Hide() + { + if ( Instance != null ) + { + Instance.ShowOverlay = false; + } + } } diff --git a/code/ui/overlay/DeathOverlay.razor b/code/ui/overlay/DeathOverlay.razor index 23c3a17..7751a38 100644 --- a/code/ui/overlay/DeathOverlay.razor +++ b/code/ui/overlay/DeathOverlay.razor @@ -1,8 +1,5 @@ -@using Sandbox; -@using Sandbox.UI; - @namespace MurderGame -@inherits Panel +@inherits Sandbox.UI.Panel
-
- Murder - This game mode is still a work in progress. Source code available at https://github.com/LMBishop/murder. -
+
+ Murder + This game mode is still a work in progress. Source code available at https://github.com/LMBishop/murder. +
-
-
- Name - Ping -
+
+
+ Name + Ping +
-
+
-
-
+
+
@code { - Dictionary Entries = new(); - + readonly Dictionary Entries = new(); + public Panel List { get; set; } public static TabListOverlay Instance { get; private set; } @@ -105,38 +104,38 @@ tablistoverlay { Instance = this; } - public bool IsOpen => Input.Down( "score" ); + public bool IsOpen => Input.Down("score"); public override void Tick() { base.Tick(); - SetClass( "hidden", !IsOpen ); + SetClass("hidden", !IsOpen); - if ( !IsVisible ) + if (!IsVisible) return; - foreach ( IClient cl in Game.Clients.Except( Entries.Keys ) ) + foreach (var cl in Game.Clients.Except(Entries.Keys)) { TabListEntry entry = new(); Entries.Add(cl, entry); entry.UpdateFrom(cl); - entry.Parent = List; + entry.Parent = List; } - foreach ( IClient cl in Entries.Keys.Except( Game.Clients ) ) + foreach (var cl in Entries.Keys.Except(Game.Clients)) { - if( Entries.TryGetValue( cl, out var entry ) ) + if (Entries.TryGetValue(cl, out var entry)) { entry.Delete(); - Entries.Remove( cl ); + Entries.Remove(cl); } } - - // foreach ( var entry in Entries ) - // { - // entry.Value.Parent = List; - // } + + // foreach ( var entry in Entries ) + // { + // entry.Value.Parent = List; + // } } } \ No newline at end of file diff --git a/code/ui/phase/PhaseInfo.razor b/code/ui/phase/PhaseInfo.razor index 4509259..7c95da5 100644 --- a/code/ui/phase/PhaseInfo.razor +++ b/code/ui/phase/PhaseInfo.razor @@ -1,8 +1,6 @@ -@using Sandbox; -@using Sandbox.UI; - @namespace MurderGame -@inherits Panel +@using Sandbox.UI +@inherits Sandbox.UI.Panel @attribute [StyleSheet]
@@ -16,8 +14,8 @@ return MurderGame.Instance.CurrentPhase; } - protected override int BuildHash() - { - return GetPhase().GetHashCode(); + protected override int BuildHash() + { + return GetPhase().GetHashCode(); } -} +} \ No newline at end of file diff --git a/code/ui/phase/PhaseTimer.razor b/code/ui/phase/PhaseTimer.razor index 73f44e2..89766cb 100644 --- a/code/ui/phase/PhaseTimer.razor +++ b/code/ui/phase/PhaseTimer.razor @@ -1,9 +1,6 @@ -@using Sandbox; -@using System -@using Sandbox.UI; - @namespace MurderGame -@inherits Panel +@using System +@inherits Sandbox.UI.Panel -@if (Spectating) { -
-
Spectating @TargetName
-
+@if (Spectating) +{ +
+
Spectating @TargetName
+
} @code { - public bool Spectating { get; set; } - public string TargetName { get; set; } + public bool Spectating { get; set; } + public string TargetName { get; set; } - protected override int BuildHash() - { - var localPawn = Game.LocalPawn; - if (localPawn is Player player && player.Camera is SpectatorCameraComponent spectator) - { - var target = spectator.Target; - Spectating = true; - TargetName = (target != null && target.IsValid() && target.LifeState == LifeState.Alive) ? target.Client.Name : ""; - return HashCode.Combine(Spectating.GetHashCode(), TargetName.GetHashCode()); - } - if (Spectating) - { - Spectating = false; - } - return Spectating.GetHashCode(); - } -} + protected override int BuildHash() + { + var localPawn = Game.LocalPawn; + if (localPawn is Player player && player.Camera is SpectatorCameraComponent spectator) + { + var target = spectator.Target; + Spectating = true; + TargetName = target != null && target.IsValid() && target.LifeState == LifeState.Alive ? target.Client.Name : ""; + return HashCode.Combine(Spectating.GetHashCode(), TargetName.GetHashCode()); + } + if (Spectating) + { + Spectating = false; + } + return Spectating.GetHashCode(); + } +} \ No newline at end of file diff --git a/code/ui/team/TeamInfo.razor b/code/ui/team/TeamInfo.razor index 71a2d66..cf5a7f8 100644 --- a/code/ui/team/TeamInfo.razor +++ b/code/ui/team/TeamInfo.razor @@ -1,8 +1,6 @@ -@using Sandbox; -@using Sandbox.UI; - @namespace MurderGame -@inherits Panel +@using Sandbox +@inherits Sandbox.UI.Panel
-@GetTeamName() + @GetTeamName()
@code @@ -35,4 +33,4 @@ { return GetTeamName().GetHashCode(); } -} +} \ No newline at end of file diff --git a/code/ui/weapon/Crosshair.razor b/code/ui/weapon/Crosshair.razor index 92cdcd3..f2196db 100644 --- a/code/ui/weapon/Crosshair.razor +++ b/code/ui/weapon/Crosshair.razor @@ -1,8 +1,5 @@ -@using Sandbox; -@using Sandbox.UI; - @namespace MurderGame -@inherits Panel +@inherits Sandbox.UI.Panel -
- +
\ No newline at end of file diff --git a/code/ui/weapon/Reload.razor b/code/ui/weapon/Reload.razor index 190a84c..22609e3 100644 --- a/code/ui/weapon/Reload.razor +++ b/code/ui/weapon/Reload.razor @@ -1,9 +1,7 @@ -@using Sandbox; -@using Sandbox.UI; -@using System; - @namespace MurderGame -@inherits Panel +@using System +@using Sandbox +@inherits Sandbox.UI.Panel -@if (ReloadNeeded) { - - +@if (ReloadNeeded) +{ + + } @code { - public bool ReloadNeeded { get; set; } - public bool Blink { get; set; } + public bool ReloadNeeded { get; set; } + public bool Blink { get; set; } - protected override int BuildHash() - { - var clientPawn = Game.LocalPawn; + protected override int BuildHash() + { + var clientPawn = Game.LocalPawn; if (clientPawn is Player {Camera: not null } player) - { - var inventory = player.Camera.GetObservedInventory(); - if (inventory?.GetCurrentWeapon() != null) - { - var weapon = inventory.GetCurrentWeapon(); - var ammo = weapon.Ammo; - ReloadNeeded = ammo == 0 && !weapon.Reloading; - Blink = !weapon.Reloading; - return HashCode.Combine(ReloadNeeded.GetHashCode(), Blink.GetHashCode()); - } - } - if (ReloadNeeded) - { - ReloadNeeded = false; - } - return ReloadNeeded.GetHashCode(); - } -} + { + var inventory = player.Camera.GetObservedInventory(); + if (inventory?.GetCurrentWeapon() != null) + { + var weapon = inventory.GetCurrentWeapon(); + var ammo = weapon.Ammo; + ReloadNeeded = ammo == 0 && !weapon.Reloading; + Blink = !weapon.Reloading; + return HashCode.Combine(ReloadNeeded.GetHashCode(), Blink.GetHashCode()); + } + } + if (ReloadNeeded) + { + ReloadNeeded = false; + } + return ReloadNeeded.GetHashCode(); + } +} \ No newline at end of file diff --git a/code/weapon/Knife.cs b/code/weapon/Knife.cs index 8ff0bb2..b3bf7f8 100644 --- a/code/weapon/Knife.cs +++ b/code/weapon/Knife.cs @@ -4,23 +4,23 @@ namespace MurderGame; public partial class Knife : Weapon { - public override string ModelPath => "weapons/swb/melee/bayonet/w_bayonet.vmdl"; - public override string ViewModelPath => "weapons/swb/melee/bayonet/v_bayonet.vmdl"; - public override string HandsModelPath => "weapons/swb/hands/rebel/v_hands_rebel.vmdl"; - public override float PrimaryRate => 1.5f; - public Knife() { Ammo = -1; MaxAmmo = -1; } + public override string ModelPath => "weapons/swb/melee/bayonet/w_bayonet.vmdl"; + public override string ViewModelPath => "weapons/swb/melee/bayonet/v_bayonet.vmdl"; + public override string HandsModelPath => "weapons/swb/hands/rebel/v_hands_rebel.vmdl"; + public override float PrimaryRate => 1.5f; + [ClientRpc] - protected virtual void ShootEffects(bool hit) + protected virtual void ShootEffects( bool hit ) { Game.AssertClient(); - - ViewModelEntity?.SetAnimParameter( hit ? "swing" : "swing_miss" , true ); + + ViewModelEntity?.SetAnimParameter( hit ? "swing" : "swing_miss", true ); } public override void PrimaryAttack() diff --git a/code/weapon/Pistol.cs b/code/weapon/Pistol.cs index 4c0c70b..6358b10 100644 --- a/code/weapon/Pistol.cs +++ b/code/weapon/Pistol.cs @@ -4,14 +4,14 @@ namespace MurderGame; public partial class Pistol : Weapon { - public override string ModelPath => "weapons/rust_pistol/rust_pistol.vmdl"; - public override string ViewModelPath => "weapons/rust_pistol/v_rust_pistol.vmdl"; - public Pistol() { MaxAmmo = 1; } + public override string ModelPath => "weapons/rust_pistol/rust_pistol.vmdl"; + public override string ViewModelPath => "weapons/rust_pistol/v_rust_pistol.vmdl"; + [ClientRpc] protected virtual void ShootEffects() { @@ -25,7 +25,7 @@ public partial class Pistol : Weapon public override void PrimaryAttack() { - if (Ammo > 0) + if ( Ammo > 0 ) { --Ammo; ShootEffects(); diff --git a/code/weapon/Weapon.cs b/code/weapon/Weapon.cs index 8eafbc3..2ee5889 100644 --- a/code/weapon/Weapon.cs +++ b/code/weapon/Weapon.cs @@ -1,5 +1,5 @@ -using Sandbox; using System.Collections.Generic; +using Sandbox; namespace MurderGame; @@ -19,14 +19,14 @@ public partial class Weapon : AnimatedEntity public virtual float PrimaryRate => 5f; public virtual float ReloadTime => 3.5f; - [Net, Predicted] public TimeSince TimeSincePrimaryAttack { get; set; } + [Net] [Predicted] public TimeSince TimeSincePrimaryAttack { get; set; } - [Net, Predicted] public TimeSince TimeSinceReload { get; set; } - [Net, Predicted] public TimeUntil TimeUntilReloadComplete { get; set; } - [Net, Predicted] public bool Reloading { get; set; } + [Net] [Predicted] public TimeSince TimeSinceReload { get; set; } + [Net] [Predicted] public TimeUntil TimeUntilReloadComplete { get; set; } + [Net] [Predicted] public bool Reloading { get; set; } - [Net, Predicted] public int Ammo { get; set; } - [Net, Predicted] public int MaxAmmo { get; set; } + [Net] [Predicted] public int Ammo { get; set; } + [Net] [Predicted] public int MaxAmmo { get; set; } public override void Spawn() { @@ -48,11 +48,12 @@ public partial class Weapon : AnimatedEntity public void OnEquip( Player pawn ) { - if (Owner == null) + if ( Owner == null ) { Owner = pawn; SetParent( pawn, true ); } + EnableDrawing = true; CreateViewModel( To.Single( pawn ) ); } @@ -68,7 +69,7 @@ public partial class Weapon : AnimatedEntity public override void Simulate( IClient player ) { Animate(); - if (Reloading && TimeUntilReloadComplete) + if ( Reloading && TimeUntilReloadComplete ) { Reloading = false; Ammo = MaxAmmo; @@ -82,7 +83,7 @@ public partial class Weapon : AnimatedEntity PrimaryAttack(); } } - else if (Input.Down("reload") && !Reloading && Ammo != MaxAmmo) + else if ( Input.Down( "reload" ) && !Reloading && Ammo != MaxAmmo ) { Reload(); Reloading = true; @@ -92,12 +93,18 @@ public partial class Weapon : AnimatedEntity public virtual bool CanPrimaryAttack() { - if ( !Owner.IsValid() || !Input.Down( "attack1" ) ) return false; + if ( !Owner.IsValid() || !Input.Down( "attack1" ) ) + { + return false; + } var rate = PrimaryRate; - if ( rate <= 0 ) return true; + if ( rate <= 0 ) + { + return true; + } - return !Reloading && TimeSincePrimaryAttack > (1 / rate); + return !Reloading && TimeSincePrimaryAttack > 1 / rate; } public virtual void PrimaryAttack() @@ -114,24 +121,29 @@ public partial class Weapon : AnimatedEntity public virtual IEnumerable TraceBullet( Vector3 start, Vector3 end, float radius = 2.0f ) { - bool underWater = Trace.TestPoint( start, "water" ); + var underWater = Trace.TestPoint( start, "water" ); var trace = Trace.Ray( start, end ) - .UseHitboxes() - .WithAnyTags( "solid", "livingplayer", "npc" ) - .Ignore( this ) - .Size( radius ); + .UseHitboxes() + .WithAnyTags( "solid", "livingplayer", "npc" ) + .Ignore( this ) + .Size( radius ); if ( !underWater ) + { trace = trace.WithAnyTags( "water" ); + } var tr = trace.Run(); if ( tr.Hit ) + { yield return tr; + } } - public virtual void ShootBullet( Vector3 pos, Vector3 dir, float spread, float force, float damage, float bulletSize ) + public virtual void ShootBullet( Vector3 pos, Vector3 dir, float spread, float force, float damage, + float bulletSize ) { var forward = dir; forward += (Vector3.Random + Vector3.Random + Vector3.Random + Vector3.Random) * spread * 0.25f; @@ -141,8 +153,15 @@ public partial class Weapon : AnimatedEntity { tr.Surface.DoBulletImpact( tr ); - if ( !Game.IsServer ) continue; - if ( !tr.Entity.IsValid() || !tr.Entity.Tags.Has("player") ) continue; + if ( !Game.IsServer ) + { + continue; + } + + if ( !tr.Entity.IsValid() || !tr.Entity.Tags.Has( "player" ) ) + { + continue; + } using ( Prediction.Off() ) { @@ -163,32 +182,40 @@ public partial class Weapon : AnimatedEntity var ray = Owner.AimRay; ShootBullet( ray.Position, ray.Forward, 0, force, damage, bulletSize ); } - + public virtual bool Melee( float force, float damage ) { var ray = Owner.AimRay; var forward = ray.Forward.Normal; var pos = ray.Position; - bool hit = false; + var hit = false; - foreach (var tr in TraceBullet(pos, pos + forward * 80, 20)) + foreach ( var tr in TraceBullet( pos, pos + forward * 80, 20 ) ) { - tr.Surface.DoBulletImpact(tr); + tr.Surface.DoBulletImpact( tr ); hit = true; - if ( !Game.IsServer ) continue; - if ( !tr.Entity.IsValid() || !tr.Entity.Tags.Has("player") ) continue; + if ( !Game.IsServer ) + { + continue; + } + + if ( !tr.Entity.IsValid() || !tr.Entity.Tags.Has( "player" ) ) + { + continue; + } - using (Prediction.Off()) + using ( Prediction.Off() ) { var damageInfo = DamageInfo.FromBullet( tr.EndPosition, forward.Normal * 100 * force, damage ) - .UsingTraceResult(tr) - .WithAttacker(Owner) - .WithWeapon(this); + .UsingTraceResult( tr ) + .WithAttacker( Owner ) + .WithWeapon( this ); - tr.Entity.TakeDamage(damageInfo); + tr.Entity.TakeDamage( damageInfo ); } } + return hit; } @@ -196,7 +223,10 @@ public partial class Weapon : AnimatedEntity public void CreateViewModel() { DestroyViewModel(); - if ( ViewModelPath == null ) return; + if ( ViewModelPath == null ) + { + return; + } var vm = new WeaponViewModel( this ); vm.Model = Model.Load( ViewModelPath ); @@ -204,13 +234,13 @@ public partial class Weapon : AnimatedEntity vm.Parent = Game.LocalPawn; vm.SetAnimParameter( "deploy", true ); ViewModelEntity = vm; - if (!string.IsNullOrEmpty(HandsModelPath)) + if ( !string.IsNullOrEmpty( HandsModelPath ) ) { HandModelEntity = new BaseViewModel(); HandModelEntity.Owner = Owner; HandModelEntity.EnableViewmodelRendering = true; - HandModelEntity.SetModel(HandsModelPath); - HandModelEntity.SetParent(ViewModelEntity, true); + HandModelEntity.SetModel( HandsModelPath ); + HandModelEntity.SetParent( ViewModelEntity, true ); } } @@ -221,6 +251,7 @@ public partial class Weapon : AnimatedEntity { ViewModelEntity.Delete(); } + if ( HandModelEntity.IsValid() ) { HandModelEntity.Delete(); diff --git a/code/weapon/WeaponViewModel.cs b/code/weapon/WeaponViewModel.cs index 97004fe..a42a6a3 100644 --- a/code/weapon/WeaponViewModel.cs +++ b/code/weapon/WeaponViewModel.cs @@ -2,10 +2,8 @@ using Sandbox; namespace MurderGame; -public partial class WeaponViewModel : BaseViewModel +public class WeaponViewModel : BaseViewModel { - protected Weapon Weapon { get; init; } - public WeaponViewModel( Weapon weapon ) { Weapon = weapon; @@ -13,10 +11,12 @@ public partial class WeaponViewModel : BaseViewModel EnableViewmodelRendering = true; } + protected Weapon Weapon { get; init; } + public override void PlaceViewmodel() { base.PlaceViewmodel(); - Camera.Main.SetViewModelCamera( 80f, 1, 500 ); + Camera.Main.SetViewModelCamera( 80f ); } } -- cgit v1.2.3-70-g09d2