2021-11-22 19:31:12 +00:00
using Content.Shared.ActionBlocker ;
2021-11-13 21:43:37 +00:00
using Content.Shared.Buckle.Components ;
2022-06-21 07:00:11 -07:00
using Content.Shared.Hands.EntitySystems ;
2021-10-04 16:10:54 +01:00
using Content.Shared.Physics.Pull ;
using Content.Shared.Pulling.Components ;
using Content.Shared.Pulling.Events ;
using Robust.Shared.Containers ;
using Robust.Shared.Map ;
using Robust.Shared.Physics ;
namespace Content.Shared.Pulling
{
public abstract partial class SharedPullingSystem : EntitySystem
{
2021-11-22 19:31:12 +00:00
[Dependency] private readonly ActionBlockerSystem _blocker = default ! ;
2022-01-31 20:08:53 +13:00
[Dependency] private readonly SharedContainerSystem _containerSystem = default ! ;
2022-06-21 07:00:11 -07:00
[Dependency] private readonly SharedHandsSystem _handsSystem = default ! ;
2021-11-22 19:31:12 +00:00
2021-12-04 12:59:44 +01:00
public bool CanPull ( EntityUid puller , EntityUid pulled )
2021-10-04 16:10:54 +01:00
{
2022-06-21 07:00:11 -07:00
if ( ! EntityManager . TryGetComponent < SharedPullerComponent > ( puller , out var comp ) )
{
return false ;
}
if ( comp . NeedsHands & & ! _handsSystem . TryGetEmptyHand ( puller , out _ ) )
2021-10-04 16:10:54 +01:00
{
return false ;
}
2022-02-15 17:06:52 +13:00
if ( ! _blocker . CanInteract ( puller , pulled ) )
2021-11-22 19:31:12 +00:00
{
return false ;
}
2022-05-16 22:24:52 +10:00
if ( ! EntityManager . TryGetComponent < IPhysBody > ( pulled , out var physics ) )
2021-10-04 16:10:54 +01:00
{
return false ;
}
2022-05-16 22:24:52 +10:00
if ( physics . BodyType = = BodyType . Static )
2021-10-04 16:10:54 +01:00
{
return false ;
}
if ( puller = = pulled )
{
return false ;
}
2022-01-31 20:08:53 +13:00
if ( ! _containerSystem . IsInSameOrNoContainer ( puller , pulled ) )
2021-10-04 16:10:54 +01:00
{
return false ;
}
2021-12-07 22:22:34 +11:00
if ( EntityManager . TryGetComponent < SharedBuckleComponent ? > ( puller , out var buckle ) )
2021-11-13 21:43:37 +00:00
{
// Prevent people pulling the chair they're on, etc.
2021-12-03 15:53:09 +01:00
if ( buckle . Buckled & & ( buckle . LastEntityBuckledTo = = pulled ) )
2021-11-13 21:43:37 +00:00
{
return false ;
}
}
2022-06-15 21:10:03 -04:00
var getPulled = new BeingPulledAttemptEvent ( puller , pulled ) ;
2022-06-22 09:53:41 +10:00
RaiseLocalEvent ( pulled , getPulled , true ) ;
2021-10-04 16:10:54 +01:00
var startPull = new StartPullAttemptEvent ( puller , pulled ) ;
2022-06-22 09:53:41 +10:00
RaiseLocalEvent ( puller , startPull , true ) ;
2022-06-15 21:10:03 -04:00
return ( ! startPull . Cancelled & & ! getPulled . Cancelled ) ;
2021-10-04 16:10:54 +01:00
}
2021-12-04 12:59:44 +01:00
public bool TogglePull ( EntityUid puller , SharedPullableComponent pullable )
2021-10-04 16:10:54 +01:00
{
if ( pullable . Puller = = puller )
{
return TryStopPull ( pullable ) ;
}
return TryStartPull ( puller , pullable . Owner ) ;
}
// -- Core attempted actions --
2021-12-04 12:59:44 +01:00
public bool TryStopPull ( SharedPullableComponent pullable , EntityUid ? user = null )
2021-10-04 16:10:54 +01:00
{
if ( ! pullable . BeingPulled )
{
return false ;
}
2021-12-03 15:53:09 +01:00
var msg = new StopPullingEvent ( user ) ;
2022-06-22 09:53:41 +10:00
RaiseLocalEvent ( pullable . Owner , msg , true ) ;
2021-10-04 16:10:54 +01:00
if ( msg . Cancelled ) return false ;
2022-06-16 05:15:56 -04:00
// Stop pulling confirmed!
if ( TryComp < PhysicsComponent > ( pullable . Owner , out var pullablePhysics ) )
{
pullablePhysics . FixedRotation = pullable . PrevFixedRotation ;
}
2021-10-04 16:10:54 +01:00
_pullSm . ForceRelationship ( null , pullable ) ;
return true ;
}
2021-12-04 12:59:44 +01:00
public bool TryStartPull ( EntityUid puller , EntityUid pullable )
2021-10-04 16:10:54 +01:00
{
2021-12-04 12:59:44 +01:00
if ( ! EntityManager . TryGetComponent < SharedPullerComponent ? > ( puller , out var pullerComp ) )
2021-10-04 16:10:54 +01:00
{
return false ;
}
2021-12-04 12:59:44 +01:00
if ( ! EntityManager . TryGetComponent < SharedPullableComponent ? > ( pullable , out var pullableComp ) )
2021-10-04 16:10:54 +01:00
{
return false ;
}
return TryStartPull ( pullerComp , pullableComp ) ;
}
// The main "start pulling" function.
public bool TryStartPull ( SharedPullerComponent puller , SharedPullableComponent pullable )
{
2021-11-23 14:02:08 +01:00
if ( puller . Pulling = = pullable . Owner )
2021-10-04 16:10:54 +01:00
return true ;
// Pulling a new object : Perform sanity checks.
2021-12-04 12:59:44 +01:00
if ( ! CanPull ( puller . Owner , pullable . Owner ) )
2021-10-04 16:10:54 +01:00
{
return false ;
}
2022-05-16 22:24:52 +10:00
if ( ! EntityManager . TryGetComponent < PhysicsComponent > ( puller . Owner , out var pullerPhysics ) )
2021-10-04 16:10:54 +01:00
{
return false ;
}
2022-05-16 22:24:52 +10:00
if ( ! EntityManager . TryGetComponent < PhysicsComponent > ( pullable . Owner , out var pullablePhysics ) )
2021-10-04 16:10:54 +01:00
{
return false ;
}
// Ensure that the puller is not currently pulling anything.
// If this isn't done, then it happens too late, and the start/stop messages go out of order,
// and next thing you know it thinks it's not pulling anything even though it is!
var oldPullable = puller . Pulling ;
if ( oldPullable ! = null )
{
2021-12-04 12:59:44 +01:00
if ( EntityManager . TryGetComponent < SharedPullableComponent ? > ( oldPullable . Value , out var oldPullableComp ) )
2021-10-04 16:10:54 +01:00
{
if ( ! TryStopPull ( oldPullableComp ) )
{
return false ;
}
}
else
{
Logger . WarningS ( "c.go.c.pulling" , "Well now you've done it, haven't you? Someone transferred pulling (onto {0}) while presently pulling something that has no Pullable component (on {1})!" , pullable . Owner , oldPullable ) ;
return false ;
}
}
// Ensure that the pullable is not currently being pulled.
// Same sort of reasons as before.
var oldPuller = pullable . Puller ;
if ( oldPuller ! = null )
{
if ( ! TryStopPull ( pullable ) )
{
return false ;
}
}
// Continue with pulling process.
2022-05-16 22:24:52 +10:00
var pullAttempt = new PullAttemptEvent ( pullerPhysics , pullablePhysics ) ;
2021-10-04 16:10:54 +01:00
2021-12-07 22:22:34 +11:00
RaiseLocalEvent ( puller . Owner , pullAttempt , broadcast : false ) ;
2021-10-04 16:10:54 +01:00
if ( pullAttempt . Cancelled )
{
return false ;
}
2022-06-22 09:53:41 +10:00
RaiseLocalEvent ( pullable . Owner , pullAttempt , true ) ;
2021-10-04 16:10:54 +01:00
if ( pullAttempt . Cancelled )
return false ;
_pullSm . ForceRelationship ( puller , pullable ) ;
2022-06-16 05:15:56 -04:00
pullable . PrevFixedRotation = pullablePhysics . FixedRotation ;
pullablePhysics . FixedRotation = pullable . FixedRotationOnPull ;
2021-10-04 16:10:54 +01:00
return true ;
}
2022-03-18 15:40:02 +11:00
public bool TryMoveTo ( SharedPullableComponent pullable , EntityCoordinates to )
2021-10-04 16:10:54 +01:00
{
if ( pullable . Puller = = null )
{
return false ;
}
2021-12-07 22:22:34 +11:00
if ( ! EntityManager . HasComponent < PhysicsComponent > ( pullable . Owner ) )
2021-10-04 16:10:54 +01:00
{
return false ;
}
2022-03-18 15:40:02 +11:00
_pullSm . ForceSetMovingTo ( pullable , to ) ;
2021-10-04 16:10:54 +01:00
return true ;
}
2022-03-18 15:40:02 +11:00
public void StopMoveTo ( SharedPullableComponent pullable )
{
_pullSm . ForceSetMovingTo ( pullable , null ) ;
}
2021-10-04 16:10:54 +01:00
}
}