aboutsummaryrefslogtreecommitdiffstats
path: root/code/pawn/Player.Use.cs
blob: 8c3cce9084b5296bc8148c4d56f82cc383cd9118 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
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;
	}
}