aboutsummaryrefslogtreecommitdiffstats
path: root/code
diff options
context:
space:
mode:
Diffstat (limited to 'code')
-rw-r--r--code/Game.cs10
-rw-r--r--code/pawn/Player.cs12
-rw-r--r--code/pawn/PlayerSpectator.cs48
-rw-r--r--code/ui/Hud.razor1
-rw-r--r--code/ui/spectator/Spectator.razor63
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();
+ }
+}