diff options
| -rw-r--r-- | code/Game.cs | 10 | ||||
| -rw-r--r-- | code/pawn/Player.cs | 12 | ||||
| -rw-r--r-- | code/pawn/PlayerSpectator.cs | 48 | ||||
| -rw-r--r-- | code/ui/Hud.razor | 1 | ||||
| -rw-r--r-- | code/ui/spectator/Spectator.razor | 63 |
5 files changed, 132 insertions, 2 deletions
diff --git a/code/Game.cs b/code/Game.cs index f235df0..24fd79d 100644 --- a/code/Game.cs +++ b/code/Game.cs @@ -1,5 +1,6 @@
using Sandbox;
+using Sandbox.UI;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -64,6 +65,15 @@ public partial class MurderGame : Sandbox.GameManager tx.Position = tx.Position + Vector3.Up * 50.0f;
pawn.Transform = tx;
}
+
+ ChatBox.Say( client.Name + " joined the game" );
+ }
+
+ public override void ClientDisconnect( IClient client, NetworkDisconnectionReason reason )
+ {
+ base.ClientDisconnect(client, reason );
+
+ ChatBox.Say( client.Name + " left the game (" + reason.ToString() + ")" );
}
}
diff --git a/code/pawn/Player.cs b/code/pawn/Player.cs index a1b126a..68d383d 100644 --- a/code/pawn/Player.cs +++ b/code/pawn/Player.cs @@ -47,6 +47,7 @@ public partial class Player : AnimatedEntity [BindComponent] public PlayerController Controller { get; }
[BindComponent] public PlayerAnimator Animator { get; }
[BindComponent] public PlayerInventory Inventory { get; }
+ [BindComponent] public PlayerSpectator Spectator { get; }
public Ragdoll PlayerRagdoll { get; set; }
public ClothingContainer PlayerClothingContainer { get; set; }
@@ -74,6 +75,7 @@ public partial class Player : AnimatedEntity Tags.Add( "livingplayer" );
EnableAllCollisions = true;
EnableDrawing = true;
+ Components.Remove( Spectator );
Components.Create<PlayerController>();
Components.Create<PlayerAnimator>();
Components.Create<PlayerInventory>();
@@ -85,6 +87,7 @@ public partial class Player : AnimatedEntity {
DisablePlayer();
DeleteRagdoll();
+ Components.RemoveAll();
}
public void DeleteRagdoll()
@@ -118,6 +121,7 @@ public partial class Player : AnimatedEntity ragdoll.PhysicsGroup.AddVelocity(LastAttackForce / 100);
PlayerClothingContainer.DressEntity( ragdoll );
PlayerRagdoll = ragdoll;
+ Components.Create<PlayerSpectator>();
}
public override void TakeDamage( DamageInfo info )
@@ -150,6 +154,7 @@ public partial class Player : AnimatedEntity Controller?.Simulate( cl );
Animator?.Simulate();
Inventory?.Simulate( cl );
+ Spectator?.Simulate();
EyeLocalPosition = Vector3.Up * (64f * Scale);
}
@@ -174,10 +179,13 @@ public partial class Player : AnimatedEntity ViewAngles = viewAngles.Normal;
}
- bool IsThirdPerson { get; set; } = false;
-
public override void FrameSimulate( IClient cl )
{
+ if (Spectator != null)
+ {
+ Spectator.FrameSimulate(this);
+ return;
+ }
SimulateRotation();
Camera.Rotation = ViewAngles.ToRotation();
diff --git a/code/pawn/PlayerSpectator.cs b/code/pawn/PlayerSpectator.cs new file mode 100644 index 0000000..c468de0 --- /dev/null +++ b/code/pawn/PlayerSpectator.cs @@ -0,0 +1,48 @@ +using Sandbox;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace MurderGame;
+
+public class PlayerSpectator : EntityComponent<Player>
+{
+ public Player Target { get; set; }
+
+ public void Simulate()
+ {
+ if (Target == null || !Target.IsValid() || Target.LifeState == LifeState.Dead)
+ {
+ var targets = GetTargets();
+ if ( targets.Count == 0 )
+ {
+ Target = null;
+ return;
+ }
+ var nextTarget = targets.First();
+ Target = (Player)nextTarget.Pawn;
+ }
+ }
+
+ public void FrameSimulate( Player player )
+ {
+ if ( Target == null || !Target.IsValid() || Target.LifeState == LifeState.Dead ) return;
+
+ // SimulateRotation(player);
+ Camera.Rotation = Target.EyeRotation;
+ Camera.FieldOfView = Screen.CreateVerticalFieldOfView( Game.Preferences.FieldOfView );
+
+ Camera.FirstPersonViewer = Target;
+ Camera.Position = Target.EyePosition;
+ }
+
+ protected void SimulateRotation(Player player)
+ {
+ player.EyeRotation = Target.ViewAngles.ToRotation();
+ player.Rotation = Target.ViewAngles.WithPitch( 0f ).ToRotation();
+ }
+
+ public List<IClient> GetTargets()
+ {
+ return Game.Clients.Where(c => c.Pawn is Player player && player.CurrentTeam != Team.Spectator && player.LifeState == LifeState.Alive).ToList();
+ }
+}
diff --git a/code/ui/Hud.razor b/code/ui/Hud.razor index 7ec500e..cacf26b 100644 --- a/code/ui/Hud.razor +++ b/code/ui/Hud.razor @@ -19,6 +19,7 @@ <Crosshair/>
<Reload/>
<PlayerInfo/>
+ <Spectator/>
</root>
@code
diff --git a/code/ui/spectator/Spectator.razor b/code/ui/spectator/Spectator.razor new file mode 100644 index 0000000..f6fe8af --- /dev/null +++ b/code/ui/spectator/Spectator.razor @@ -0,0 +1,63 @@ +@using Sandbox;
+@using Sandbox.UI;
+@using System;
+
+@namespace MurderGame
+@inherits Panel
+
+<style>
+spectator {
+ top: 0;
+ left: 0;
+ width: 100vw;
+ height: 100vh;
+ position: absolute;
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ flex-direction: column;
+}
+.box {
+ backdrop-filter-blur: 8px;
+ background-color: rgba(0, 0, 0, 0.20);
+ padding: 10px;
+ color: white;
+ font-weight: 700;
+ font-size: 35px;
+ font-family: "Roboto";
+ margin: 30px;
+}
+</style>
+
+@if (Spectating) {
+<div class="box">
+ <div>Spectating @TargetName</div>
+</div>
+}
+
+@code
+{
+ public bool Spectating { get; set; }
+ public string TargetName { get; set; }
+
+ protected override int BuildHash()
+ {
+ var localPawn = Game.LocalPawn;
+ if (localPawn is Player player)
+ {
+ var spectator = player.Spectator;
+ if (spectator != null)
+ {
+ 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();
+ }
+}
|
