Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions Code/Components/FrozenBy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/// <summary>
/// Tracks which connection last froze this object with the physgun.
/// Added when frozen, removed when unfrozen.
/// </summary>
public sealed class FrozenBy : Component
{
[Sync( SyncFlags.FromHost )]
public Guid FreezerId { get; set; }

/// <summary>
/// Marks a gameObject as frozen by a connection, adding the component if it doesn't have one yet.
/// </summary>
public static void Set( GameObject go, Guid freezerId )
{
var frozen = go.GetOrAddComponent<FrozenBy>();
frozen.FreezerId = freezerId;
}

/// <summary>
/// Clears the frozen marker from a gameObject if it has one.
/// </summary>
public static void Clear( GameObject go )
{
if ( go.Components.TryGet<FrozenBy>( out var frozen ) )
frozen.Destroy();
}
}
48 changes: 45 additions & 3 deletions Code/Weapons/PhysGun/Physgun.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ public override readonly int GetHashCode()

bool _launched;

TimeSince _lastReloadPress = 1000;

/// <summary>
/// The force applied to pull objects to us.
/// </summary>
Expand All @@ -88,6 +90,11 @@ public override readonly int GetHashCode()
/// </summary>
static float PullDistance => 200.0f;

/// <summary>
/// Max time between reload presses to count as a double-tap.
/// </summary>
static float DoubleTapWindow => 0.4f;

public override void OnCameraMove( Player player, ref Angles angles )
{
base.OnCameraMove( player, ref angles );
Expand Down Expand Up @@ -181,7 +188,7 @@ public override void OnControl( Player player )

if ( Input.Down( "attack2" ) )
{
Freeze( _state.Body );
Freeze( _state.Body, player.Network.Owner.Id );
_state = default;
_preventReselect = true;
ViewModel?.PlaySound( ReleasedSound );
Expand Down Expand Up @@ -295,10 +302,16 @@ public override void OnControl( Player player )
}
else if ( Input.Pressed( "reload" ) )
{
if ( _stateHovered.IsValid() )
if ( _lastReloadPress < DoubleTapWindow )
{
UnfreezeAllFrozen( player.Network.Owner.Id );
}
else if ( _stateHovered.IsValid() )
{
UnfreezeAll( _stateHovered.Body );
}

_lastReloadPress = 0;
}
else
{
Expand Down Expand Up @@ -588,7 +601,7 @@ static float ClampGrabDistance( Rigidbody body, Vector3 point, Transform eye, fl
}

[Rpc.Broadcast]
void Freeze( Rigidbody body )
void Freeze( Rigidbody body, Guid freezerId )
{
if ( !body.IsValid() ) return;

Expand All @@ -604,6 +617,7 @@ void Freeze( Rigidbody body )
if ( Networking.IsHost )
{
body.MotionEnabled = false;
FrozenBy.Set( body.GameObject, freezerId );
}
}

Expand All @@ -614,6 +628,7 @@ void Unfreeze( Rigidbody body )
if ( body.IsProxy ) return;

body.MotionEnabled = true;
FrozenBy.Clear( body.GameObject );
}

[Rpc.Broadcast]
Expand All @@ -638,6 +653,33 @@ void UnfreezeAll( Rigidbody body )
}
}

[Rpc.Broadcast]
void UnfreezeAllFrozen( Guid freezerId )
{
if ( freezerId == Guid.Empty ) return;

foreach ( var rb in GetFrozenBodies( freezerId ) )
{
var effect = UnFreezeEffectPrefab.Clone( rb.WorldTransform );
foreach ( var emitter in effect.GetComponentsInChildren<ParticleModelEmitter>() )
{
emitter.Target = rb.GameObject;
}

Unfreeze( rb );
}
}

static IEnumerable<Rigidbody> GetFrozenBodies( Guid freezerId )
{
foreach ( var frozen in Game.ActiveScene.GetAllComponents<FrozenBy>() )
{
if ( frozen.FreezerId != freezerId ) continue;
if ( frozen.Components.TryGet<Rigidbody>( out var rb ) )
yield return rb;
}
}

[Rpc.Host]
void Launch( Rigidbody body, Vector3 force )
{
Expand Down