Beispiel #1
0
    public bool CanFTL(EntityUid?uid, [NotNullWhen(false)] out string?reason, TransformComponent?xform = null)
    {
        reason = null;

        if (!TryComp <IMapGridComponent>(uid, out var grid) ||
            !Resolve(uid.Value, ref xform))
        {
            return(true);
        }

        var bounds    = grid.Grid.WorldAABB.Enlarged(ShuttleFTLRange);
        var bodyQuery = GetEntityQuery <PhysicsComponent>();

        foreach (var other in _mapManager.FindGridsIntersecting(xform.MapID, bounds))
        {
            if (grid.GridIndex == other.Index ||
                !bodyQuery.TryGetComponent(other.GridEntityId, out var body) ||
                body.Mass < ShuttleFTLMassThreshold)
            {
                continue;
            }

            reason = Loc.GetString("shuttle-console-proximity");
            return(false);
        }

        return(true);
    }
Beispiel #2
0
        /// <summary>
        /// Sets the shuttle's movement mode. Does minimal revalidation.
        /// </summary>
        private void SetShuttleMode(ShuttleMode mode, ShuttleConsoleComponent consoleComponent,
                                    ShuttleComponent shuttleComponent, TransformComponent?consoleXform = null)
        {
            // Re-validate
            if (!this.IsPowered(consoleComponent.Owner, EntityManager) ||
                !Resolve(consoleComponent.Owner, ref consoleXform) ||
                !consoleXform.Anchored ||
                consoleXform.GridID != Transform(shuttleComponent.Owner).GridID)
            {
                return;
            }

            shuttleComponent.Mode = mode;

            switch (mode)
            {
            case ShuttleMode.Strafing:
                break;

            case ShuttleMode.Cruise:
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
    /// <summary>
    /// Get the body's total angular velocity. This is the rate of change of the entity's world rotation.
    /// </summary>
    /// <remarks>
    /// Consider using <see cref="GetMapVelocities"/> if you need linear and angular at the same time.
    /// </remarks>
    public float GetMapAngularVelocity(
        EntityUid uid,
        PhysicsComponent?component = null,
        TransformComponent?xform   = null,
        EntityQuery <TransformComponent>?xformQuery = null,
        EntityQuery <PhysicsComponent>?physicsQuery = null)
    {
        if (!Resolve(uid, ref component))
        {
            return(0);
        }

        xformQuery ??= EntityManager.GetEntityQuery <TransformComponent>();
        physicsQuery ??= EntityManager.GetEntityQuery <PhysicsComponent>();

        xform ??= xformQuery.Value.GetComponent(uid);
        var parent = xform.ParentUid;

        var angularVelocity = component.AngularVelocity;

        while (parent.IsValid())
        {
            var parentXform = xformQuery.Value.GetComponent(parent);

            if (physicsQuery.Value.TryGetComponent(parent, out var body))
            {
                angularVelocity += body.AngularVelocity;
            }
            parent = parentXform.ParentUid;
        }

        return(angularVelocity);
    }
Beispiel #4
0
        private void UserSplit(EntityUid uid, EntityUid userUid, int amount,
                               StackComponent?stack             = null,
                               TransformComponent?userTransform = null)
        {
            if (!Resolve(uid, ref stack))
            {
                return;
            }

            if (!Resolve(userUid, ref userTransform))
            {
                return;
            }

            if (amount <= 0)
            {
                _popupSystem.PopupCursor(Loc.GetString("comp-stack-split-too-small"), Filter.Entities(userUid));
                return;
            }

            if (Split(uid, amount, userTransform.Coordinates, stack) is not {
            } split)
            {
                return;
            }

            if (TryComp <HandsComponent>(userUid, out var hands) && TryComp <ItemComponent>(split, out var item))
            {
                hands.PutInHandOrDrop(item);
            }

            _popupSystem.PopupCursor(Loc.GetString("comp-stack-split"), Filter.Entities(userUid));
        }
        /// <summary>
        ///     Tries to anchor the entity.
        /// </summary>
        /// <returns>true if anchored, false otherwise</returns>
        public async Task <bool> TryAnchor(EntityUid uid, EntityUid userUid, EntityUid usingUid,
                                           AnchorableComponent?anchorable   = null,
                                           TransformComponent?transform     = null,
                                           SharedPullableComponent?pullable = null,
                                           ToolComponent?usingTool          = null)
        {
            if (!Resolve(uid, ref anchorable, ref transform))
            {
                return(false);
            }

            // Optional resolves.
            Resolve(uid, ref pullable, false);

            if (!Resolve(usingUid, ref usingTool))
            {
                return(false);
            }

            if (!(await Valid(uid, userUid, usingUid, true, anchorable, usingTool)))
            {
                return(false);
            }

            // Snap rotation to cardinal (multiple of 90)
            var rot = transform.LocalRotation;

            transform.LocalRotation = Math.Round(rot / (Math.PI / 2)) * (Math.PI / 2);

            if (pullable is { Puller : {} })
 /// <summary>
 ///     Spills the specified solution at the entity's location if possible.
 /// </summary>
 /// <param name="uid">
 ///     The entity to use as a location to spill the solution at.
 /// </param>
 /// <param name="solution">Initial solution for the prototype.</param>
 /// <param name="prototype">The prototype to use.</param>
 /// <param name="sound">Play the spill sound.</param>
 /// <param name="combine">Whether to attempt to merge with existing puddles</param>
 /// <param name="transformComponent">Optional Transform component</param>
 /// <returns>The puddle if one was created, null otherwise.</returns>
 public PuddleComponent?SpillAt(EntityUid uid, Solution solution, string prototype,
                                bool sound = true, bool combine = true, TransformComponent?transformComponent = null)
 {
     return(!Resolve(uid, ref transformComponent, false)
         ? null
         : SpillAt(solution, transformComponent.Coordinates, prototype, sound: sound, combine: combine));
 }
Beispiel #7
0
    public Box2 GetHardAABB(PhysicsComponent body, TransformComponent?xform = null, FixturesComponent?fixtures = null)
    {
        if (!Resolve(body.Owner, ref xform, ref fixtures))
        {
            throw new InvalidOperationException();
        }

        var(worldPos, worldRot) = xform.GetWorldPositionRotation();

        var transform = new Transform(worldPos, (float)worldRot.Theta);

        var bounds = new Box2(transform.Position, transform.Position);

        foreach (var fixture in fixtures.Fixtures.Values)
        {
            if (!fixture.Hard)
            {
                continue;
            }

            for (var i = 0; i < fixture.Shape.ChildCount; i++)
            {
                var boundy = fixture.Shape.ComputeAABB(transform, i);
                bounds = bounds.Union(boundy);
            }
        }

        return(bounds);
    }
Beispiel #8
0
    public EntityUid?TakeAmmo(AmmoBoxComponent ammoBox, TransformComponent?xform = null)
    {
        if (!Resolve(ammoBox.Owner, ref xform))
        {
            return(null);
        }

        if (ammoBox.SpawnedAmmo.TryPop(out var ammo))
        {
            ammoBox.AmmoContainer.Remove(ammo);
            return(ammo);
        }

        if (ammoBox.UnspawnedCount > 0)
        {
            ammo = EntityManager.SpawnEntity(ammoBox.FillPrototype, xform.Coordinates);

            // when dumping from held ammo box, this detaches the spawned ammo from the player.
            EntityManager.GetComponent <TransformComponent>(ammo).AttachParentToContainerOrGrid();

            ammoBox.UnspawnedCount--;
        }

        return(ammo);
    }
Beispiel #9
0
        /// <summary>
        ///     Tries to unanchor the entity.
        /// </summary>
        /// <returns>true if unanchored, false otherwise</returns>
        private void TryUnAnchor(EntityUid uid, EntityUid userUid, EntityUid usingUid,
                                 AnchorableComponent?anchorable = null,
                                 TransformComponent?transform   = null,
                                 ToolComponent?usingTool        = null)
        {
            if (!Resolve(uid, ref anchorable, ref transform) ||
                anchorable.CancelToken != null)
            {
                return;
            }

            if (!Resolve(usingUid, ref usingTool))
            {
                return;
            }

            if (!Valid(uid, userUid, usingUid, false))
            {
                return;
            }

            anchorable.CancelToken = new CancellationTokenSource();

            _toolSystem.UseTool(usingUid, userUid, uid, 0f, anchorable.Delay, usingTool.Qualities,
                                new TryUnanchorCompletedEvent(), new TryUnanchorCancelledEvent(), uid, cancelToken: anchorable.CancelToken.Token);
        }
Beispiel #10
0
    private void UpdateAppearance(EntityUid uid, AppearanceComponent?appearance = null, NodeContainerComponent?container = null,
                                  TransformComponent?xform = null)
    {
        if (!Resolve(uid, ref appearance, ref container, ref xform, false))
        {
            return;
        }

        if (!_mapManager.TryGetGrid(xform.GridUid, out var grid))
        {
            return;
        }

        // get connected entities
        var anyPipeNodes = false;
        HashSet <EntityUid> connected = new();

        foreach (var node in container.Nodes.Values)
        {
            if (node is not PipeNode)
            {
                continue;
            }

            anyPipeNodes = true;

            foreach (var connectedNode in node.ReachableNodes)
            {
                if (connectedNode is PipeNode)
                {
                    connected.Add(connectedNode.Owner);
                }
            }
        }

        if (!anyPipeNodes)
        {
            return;
        }

        // find the cardinal directions of any connected entities
        var netConnectedDirections = PipeDirection.None;
        var tile = grid.TileIndicesFor(xform.Coordinates);

        foreach (var neighbour in connected)
        {
            var otherTile = grid.TileIndicesFor(Transform(neighbour).Coordinates);

            netConnectedDirections |= (otherTile - tile) switch
            {
                (0, 1) => PipeDirection.North,
                (0, -1) => PipeDirection.South,
                (1, 0) => PipeDirection.East,
                (-1, 0) => PipeDirection.West,
                _ => PipeDirection.None
            };
        }

        appearance.SetData(PipeVisuals.VisualState, netConnectedDirections);
    }
        /// <summary>
        ///     Force bomb to explode immediately
        /// </summary>
        public void ActivateBomb(EntityUid uid, NukeComponent?component = null,
                                 TransformComponent?transform           = null)
        {
            if (!Resolve(uid, ref component, ref transform))
            {
                return;
            }

            if (component.Exploded)
            {
                return;
            }

            component.Exploded = true;

            _explosions.QueueExplosion(uid,
                                       component.ExplosionType,
                                       component.TotalIntensity,
                                       component.IntensitySlope,
                                       component.MaxIntensity);

            RaiseLocalEvent(new NukeExplodedEvent());

            EntityManager.DeleteEntity(uid);
        }
        /// <summary>
        ///     Try to find the closest entity from whitelist on a current map
        ///     Will return null if can't find anything
        /// </summary>
        private EntityUid?FindTargetFromWhitelist(EntityUid uid, EntityWhitelist whitelist,
                                                  TransformComponent?transform = null)
        {
            if (!Resolve(uid, ref transform))
            {
                return(null);
            }

            var mapId = transform.MapID;
            var ents  = _entityLookup.GetEntitiesInMap(mapId);

            // sort all entities in distance increasing order
            var l = new SortedList <float, EntityUid>();

            foreach (var e in ents)
            {
                if (whitelist.IsValid(e))
                {
                    var dist = (EntityManager.GetComponent <TransformComponent>(e).WorldPosition - transform.WorldPosition).LengthSquared;
                    l.TryAdd(dist, e);
                }
            }

            // return uid with a smallest distacne
            return(l.Count > 0 ? l.First().Value : null);
        }
        /// <summary>
        ///     Force bomb to explode immediately
        /// </summary>
        public void ActivateBomb(EntityUid uid, NukeComponent?component = null,
                                 TransformComponent?transform           = null)
        {
            if (!Resolve(uid, ref component, ref transform))
            {
                return;
            }

            // gib anyone in a blast radius
            // its lame, but will work for now
            var pos  = transform.Coordinates;
            var ents = _lookup.GetEntitiesInRange(pos, component.BlastRadius);

            foreach (var ent in ents)
            {
                var entUid = ent;
                if (!EntityManager.EntityExists(entUid))
                {
                    continue;
                }

                if (EntityManager.TryGetComponent(entUid, out SharedBodyComponent? body))
                {
                    body.Gib();
                }
            }

            EntityManager.DeleteEntity(uid);
        }
Beispiel #14
0
        private void UserSplit(EntityUid uid, EntityUid userUid, int amount,
                               StackComponent?stack             = null,
                               TransformComponent?userTransform = null)
        {
            if (!Resolve(uid, ref stack))
            {
                return;
            }

            if (!Resolve(userUid, ref userTransform))
            {
                return;
            }

            if (amount <= 0)
            {
                PopupSystem.PopupCursor(Loc.GetString("comp-stack-split-too-small"), Filter.Entities(userUid));
                return;
            }

            if (Split(uid, amount, userTransform.Coordinates, stack) is not {
            } split)
            {
                return;
            }

            HandsSystem.PickupOrDrop(userUid, split);

            PopupSystem.PopupCursor(Loc.GetString("comp-stack-split"), Filter.Entities(userUid));
        }
Beispiel #15
0
        /// <summary>
        ///     Try to find the closest entity from whitelist on a current map
        ///     Will return null if can't find anything
        /// </summary>
        private EntityUid?FindTargetFromComponent(EntityUid uid, Type whitelist, TransformComponent?transform = null)
        {
            var xformQuery = GetEntityQuery <TransformComponent>();

            if (transform == null)
            {
                xformQuery.TryGetComponent(uid, out transform);
            }

            if (transform == null)
            {
                return(null);
            }

            // sort all entities in distance increasing order
            var mapId    = transform.MapID;
            var l        = new SortedList <float, EntityUid>();
            var worldPos = _transform.GetWorldPosition(transform, xformQuery);

            foreach (var comp in EntityManager.GetAllComponents(whitelist))
            {
                if (!xformQuery.TryGetComponent(comp.Owner, out var compXform) ||
                    compXform.MapID != mapId)
                {
                    continue;
                }

                var dist = (_transform.GetWorldPosition(compXform, xformQuery) - worldPos).LengthSquared;
                l.TryAdd(dist, comp.Owner);
            }

            // return uid with a smallest distacne
            return(l.Count > 0 ? l.First().Value : null);
        }
Beispiel #16
0
 public virtual void TryToggleAnchor(EntityUid uid, EntityUid userUid, EntityUid usingUid,
                                     AnchorableComponent?anchorable   = null,
                                     TransformComponent?transform     = null,
                                     SharedPullableComponent?pullable = null,
                                     ToolComponent?usingTool          = null)
 {
     // Thanks tool system.
     return;
 }
Beispiel #17
0
        public void SetAirblocked(AirtightComponent airtight, bool airblocked, TransformComponent?xform = null)
        {
            if (!Resolve(airtight.Owner, ref xform))
            {
                return;
            }

            airtight.AirBlocked = airblocked;
            UpdatePosition(airtight, xform);
            RaiseLocalEvent(airtight.Owner, new AirtightChanged(airtight));
        }
        private void TryFindAndSetProvider(ExtensionCableReceiverComponent receiver, TransformComponent?xform = null)
        {
            if (!TryFindAvailableProvider(receiver.Owner, receiver.ReceptionRange, out var provider, xform))
            {
                return;
            }

            receiver.Provider = provider;
            provider.LinkedReceivers.Add(receiver);
            RaiseLocalEvent(receiver.Owner, new ProviderConnectedEvent(provider), broadcast: false);
            RaiseLocalEvent(provider.Owner, new ReceiverConnectedEvent(receiver), broadcast: false);
        }
Beispiel #19
0
        protected override void InsertItem(int index, EntityComponent item)
        {
            TransformComponent?oldTransformComponent = Entity.Transform;

            base.InsertItem(index, item);

            if (item is TransformComponent)
            {
                if (oldTransformComponent != null)
                {
                    Remove(oldTransformComponent);
                }
            }
        }
Beispiel #20
0
        public void UpdatePosition(AirtightComponent airtight, TransformComponent?xform = null)
        {
            if (!Resolve(airtight.Owner, ref xform))
            {
                return;
            }

            if (!xform.Anchored || !_mapManager.TryGetGrid(xform.GridUid, out var grid))
            {
                return;
            }

            airtight.LastPosition = (xform.GridUid.Value, grid.TileIndicesFor(xform.Coordinates));
            InvalidatePosition(airtight.LastPosition.Item1, airtight.LastPosition.Item2, airtight.FixVacuum && !airtight.AirBlocked);
        }
    public (Vector2, float) GetMapVelocities(
        EntityUid uid,
        PhysicsComponent?component = null,
        TransformComponent?xform   = null,
        EntityQuery <TransformComponent>?xformQuery = null,
        EntityQuery <PhysicsComponent>?physicsQuery = null)
    {
        if (!Resolve(uid, ref component))
        {
            return(Vector2.Zero, 0);
        }

        xformQuery ??= EntityManager.GetEntityQuery <TransformComponent>();
        physicsQuery ??= EntityManager.GetEntityQuery <PhysicsComponent>();

        xform ??= xformQuery.Value.GetComponent(uid);
        var parent = xform.ParentUid;

        var localPos = xform.LocalPosition;

        var     linearVelocity  = component.LinearVelocity;
        var     angularVelocity = component.AngularVelocity;
        Vector2 linearVelocityAngularContribution = Vector2.Zero;

        while (parent.IsValid())
        {
            var parentXform = xformQuery.Value.GetComponent(parent);

            if (physicsQuery.Value.TryGetComponent(parent, out var body))
            {
                angularVelocity += body.AngularVelocity;

                // add linear velocity of parent relative to it's own parent (again, in map coordinates)
                linearVelocity += body.LinearVelocity;

                // add the component of the linear velocity that results from the parent's rotation. This is NOT in map
                // coordinates, this is the velocity in the parentXform.Parent's frame.
                linearVelocityAngularContribution += Vector2.Cross(body.AngularVelocity, localPos - body.LocalCenter);
                linearVelocityAngularContribution  = parentXform.LocalRotation.RotateVec(linearVelocityAngularContribution);
            }

            localPos = parentXform.LocalPosition + parentXform.LocalRotation.RotateVec(localPos);
            parent   = parentXform.ParentUid;
        }

        return(linearVelocity + linearVelocityAngularContribution, angularVelocity);
    }
    /// <summary>
    ///     This is the total rate of change of the entity's map-position, resulting from the linear and angular
    ///     velocities of this entity and any parents.
    /// </summary>
    /// <remarks>
    ///     Use <see cref="GetMapVelocities"/> if you need linear and angular at the same time.
    /// </remarks>
    public Vector2 GetMapLinearVelocity(
        EntityUid uid,
        PhysicsComponent?component = null,
        TransformComponent?xform   = null,
        EntityQuery <TransformComponent>?xformQuery = null,
        EntityQuery <PhysicsComponent>?physicsQuery = null)
    {
        if (!Resolve(uid, ref component))
        {
            return(Vector2.Zero);
        }

        xformQuery ??= EntityManager.GetEntityQuery <TransformComponent>();
        physicsQuery ??= EntityManager.GetEntityQuery <PhysicsComponent>();

        xform ??= xformQuery.Value.GetComponent(uid);
        var parent   = xform.ParentUid;
        var localPos = xform.LocalPosition;

        var     velocity         = component.LinearVelocity;
        Vector2 angularComponent = Vector2.Zero;

        while (parent.IsValid())
        {
            var parentXform = xformQuery.Value.GetComponent(parent);

            if (physicsQuery.Value.TryGetComponent(parent, out var body))
            {
                // add linear velocity of parent relative to it's own parent (again, in map coordinates)
                velocity += body.LinearVelocity;

                // add angular velocity that results from the parent's rotation (NOT in map coordinates, but in the parentXform.Parent's frame)
                angularComponent += Vector2.Cross(body.AngularVelocity, localPos - body.LocalCenter);
                angularComponent  = parentXform.LocalRotation.RotateVec(angularComponent);
            }

            localPos = parentXform.LocalPosition + parentXform.LocalRotation.RotateVec(localPos);
            parent   = parentXform.ParentUid;
        }

        // angular component of the velocity should now be in terms of map coordinates and can be added onto the sum of
        // linear velocities.
        return(velocity + angularComponent);
    }
Beispiel #23
0
        /// <summary>
        ///     Tries to toggle the anchored status of this component's owner.
        /// </summary>
        /// <returns>true if toggled, false otherwise</returns>
        public override void TryToggleAnchor(EntityUid uid, EntityUid userUid, EntityUid usingUid,
                                             AnchorableComponent?anchorable   = null,
                                             TransformComponent?transform     = null,
                                             SharedPullableComponent?pullable = null,
                                             ToolComponent?usingTool          = null)
        {
            if (!Resolve(uid, ref transform))
            {
                return;
            }

            if (transform.Anchored)
            {
                TryUnAnchor(uid, userUid, usingUid, anchorable, transform, usingTool);
            }
            else
            {
                TryAnchor(uid, userUid, usingUid, anchorable, transform, pullable, usingTool);
            }
        }
Beispiel #24
0
        /// <summary>
        ///     If this node should be considered for connection by other nodes.
        /// </summary>
        public virtual bool Connectable(IEntityManager entMan, TransformComponent?xform = null)
        {
            if (Deleting)
            {
                return(false);
            }

            if (entMan.IsQueuedForDeletion(Owner))
            {
                return(false);
            }

            if (!NeedAnchored)
            {
                return(true);
            }

            xform ??= entMan.GetComponent <TransformComponent>(Owner);
            return(xform.Anchored);
        }
    private void SetEnabled(CargoTelepadComponent component, ApcPowerReceiverComponent?receiver = null,
                            TransformComponent?xform = null)
    {
        // False due to AllCompsOneEntity test where they may not have the powerreceiver.
        if (!Resolve(component.Owner, ref receiver, ref xform, false))
        {
            return;
        }

        var disabled = !receiver.Powered || !xform.Anchored;

        // Setting idle state should be handled by Update();
        if (disabled)
        {
            return;
        }

        TryComp <AppearanceComponent>(component.Owner, out var appearance);
        component.CurrentState = CargoTelepadState.Unpowered;
        appearance?.SetData(CargoTelepadVisuals.State, CargoTelepadState.Unpowered);
    }
        public bool IsWeightless(EntityUid uid, PhysicsComponent?body = null, TransformComponent?xform = null)
        {
            Resolve(uid, ref body, false);

            if ((body?.BodyType & (BodyType.Static | BodyType.Kinematic)) != 0)
            {
                return(false);
            }

            if (TryComp <MovementIgnoreGravityComponent>(uid, out var ignoreGravityComponent))
            {
                return(ignoreGravityComponent.Weightless);
            }

            if (!Resolve(uid, ref xform))
            {
                return(true);
            }

            // If grid / map has gravity
            if ((TryComp <GravityComponent>(xform.GridUid, out var gravity) ||
                 TryComp(xform.MapUid, out gravity)) && gravity.Enabled)
            {
                return(false);
            }

            // Something holding us down
            // If the planet has gravity component and no gravity it will still give gravity
            // If there's no gravity comp at all (i.e. space) then they don't work.
            if (gravity != null && _inventory.TryGetSlotEntity(uid, "shoes", out var ent))
            {
                if (TryComp <MagbootsComponent>(ent, out var boots) && boots.On)
                {
                    return(false);
                }
            }

            return(true);
        }
Beispiel #27
0
        public void UpdateBounds(EntityUid uid, TransformComponent?xform = null)
        {
            var xformQuery = EntityManager.GetEntityQuery <TransformComponent>();

            if (xform == null)
            {
                xformQuery.TryGetComponent(uid, out xform);
            }

            if (xform == null)
            {
                Logger.Error($"Unable to resolve transform on {EntityManager.ToPrettyString(uid)}");
                DebugTools.Assert(false);
                return;
            }

            if (xform.Anchored || _container.IsEntityInContainer(uid, xform))
            {
                return;
            }

            var lookup = GetLookup(uid, xform, xformQuery);

            if (lookup == null)
            {
                return;
            }

            var lookupXform = xformQuery.GetComponent(lookup.Owner);
            var coordinates = _transform.GetMoverCoordinates(xform.Coordinates, xformQuery);
            // If we're contained then LocalRotation should be 0 anyway.
            var aabb = GetAABB(xform.Owner, coordinates.Position, _transform.GetWorldRotation(xform) - _transform.GetWorldRotation(lookupXform), xform, xformQuery);

            // TODO: Only container children need updating so could manually do this slightly better.
            AddToEntityTree(lookup, xform, aabb, xformQuery);
        }
        /// <summary>
        /// Retract the guardian if either the host or the guardian move away from each other.
        /// </summary>
        private void CheckGuardianMove(
            EntityUid hostUid,
            EntityUid guardianUid,
            GuardianHostComponent?hostComponent = null,
            GuardianComponent?guardianComponent = null,
            TransformComponent?hostXform        = null,
            TransformComponent?guardianXform    = null)
        {
            if (!Resolve(hostUid, ref hostComponent, ref hostXform) ||
                !Resolve(guardianUid, ref guardianComponent, ref guardianXform))
            {
                return;
            }

            if (!guardianComponent.GuardianLoose)
            {
                return;
            }

            if (!guardianXform.Coordinates.InRange(EntityManager, hostXform.Coordinates, guardianComponent.DistanceAllowed))
            {
                RetractGuardian(hostComponent, guardianComponent);
            }
        }
Beispiel #29
0
        public SuitSensorStatus?GetSensorState(EntityUid uid, SuitSensorComponent?sensor = null, TransformComponent?transform = null)
        {
            if (!Resolve(uid, ref sensor, ref transform))
            {
                return(null);
            }

            // check if sensor is enabled and worn by user
            if (sensor.Mode == SuitSensorMode.SensorOff || sensor.User == null)
            {
                return(null);
            }

            // try to get mobs id from ID slot
            var userName = Loc.GetString("suit-sensor-component-unknown-name");
            var userJob  = Loc.GetString("suit-sensor-component-unknown-job");

            if (_idCardSystem.TryFindIdCard(sensor.User.Value, out var card))
            {
                if (card.FullName != null)
                {
                    userName = card.FullName;
                }
                if (card.JobTitle != null)
                {
                    userJob = card.JobTitle;
                }
            }

            // get health mob state
            var isAlive = false;

            if (EntityManager.TryGetComponent(sensor.User.Value, out MobStateComponent? mobState))
            {
                isAlive = mobState.IsAlive();
            }

            // get mob total damage
            var totalDamage = 0;

            if (EntityManager.TryGetComponent(sensor.User.Value, out DamageableComponent? damageable))
            {
                totalDamage = damageable.TotalDamage.Int();
            }

            // finally, form suit sensor status
            var status = new SuitSensorStatus(userName, userJob);

            switch (sensor.Mode)
            {
            case SuitSensorMode.SensorBinary:
                status.IsAlive = isAlive;
                break;

            case SuitSensorMode.SensorVitals:
                status.IsAlive     = isAlive;
                status.TotalDamage = totalDamage;
                break;

            case SuitSensorMode.SensorCords:
                status.IsAlive     = isAlive;
                status.TotalDamage = totalDamage;
                status.Coordinates = transform.MapPosition;
                break;
            }

            return(status);
        }
        private bool IsCancelled(IEntityManager entityManager)
        {
            if (!entityManager.EntityExists(EventArgs.User) || EventArgs.Target is {} target&& !entityManager.EntityExists(target))
            {
                return(true);
            }

            //https://github.com/tgstation/tgstation/blob/1aa293ea337283a0191140a878eeba319221e5df/code/__HELPERS/mobs.dm
            if (EventArgs.CancelToken.IsCancellationRequested)
            {
                return(true);
            }

            // TODO :Handle inertia in space.
            if (EventArgs.BreakOnUserMove && !entityManager.GetComponent <TransformComponent>(EventArgs.User).Coordinates.InRange(
                    entityManager, UserGrid, EventArgs.MovementThreshold))
            {
                return(true);
            }

            if (EventArgs.Target != null &&
                EventArgs.BreakOnTargetMove &&
                !entityManager.GetComponent <TransformComponent>(EventArgs.Target !.Value).Coordinates.InRange(entityManager, TargetGrid, EventArgs.MovementThreshold))
            {
                return(true);
            }

            if (EventArgs.ExtraCheck != null && !EventArgs.ExtraCheck.Invoke())
            {
                return(true);
            }

            if (EventArgs.BreakOnStun &&
                entityManager.HasComponent <StunnedComponent>(EventArgs.User))
            {
                return(true);
            }

            if (EventArgs.NeedHand)
            {
                if (!entityManager.TryGetComponent(EventArgs.User, out HandsComponent? handsComponent))
                {
                    // If we had a hand but no longer have it that's still a paddlin'
                    if (_activeHand != null)
                    {
                        return(true);
                    }
                }
                else
                {
                    var currentActiveHand = handsComponent.ActiveHand?.Name;
                    if (_activeHand != currentActiveHand)
                    {
                        return(true);
                    }

                    var currentItem = handsComponent.ActiveHandEntity;
                    if (_activeItem != currentItem)
                    {
                        return(true);
                    }
                }
            }

            if (EventArgs.DistanceThreshold != null)
            {
                var xformQuery = entityManager.GetEntityQuery <TransformComponent>();
                TransformComponent?userXform = null;

                // Check user distance to target AND used entities.
                if (EventArgs.Target != null && !EventArgs.User.Equals(EventArgs.Target))
                {
                    //recalculate Target location in case Target has also moved
                    var targetCoordinates = xformQuery.GetComponent(EventArgs.Target.Value).Coordinates;
                    userXform ??= xformQuery.GetComponent(EventArgs.User);
                    if (!userXform.Coordinates.InRange(entityManager, targetCoordinates, EventArgs.DistanceThreshold.Value))
                    {
                        return(true);
                    }
                }

                if (EventArgs.Used != null)
                {
                    var targetCoordinates = xformQuery.GetComponent(EventArgs.Used.Value).Coordinates;
                    userXform ??= xformQuery.GetComponent(EventArgs.User);
                    if (!userXform.Coordinates.InRange(entityManager, targetCoordinates, EventArgs.DistanceThreshold.Value))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }