全站通知:

Usable Entities

阅读

    

2023-09-12更新

    

最新编辑:TrimesS_

阅读:

  

更新日期:2023-09-12

  

最新编辑:TrimesS_

来自S&boxWIKI_BWIKI_哔哩哔哩
跳到导航 跳到搜索
页面贡献者 :
-TrimesS-

Entities can be made usable by players (as well as NPCs and anything else should the game developers choose to do so) via the IUse interface.

Example usage Marking entity as usable is very easy, by simply implementing the aforementioned IUse interface:

public partial class MyEntity: ModelEntity, IUse
{
    // Other entity code...

	public bool OnUse( Entity user )
	{
		// Do something when entity is used...

		Log.Info( $"{this} has been used by {user}!" );

		return false;
	}

	public bool IsUsable( Entity user )
	{
		// Disallow using the entity when some condition is or is not met
		if ( SomeCondition == false ) return false;
		return true;
	}
}

Full documentation about IUse can be found on the API documentation website and in your IDE.

Game implementation Once you have your entities set up, you might need to set up your game to use the IUse interface if it doesn't do this already.

Example implementation might look something like this:

public partial class Player
{
	/// <summary>
	/// Entity the player is currently using via their interaction key.
	/// </summary>
	public Entity Using { get; protected set; }

	/// <summary>
	/// This should be called somewhere in your player's tick to allow them to use entities,
	/// for example the Simulate callback method of the player pawn entity.
	/// </summary>
	protected virtual void TickPlayerUse()
	{
		// This is serverside only
		if ( !Game.IsServer ) return;

		// Turn prediction off
		using ( Prediction.Off() )
		{
			if ( Input.Pressed( InputButton.Use ) )
			{
				Using = FindUsable();

				if ( Using == null )
				{
					UseFail();
					return;
				}
			}

			if ( !Input.Down( InputButton.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;
	}
}