Weapons/ToolGun/Modes/Hydraulic/HydraulicEntity.cs
using Sandbox.Utility;
public sealed class HydraulicEntity : Component, IPlayerControllable
{
[Property, Range( 0, 1 )]
public GameObject OnEffect { get; set; }
[Property, Range( 0, 100 ), ClientEditable]
public float MinLength { get; set; } = 10f;
[Property, Range( 0, 100 ), ClientEditable]
public float MaxLength { get; set; } = 100f;
[Property, Range( 0, 1 ), ClientEditable]
public float Length { get; set; } = 0.5f;
[Property, Range( 0, 1 ), ClientEditable]
public float Speed { get; set; } = 0.25f;
[Property, Sync, ClientEditable]
public ClientInput Push { get; set; }
[Property, Range( 0, 1 ), ClientEditable]
public float PushSpeed { get; set; } = 0.25f;
[Property, Sync, ClientEditable]
public ClientInput Pull { get; set; }
[Property, Range( 0, 1 ), ClientEditable]
public float PullSpeed { get; set; } = 0.25f;
[Property, Sync, ClientEditable]
public ClientInput Toggle { get; set; }
/// <summary>
/// While the client input is active we'll apply thrust
/// </summary>
[Property, Sync, ClientEditable]
public ClientInput Activate { get; set; }
[Property]
public SliderJoint Joint { get; set; }
[Property, ClientEditable, ToggleGroup( "Animated" )]
public bool Animated { get; set; }
[Property, ClientEditable, ToggleGroup( "Animated" ), Range( 0, 10 )]
public float AnimationSpeed { get; set; } = 1.0f;
[Property, ClientEditable, ToggleGroup( "Animated" )]
public EaseType EaseIn { get; set; } = EaseType.Linear;
[Property, ClientEditable, ToggleGroup( "Animated" )]
public EaseType EaseOut { get; set; } = EaseType.Linear;
public enum EaseType
{
Linear,
EaseIn,
EaseOut,
EaseInOut,
Bounce
}
protected override void OnEnabled()
{
base.OnEnabled();
OnEffect?.Enabled = false;
}
bool _state;
public void SetActiveState( bool state )
{
if ( _state == state ) return;
_state = state;
OnEffect?.Enabled = state;
Network.Refresh();
}
public void OnStartControl()
{
}
public void OnEndControl()
{
}
float? _lastTargetValue;
float? _targetValue;
public void OnControl()
{
if ( Activate.Down() )
{
Length += Speed * Time.Delta;
}
else if ( Activate.Released() )
{
Length = 0;
}
if ( Push.Down() )
{
Length += PushSpeed * Time.Delta * 5.0f;
}
if ( Pull.Down() )
{
Length -= PullSpeed * Time.Delta * 5.0f;
}
if ( Toggle.Pressed() )
{
_targetValue = _lastTargetValue.HasValue ? (_lastTargetValue > 0.5f ? 0.0f : 1.0f) : 1;
_lastTargetValue = _targetValue;
}
if ( _targetValue.HasValue )
{
if ( _targetValue > Length )
{
Length += PushSpeed * Time.Delta * 5.0f;
if ( Length > 1 )
{
_targetValue = null;
}
}
else
{
Length -= PullSpeed * Time.Delta * 5.0f;
if ( Length < 0 )
{
_targetValue = null;
}
}
}
Length = Length.Clamp( 0, 1 );
var analog = Activate.GetAnalog();
}
float _animTime = 0;
protected override void OnUpdate()
{
base.OnUpdate();
if ( !Joint.IsValid() ) return;
var line = Joint.Body.WorldPosition - Joint.GameObject.WorldPosition;
var line_rot = Rotation.LookAt( line, WorldRotation.Up );
DebugOverlay.Line( Joint.GameObject.WorldPosition, Joint.Body.WorldPosition, Color.Green );
if ( Animated )
{
_animTime += Time.Delta * AnimationSpeed * 0.33f;
_animTime = _animTime % 2;
var delta = _animTime;
if ( delta > 1 )
{
delta = 2 - delta;
delta = GetEase( 1 - delta, EaseOut );
delta = 1 - delta;
}
else
{
delta = GetEase( delta, EaseIn );
}
Length = (delta);
}
Joint.MinLength = MinLength + (Length * (MaxLength - MinLength));
Joint.MaxLength = MinLength + (Length * (MaxLength - MinLength));
if ( GetComponent<CapsuleCollider>() is CapsuleCollider capsule )
{
capsule.Static = false;
capsule.Start = capsule.WorldTransform.PointToLocal( Joint.GameObject.WorldPosition );
capsule.End = capsule.WorldTransform.PointToLocal( Joint.Body.WorldPosition );
capsule.Radius = 1.0f;
capsule.ColliderFlags = ColliderFlags.IgnoreMass;
capsule.Tags.Set( "trigger", true );
}
if ( GetComponent<SkinnedModelRenderer>() is SkinnedModelRenderer renderer )
{
renderer.CreateBoneObjects = true;
var len = line.Length - MinLength;
var a = Joint.GameObject.WorldPosition;
var b = a + line.Normal * MinLength * 0.5f;
var c = b + line.Normal * len;
var d = c + line.Normal * MinLength * 0.5f;
renderer.GetBoneObject( 0 )?.WorldTransform = new Transform( a, line_rot );
renderer.GetBoneObject( 0 )?.Flags |= GameObjectFlags.ProceduralBone;
renderer.GetBoneObject( 1 )?.WorldTransform = new Transform( b, line_rot ); ;
renderer.GetBoneObject( 1 )?.Flags |= GameObjectFlags.ProceduralBone;
renderer.GetBoneObject( 2 )?.WorldTransform = new Transform( c, line_rot ); ;
renderer.GetBoneObject( 2 )?.Flags |= GameObjectFlags.ProceduralBone;
renderer.GetBoneObject( 3 )?.WorldTransform = new Transform( d, line_rot ); ;
renderer.GetBoneObject( 3 )?.Flags |= GameObjectFlags.ProceduralBone;
}
}
private float GetEase( float delta, EaseType easeIn )
{
switch ( easeIn )
{
case EaseType.Linear: return delta;
case EaseType.EaseIn: return Easing.EaseIn( delta );
case EaseType.EaseOut: return Easing.EaseOut( delta );
case EaseType.EaseInOut: return Easing.EaseInOut( delta );
case EaseType.Bounce: return Easing.BounceOut( delta );
}
return delta;
}
}