Exemplo n.º 1
0
        private void HandleDestroy(ServerSingularityComponent component, EntityUid entity)
        {
            // TODO: Need singuloimmune tag
            if (!CanDestroy(component, entity))
            {
                return;
            }

            // Singularity priority management / etc.
            if (EntityManager.TryGetComponent <ServerSingularityComponent?>(entity, out var otherSingulo))
            {
                // MERGE
                if (!otherSingulo.BeingDeletedByAnotherSingularity)
                {
                    component.Energy += otherSingulo.Energy;
                }

                otherSingulo.BeingDeletedByAnotherSingularity = true;
            }

            if (EntityManager.TryGetComponent <SinguloFoodComponent?>(entity, out var singuloFood))
            {
                component.Energy += singuloFood.Energy;
            }
            else
            {
                component.Energy++;
            }

            EntityManager.QueueDeleteEntity(entity);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Pull dynamic bodies in range to the singulo.
        /// </summary>
        private void PullEntities(ServerSingularityComponent component, TransformComponent xform, Vector2 worldPos, float frameTime)
        {
            // TODO: When we split up dynamic and static trees we might be able to make items always on the broadphase
            // in which case we can just query dynamictree directly for brrt
            var pullRange    = PullRange(component);
            var destroyRange = DestroyTileRange(component);

            foreach (var entity in _lookup.GetEntitiesInRange(xform.MapID, worldPos, pullRange))
            {
                // I tried having it so level 6 can de-anchor. BAD IDEA, MASSIVE LAG.
                if (entity == component.Owner ||
                    !EntityManager.TryGetComponent <PhysicsComponent?>(entity, out var collidableComponent) ||
                    collidableComponent.BodyType == BodyType.Static)
                {
                    continue;
                }

                if (!CanPull(entity))
                {
                    continue;
                }

                var vec = worldPos - EntityManager.GetComponent <TransformComponent>(entity).WorldPosition;

                if (vec.Length < destroyRange - 0.01f)
                {
                    continue;
                }

                var speed = vec.Length * component.Level * collidableComponent.Mass * 100f;

                // Because tile friction is so high we'll just multiply by mass so stuff like closets can even move.
                collidableComponent.ApplyLinearImpulse(vec.Normalized * speed * frameTime);
            }
        }
Exemplo n.º 3
0
        private void PullEntities(ServerSingularityComponent component)
        {
            var singularityCoords = component.Owner.Transform.Coordinates;
            // TODO: Maybe if we have named fixtures needs to pull out the outer circle collider (inner will be for deleting).
            var entitiesToPull = IoCManager.Resolve <IEntityLookup>().GetEntitiesInRange(singularityCoords, component.Level * 10);

            foreach (var entity in entitiesToPull)
            {
                if (!entity.TryGetComponent <PhysicsComponent>(out var collidableComponent) || collidableComponent.BodyType == BodyType.Static)
                {
                    continue;
                }
                if (entity.HasComponent <GhostComponent>())
                {
                    continue;
                }
                if (singularityCoords.EntityId != entity.Transform.Coordinates.EntityId)
                {
                    continue;
                }
                var vec = (singularityCoords - entity.Transform.Coordinates).Position;
                if (vec == Vector2.Zero)
                {
                    continue;
                }

                var speed = 10 / vec.Length * component.Level;

                collidableComponent.ApplyLinearImpulse(vec.Normalized * speed);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Handle deleting entities and increasing energy
        /// </summary>
        private void DestroyEntities(ServerSingularityComponent component, TransformComponent xform, Vector2 worldPos)
        {
            // The reason we don't /just/ use collision is because we'll be deleting stuff that may not necessarily have physics (e.g. carpets).
            var destroyRange = DestroyTileRange(component);

            foreach (var entity in _lookup.GetEntitiesInRange(xform.MapID, worldPos, destroyRange))
            {
                HandleDestroy(component, entity);
            }
        }
Exemplo n.º 5
0
        private void Update(ServerSingularityComponent component, float frameTime)
        {
            if (component.BeingDeletedByAnotherSingularity)
            {
                return;
            }

            var worldPos = EntityManager.GetComponent <TransformComponent>(component.Owner).WorldPosition;

            DestroyEntities(component, worldPos);
            DestroyTiles(component, worldPos);
            PullEntities(component, worldPos);
        }
Exemplo n.º 6
0
        private void Update(ServerSingularityComponent component, TransformComponent xform, float frameTime)
        {
            if (component.BeingDeletedByAnotherSingularity)
            {
                return;
            }

            var worldPos = xform.WorldPosition;

            DestroyEntities(component, xform, worldPos);
            DestroyTiles(component, xform, worldPos);
            PullEntities(component, xform, worldPos, frameTime);
        }
Exemplo n.º 7
0
        private void HandleCollide(EntityUid uid, ServerSingularityComponent component, StartCollideEvent args)
        {
            // If we're being deleted by another singularity, this call is probably for that singularity.
            // Even if not, just don't bother.
            if (component.BeingDeletedByAnotherSingularity)
            {
                return;
            }

            var otherEntity = args.OtherFixture.Body.Owner;

            if (otherEntity.TryGetComponent <IMapGridComponent>(out var mapGridComponent))
            {
                foreach (var tile in mapGridComponent.Grid.GetTilesIntersecting(args.OurFixture.Body.GetWorldAABB()))
                {
                    mapGridComponent.Grid.SetTile(tile.GridIndices, Robust.Shared.Map.Tile.Empty);
                    component.Energy++;
                }
                return;
            }

            if (otherEntity.HasComponent <ContainmentFieldComponent>() ||
                (otherEntity.TryGetComponent <ContainmentFieldGeneratorComponent>(out var containmentField) && containmentField.CanRepell(component.Owner)))
            {
                return;
            }

            if (otherEntity.IsInContainer())
            {
                return;
            }

            // Singularity priority management / etc.
            if (otherEntity.TryGetComponent <ServerSingularityComponent>(out var otherSingulo))
            {
                otherSingulo.BeingDeletedByAnotherSingularity = true;
            }

            otherEntity.QueueDelete();

            if (otherEntity.TryGetComponent <SinguloFoodComponent>(out var singuloFood))
            {
                component.Energy += singuloFood.Energy;
            }
            else
            {
                component.Energy++;
            }
        }
Exemplo n.º 8
0
        private void DestroyTiles(ServerSingularityComponent component)
        {
            if (!component.Owner.TryGetComponent(out PhysicsComponent? physicsComponent))
            {
                return;
            }
            var worldBox = physicsComponent.GetWorldAABB();

            foreach (var grid in _mapManager.FindGridsIntersecting(component.Owner.Transform.MapID, worldBox))
            {
                foreach (var tile in grid.GetTilesIntersecting(worldBox))
                {
                    grid.SetTile(tile.GridIndices, Tile.Empty);
                }
            }
        }
Exemplo n.º 9
0
        private void HandleCollide(EntityUid uid, ServerSingularityComponent component, StartCollideEvent args)
        {
            // This handles bouncing off of containment walls.
            // If you want the delete behavior we do it under DeleteEntities for reasons (not everything has physics).

            // If we're being deleted by another singularity, this call is probably for that singularity.
            // Even if not, just don't bother.
            if (component.BeingDeletedByAnotherSingularity)
            {
                return;
            }

            // Using this to also get smooth deletions is hard because we need to be hard for good bounce
            // off of containment but also we need to be non-hard so we can freely move through the station.
            // For now I've just made it so only the lookup does deletions and collision is just for fields.
        }
Exemplo n.º 10
0
        /// <summary>
        /// Destroy any grid tiles within the relevant Level range.
        /// </summary>
        private void DestroyTiles(ServerSingularityComponent component, TransformComponent xform, Vector2 worldPos)
        {
            var radius = DestroyTileRange(component);

            var circle = new Circle(worldPos, radius);
            var box    = new Box2(worldPos - radius, worldPos + radius);

            foreach (var grid in _mapManager.FindGridsIntersecting(xform.MapID, box))
            {
                // Bundle these together so we can use the faster helper to set tiles.
                var toDestroy = new List <(Vector2i, Tile)>();

                foreach (var tile in grid.GetTilesIntersecting(circle))
                {
                    if (tile.Tile.IsEmpty)
                    {
                        continue;
                    }

                    // Avoid ripping up tiles that may be essential to containment
                    if (component.Level < 5)
                    {
                        var canDelete = true;

                        foreach (var ent in grid.GetAnchoredEntities(tile.GridIndices))
                        {
                            if (EntityManager.HasComponent <ContainmentFieldComponent>(ent) ||
                                EntityManager.HasComponent <ContainmentFieldGeneratorComponent>(ent))
                            {
                                canDelete = false;
                                break;
                            }
                        }

                        if (!canDelete)
                        {
                            continue;
                        }
                    }

                    toDestroy.Add((tile.GridIndices, Tile.Empty));
                }

                component.Energy += TileEnergyGain * toDestroy.Count;
                grid.SetTiles(toDestroy);
            }
        }
        private void MoveSingulo(ServerSingularityComponent singularity, PhysicsComponent physics)
        {
            // TODO: Need to make this events instead.
            if (singularity.Level <= 1)
            {
                physics.BodyStatus = BodyStatus.OnGround;
                return;
            }

            // TODO: Could try gradual changes instead
            var pushAngle    = _robustRandom.NextAngle();
            var pushStrength = _robustRandom.NextFloat(0.75f, 1.0f);

            physics.LinearVelocity = Vector2.Zero;
            physics.BodyStatus     = BodyStatus.InAir;
            physics.ApplyLinearImpulse(pushAngle.ToVec() * (pushStrength + 10f / Math.Min(singularity.Level, 4) * physics.Mass));
            // TODO: Speedcap it probably?
        }
Exemplo n.º 12
0
        private void MoveSingulo(ServerSingularityComponent singularity, PhysicsComponent physics)
        {
            if (singularity.Level <= 1)
            {
                return;
            }
            // TODO: Could try gradual changes instead but for now just try to replicate

            var pushVector = new Vector2(_robustRandom.Next(-10, 10), _robustRandom.Next(-10, 10));

            if (pushVector == Vector2.Zero)
            {
                return;
            }

            physics.LinearVelocity = Vector2.Zero;
            physics.LinearVelocity = pushVector.Normalized * 2;
        }
Exemplo n.º 13
0
        private void MoveSingulo(ServerSingularityComponent singularity, PhysicsComponent physics)
        {
            // To prevent getting stuck, ServerSingularityComponent will zero the velocity of a singularity when it goes to a level <= 1 (see here).
            if (singularity.Level <= 1)
            {
                return;
            }
            // TODO: Could try gradual changes instead but for now just try to replicate

            var pushVector = new Vector2(_robustRandom.Next(-10, 10), _robustRandom.Next(-10, 10));

            if (pushVector == Vector2.Zero)
            {
                return;
            }

            physics.LinearVelocity = Vector2.Zero;
            physics.LinearVelocity = pushVector.Normalized * 2;
        }
Exemplo n.º 14
0
        /// <summary>
        /// Destroy any grid tiles within the relevant Level range.
        /// </summary>
        private void DestroyTiles(ServerSingularityComponent component, Vector2 worldPos)
        {
            var radius = DestroyTileRange(component);

            var circle = new Circle(worldPos, radius);
            var box    = new Box2(worldPos - radius, worldPos + radius);

            foreach (var grid in _mapManager.FindGridsIntersecting(EntityManager.GetComponent <TransformComponent>(component.Owner).MapID, box))
            {
                foreach (var tile in grid.GetTilesIntersecting(circle))
                {
                    if (tile.Tile.IsEmpty)
                    {
                        continue;
                    }
                    grid.SetTile(tile.GridIndices, Tile.Empty);
                    component.Energy += TileEnergyGain;
                }
            }
        }
Exemplo n.º 15
0
        private void MoveSingulo(ServerSingularityComponent singularity, PhysicsComponent physics)
        {
            // TODO: Need to make this events instead.
            if (singularity.Level <= 1)
            {
                physics.BodyStatus = BodyStatus.OnGround;
                return;
            }

            // TODO: Could try gradual changes instead
            var pushVector = new Vector2(_robustRandom.Next(-10, 10), _robustRandom.Next(-10, 10));

            if (pushVector == Vector2.Zero)
            {
                return;
            }

            physics.LinearVelocity = Vector2.Zero;
            physics.BodyStatus     = BodyStatus.InAir;
            physics.ApplyLinearImpulse(pushVector.Normalized + 1f / singularity.Level * physics.Mass);
            // TODO: Speedcap it probably?
        }
Exemplo n.º 16
0
        private void OnCollide(EntityUid uid, ServerSingularityComponent component, StartCollideEvent args)
        {
            if (args.OurFixture.ID != "DeleteCircle")
            {
                return;
            }

            // This handles bouncing off of containment walls.
            // If you want the delete behavior we do it under DeleteEntities for reasons (not everything has physics).

            // If we're being deleted by another singularity, this call is probably for that singularity.
            // Even if not, just don't bother.
            if (component.BeingDeletedByAnotherSingularity)
            {
                return;
            }

            var otherUid = args.OtherFixture.Body.Owner;

            // HandleDestroy will also check CanDestroy for us
            HandleDestroy(component, otherUid);
        }
Exemplo n.º 17
0
 private float DestroyTileRange(ServerSingularityComponent component)
 {
     return(component.Level - 0.5f);
 }
Exemplo n.º 18
0
 private float PullRange(ServerSingularityComponent component)
 {
     // Level 6 is normally 15 range but that's yuge.
     return(2 + component.Level * 2);
 }