aboutsummaryrefslogtreecommitdiffstats
path: root/code/pawn/Player.Use.cs
diff options
context:
space:
mode:
Diffstat (limited to 'code/pawn/Player.Use.cs')
-rw-r--r--code/pawn/Player.Use.cs117
1 files changed, 117 insertions, 0 deletions
diff --git a/code/pawn/Player.Use.cs b/code/pawn/Player.Use.cs
new file mode 100644
index 0000000..3f35052
--- /dev/null
+++ b/code/pawn/Player.Use.cs
@@ -0,0 +1,117 @@
+using Sandbox;
+
+namespace MurderGame;
+
+public partial class Player
+{
+ public Entity Using { get; protected set; }
+
+ protected virtual void TickPlayerUse()
+ {
+ // This is serverside only
+ if ( !Game.IsServer ) return;
+
+ // Turn prediction off
+ using ( Prediction.Off() )
+ {
+ if ( Input.Pressed( "use" ) )
+ {
+ Using = FindUsable();
+
+ if ( Using == null )
+ {
+ UseFail();
+ return;
+ }
+ }
+
+ if ( !Input.Down( "use" ) )
+ {
+ StopUsing();
+ return;
+ }
+
+ if ( !Using.IsValid() )
+ return;
+
+ // If we move too far away or something we should probably ClearUse()?
+
+ //
+ // If use returns true then we can keep using it
+ //
+ if ( Using is IUse use && use.OnUse( this ) )
+ return;
+
+ StopUsing();
+ }
+ }
+
+ /// <summary>
+ /// Player tried to use something but there was nothing there.
+ /// Tradition is to give a disappointed boop.
+ /// </summary>
+ protected virtual void UseFail()
+ {
+ PlaySound( "player_use_fail" );
+ }
+
+ /// <summary>
+ /// If we're using an entity, stop using it
+ /// </summary>
+ protected virtual void StopUsing()
+ {
+ Using = null;
+ }
+
+ /// <summary>
+ /// Returns if the entity is a valid usable entity
+ /// </summary>
+ protected bool IsValidUseEntity( Entity e )
+ {
+ if ( e == null ) return false;
+ if ( e is not IUse use ) return false;
+ if ( !use.IsUsable( this ) ) return false;
+
+ return true;
+ }
+
+ /// <summary>
+ /// Find a usable entity for this player to use
+ /// </summary>
+ protected virtual Entity FindUsable()
+ {
+ // First try a direct 0 width line
+ var tr = Trace.Ray( EyePosition, EyePosition + EyeRotation.Forward * 85 )
+ .Ignore( this )
+ .Run();
+
+ // See if any of the parent entities are usable if we ain't.
+ var ent = tr.Entity;
+ while ( ent.IsValid() && !IsValidUseEntity( ent ) )
+ {
+ ent = ent.Parent;
+ }
+
+ // Nothing found, try a wider search
+ if ( !IsValidUseEntity( ent ) )
+ {
+ tr = Trace.Ray( EyePosition, EyePosition + EyeRotation.Forward * 85 )
+ .Radius( 2 )
+ .Ignore( this )
+ .Run();
+
+ // See if any of the parent entities are usable if we ain't.
+ ent = tr.Entity;
+ while ( ent.IsValid() && !IsValidUseEntity( ent ) )
+ {
+ ent = ent.Parent;
+ }
+ }
+
+ // Still no good? Bail.
+ if ( !IsValidUseEntity( ent ) ) return null;
+
+ return ent;
+ }
+}
+