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 ;
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.GameObjects ;
using Robust.Shared.Map ;
2021-11-22 19:31:12 +00:00
using Robust.Shared.IoC ;
2021-10-04 16:10:54 +01:00
using Robust.Shared.Physics ;
using Robust.Shared.Log ;
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 ! ;
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
{
2021-12-07 22:22:34 +11:00
if ( ! EntityManager . HasComponent < SharedPullerComponent > ( puller ) )
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 ;
}
2021-12-07 22:22:34 +11:00
if ( ! EntityManager . TryGetComponent < IPhysBody ? > ( pulled , out var _physics ) )
2021-10-04 16:10:54 +01:00
{
return false ;
}
if ( _physics . BodyType = = BodyType . Static )
{
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 ;
}
}
2021-10-04 16:10:54 +01:00
var startPull = new StartPullAttemptEvent ( puller , pulled ) ;
2021-12-03 15:53:09 +01:00
RaiseLocalEvent ( puller , startPull ) ;
2021-10-04 16:10:54 +01:00
return ! startPull . Cancelled ;
}
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 ) ;
2021-12-07 22:22:34 +11:00
RaiseLocalEvent ( pullable . Owner , msg ) ;
2021-10-04 16:10:54 +01:00
if ( msg . Cancelled ) return false ;
_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 ;
}
2021-12-04 12:59:44 +01:00
if ( ! EntityManager . TryGetComponent < PhysicsComponent ? > ( puller . Owner , out var pullerPhysics ) )
2021-10-04 16:10:54 +01:00
{
return false ;
}
2021-12-04 12:59:44 +01: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.
var pullAttempt = new PullAttemptMessage ( pullerPhysics , pullablePhysics ) ;
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 ;
}
2021-12-07 22:22:34 +11:00
RaiseLocalEvent ( pullable . Owner , pullAttempt ) ;
2021-10-04 16:10:54 +01:00
if ( pullAttempt . Cancelled )
{
return false ;
}
_pullSm . ForceRelationship ( puller , pullable ) ;
return true ;
}
2021-11-07 02:16:49 +00: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 ;
}
_pullSm . ForceSetMovingTo ( pullable , to ) ;
return true ;
}
public void StopMoveTo ( SharedPullableComponent pullable )
{
_pullSm . ForceSetMovingTo ( pullable , null ) ;
}
}
}