mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-08-01 08:18:20 -04:00
https://sbox.game/dev/doc/gameplay/inventory-weapons/ Added InventoryComponent - a slot based inventory, hotbar or shared bucket slots, with a starting loadout BaseInventoryItem - base class for inventory items, with hooks to veto switching, holstering and dropping BaseWeapon - a GMod style base weapon - fire modes, magazines and reserve ammo, reloading, dry fire, ballistics, spread, crosshair and HUD BaseWeaponModel - view/world model base with muzzle flash, brass ejection, tracers and animation hooks Ammo types are resources (.ammo) - weapons share reserve pools by type, clamped to a max reserve BaseWeapon.ShootBullets / ShootBullet - bullet tracing with damage, impulse and hitbox tags Weapon hold types editor Animgraph enum parameters can be set by option name - Renderer.Set( "holdtype", "pistol" ) NpcUsage on BaseWeapon - engagement range and burst behaviour so NPCs can use any weapon ICameraModifier - cameras compose their view through an ordered modifier chain, read the result from CameraComponent.View CameraEffectSystem - screen shake, directional punches and tilts, with world epicenter falloff - camera.AddShake / AddPunch / AddTilt EnvShake component - shakes the view, rumbles controllers, kicks physics TracerEffect - an animated tracer line, ITargetedEffect for effects that fly at a target SceneAnchor - a world position that can follow an object or bone SkinnedModelRenderer.GetClosestBone( worldPosition ) Vector3.WithAimCone can take a custom Random for reproducible spread Improve/Fix PlayerController searches parents for IPressable when pressing PlayerController camera runs through the modifier chain - IEvents.PostCameraSetup is obsolete SoundPlayer preview uses shortcuts - Space toggles playback, Ctrl+Space restarts Fixed Radius( 0 ) traces missing everything Fixed NRE in AssetPreviewWidget Removed Removed CameraComponent.ISceneCameraSetup (obsolete since October, nothing uses)
216 lines
5.2 KiB
C#
216 lines
5.2 KiB
C#
using NativeEngine;
|
|
|
|
namespace Sandbox;
|
|
|
|
/// <summary>
|
|
/// Anim param values contain any value for a limited set of types
|
|
/// </summary>
|
|
public struct AnimParam<T>
|
|
{
|
|
public string Name;
|
|
public T MinValue;
|
|
public T MaxValue;
|
|
public T DefaultValue;
|
|
public string[] OptionNames;
|
|
}
|
|
|
|
public sealed partial class AnimationGraph : Resource
|
|
{
|
|
internal HAnimationGraph native;
|
|
|
|
public override bool IsValid => native.IsValid;
|
|
|
|
/// <summary>
|
|
/// Whether the animation graph is invalid, or has not yet loaded.
|
|
/// </summary>
|
|
public override bool IsError => native.IsNull || !native.IsStrongHandleValid();
|
|
|
|
/// <summary>
|
|
/// Animation graph file name.
|
|
/// </summary>
|
|
public string Name { get; internal set; }
|
|
|
|
/// <summary>
|
|
/// Private constructor, use <see cref="FromNative(HAnimationGraph, string)"/>
|
|
/// </summary>
|
|
private AnimationGraph( HAnimationGraph native, string name )
|
|
{
|
|
if ( native.IsNull ) throw new Exception( "Animation Graph pointer cannot be null!" );
|
|
|
|
this.native = native;
|
|
Name = name;
|
|
|
|
UpdateNameToIndexMapping();
|
|
RegisterWeakResourceId( Name );
|
|
}
|
|
|
|
internal override void OnReloaded()
|
|
{
|
|
base.OnReloaded();
|
|
|
|
UpdateNameToIndexMapping();
|
|
}
|
|
|
|
private void UpdateNameToIndexMapping()
|
|
{
|
|
_nameToIndex.Clear();
|
|
_enumOptions?.Clear();
|
|
|
|
for ( var i = 0; i < ParamCount; i++ )
|
|
{
|
|
_nameToIndex[GetParameterFromList( i ).GetName()] = i;
|
|
}
|
|
}
|
|
|
|
private Dictionary<string, Dictionary<string, int>> _enumOptions;
|
|
|
|
/// <summary>
|
|
/// Find the index of a named option on an enum parameter, case insensitive. False when the
|
|
/// parameter doesn't exist, isn't an enum, or has no option with that name.
|
|
/// </summary>
|
|
internal bool TryGetEnumOptionIndex( string parameterName, string option, out int index )
|
|
{
|
|
index = default;
|
|
|
|
if ( string.IsNullOrEmpty( parameterName ) || string.IsNullOrEmpty( option ) )
|
|
return false;
|
|
|
|
_enumOptions ??= new( StringComparer.OrdinalIgnoreCase );
|
|
|
|
if ( _enumOptions.TryGetValue( parameterName, out var options ) )
|
|
return options.TryGetValue( option, out index );
|
|
|
|
var param = GetParameterFromList( parameterName );
|
|
if ( !param.IsValid || param.GetParameterType() != AnimParamType.Enum )
|
|
return false;
|
|
|
|
options = new( StringComparer.OrdinalIgnoreCase );
|
|
|
|
for ( var i = 0; i < param.GetNumOptionNames(); i++ )
|
|
{
|
|
options[param.GetOptionName( i )] = i;
|
|
}
|
|
|
|
_enumOptions[parameterName] = options;
|
|
|
|
return options.TryGetValue( option, out index );
|
|
}
|
|
|
|
internal override void Destroy()
|
|
{
|
|
if ( !native.IsNull )
|
|
{
|
|
var n = native;
|
|
native = default;
|
|
|
|
MainThread.Queue( () => n.DestroyStrongHandle() );
|
|
}
|
|
|
|
base.Destroy();
|
|
}
|
|
|
|
internal IAnimParameterList ParameterList => native.GetParameterList();
|
|
internal IAnimParameter GetParameterFromList( int index ) => ParameterList.GetParameter( index );
|
|
internal IAnimParameter GetParameterFromList( string name ) => ParameterList.GetParameter( name );
|
|
|
|
/// <summary>
|
|
/// Number of parameters in this animgraph
|
|
/// </summary>
|
|
public int ParamCount => ParameterList.Count();
|
|
|
|
private Dictionary<string, int> _nameToIndex = new();
|
|
|
|
private static readonly Type[] _types =
|
|
[
|
|
null,
|
|
typeof( bool ),
|
|
typeof( byte ),
|
|
typeof( int ),
|
|
typeof( float ),
|
|
typeof( Vector3 ),
|
|
typeof( Rotation ),
|
|
];
|
|
|
|
/// <summary>
|
|
/// Get value type of parameter at given index
|
|
/// </summary>
|
|
public Type GetParameterType( int index )
|
|
{
|
|
return _types[(int)GetParameterFromList( index ).GetParameterType()];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get value type of parameter with the given <paramref name="name"/>, or <see langword="null"/> if not found.
|
|
/// </summary>
|
|
public Type GetParameterType( string name )
|
|
{
|
|
if ( GetParameterFromList( name ) is not { IsValid: true } param )
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var parameterType = param.GetParameterType();
|
|
|
|
return _types[(int)parameterType];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get name of parameter at given index
|
|
/// </summary>
|
|
public string GetParameterName( int index )
|
|
{
|
|
return GetParameterFromList( index ).GetName();
|
|
}
|
|
|
|
internal AnimParam<T> GetParameterInternal<T>( IAnimParameter param )
|
|
{
|
|
if ( !param.IsValid )
|
|
{
|
|
throw new ArgumentException( $"Invalid parameter" );
|
|
}
|
|
|
|
var parameterType = param.GetParameterType();
|
|
var type = _types[(int)parameterType];
|
|
|
|
if ( type != typeof( T ) )
|
|
{
|
|
throw new ArgumentException( $"Invalid parameter type {typeof( T )}, expected {type}" );
|
|
}
|
|
|
|
return new()
|
|
{
|
|
Name = param.GetName(),
|
|
MinValue = param.GetMinValue().GetValue<T>(),
|
|
MaxValue = param.GetMaxValue().GetValue<T>(),
|
|
DefaultValue = param.GetDefaultValue().GetValue<T>(),
|
|
OptionNames = parameterType == AnimParamType.Enum ? Enumerable.Range( 0, param.GetNumOptionNames() )
|
|
.Select( param.GetOptionName )
|
|
.ToArray() : null
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Try to get parameter index at given name
|
|
/// </summary>
|
|
public bool TryGetParameterIndex( string name, out int index )
|
|
{
|
|
return _nameToIndex.TryGetValue( name, out index );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get parameter at given name
|
|
/// </summary>
|
|
public AnimParam<T> GetParameter<T>( string name )
|
|
{
|
|
return GetParameterInternal<T>( GetParameterFromList( name ) );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get parameter at given index
|
|
/// </summary>
|
|
public AnimParam<T> GetParameter<T>( int index )
|
|
{
|
|
return GetParameterInternal<T>( GetParameterFromList( index ) );
|
|
}
|
|
}
|