Ejemplo n.º 1
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);
    }
    /// <summary>
    /// Retrieves a shuttle for delivery.
    /// </summary>
    public void CallShuttle(StationCargoOrderDatabaseComponent orderDatabase)
    {
        if (!TryComp <CargoShuttleComponent>(orderDatabase.Shuttle, out var shuttle) ||
            !TryComp <TransformComponent>(orderDatabase.Owner, out var xform))
        {
            return;
        }

        // Already called / not available
        if (shuttle.NextCall == null || _timing.CurTime < shuttle.NextCall)
        {
            return;
        }

        shuttle.NextCall = null;

        // Find a valid free area nearby to spawn in on
        // TODO: Make this use hyperspace now.
        var  center    = new Vector2();
        var  minRadius = 0f;
        Box2?aabb      = null;

        foreach (var grid in _mapManager.GetAllMapGrids(xform.MapID))
        {
            aabb = aabb?.Union(grid.WorldAABB) ?? grid.WorldAABB;
        }

        if (aabb != null)
        {
            center    = aabb.Value.Center;
            minRadius = MathF.Max(aabb.Value.Width, aabb.Value.Height);
        }

        var offset = 0f;

        if (TryComp <IMapGridComponent>(orderDatabase.Shuttle, out var shuttleGrid))
        {
            var bounds = shuttleGrid.Grid.LocalAABB;
            offset = MathF.Max(bounds.Width, bounds.Height) / 2f;
        }

        Transform(shuttle.Owner).Coordinates = new EntityCoordinates(xform.ParentUid,
                                                                     center + _random.NextVector2(minRadius + offset, minRadius + CallOffset + offset));
        DebugTools.Assert(!MetaData(shuttle.Owner).EntityPaused);

        AddCargoContents(shuttle, orderDatabase);
        UpdateOrders(orderDatabase);
        UpdateShuttleCargoConsoles(shuttle);
        _console.RefreshShuttleConsoles();

        _sawmill.Info($"Retrieved cargo shuttle {ToPrettyString(shuttle.Owner)} from {ToPrettyString(orderDatabase.Owner)}");
    }
Ejemplo n.º 3
0
    public Box2 GetWorldAABB(PhysicsComponent body, TransformComponent xform, EntityQuery <TransformComponent> xforms, EntityQuery <FixturesComponent> fixtures)
    {
        var(worldPos, worldRot) = xform.GetWorldPositionRotation(xforms);

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

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

        foreach (var fixture in fixtures.GetComponent(body.Owner).Fixtures.Values)
        {
            for (var i = 0; i < fixture.Shape.ChildCount; i++)
            {
                var boundy = fixture.Shape.ComputeAABB(transform, i);
                bounds = bounds.Union(boundy);
            }
        }

        return(bounds);
    }
Ejemplo n.º 4
0
        /// <summary>
        /// Expands the AABB for this grid when a new tile is added. If the tile is already inside the existing AABB,
        /// nothing happens. If it is outside, the AABB is expanded to fit the new tile.
        /// </summary>
        private void UpdateAABB()
        {
            LocalBounds = new Box2();
            foreach (var chunk in _chunks.Values)
            {
                var chunkBounds = chunk.CalcLocalBounds();

                if (chunkBounds.Size.Equals(Vector2i.Zero))
                {
                    continue;
                }

                if (LocalBounds.Size == Vector2.Zero)
                {
                    var gridBounds = chunkBounds.Translated(chunk.Indices * chunk.ChunkSize);
                    LocalBounds = gridBounds;
                }
                else
                {
                    var gridBounds = chunkBounds.Translated(chunk.Indices * chunk.ChunkSize);
                    LocalBounds = LocalBounds.Union(gridBounds);
                }
            }
        }
Ejemplo n.º 5
0
        public override void Update(float frameTime)
        {
            base.Update(frameTime);

            if (!Started)
            {
                return;
            }

            if (_waveCounter <= 0)
            {
                Running = false;
                return;
            }
            _cooldown -= frameTime;

            if (_cooldown > 0f)
            {
                return;
            }

            _waveCounter--;

            _cooldown += (MaximumCooldown - MinimumCooldown) * _robustRandom.NextFloat() + MinimumCooldown;

            Box2?playableArea = null;
            var  mapId        = EntitySystem.Get <GameTicker>().DefaultMap;

            foreach (var grid in _mapManager.GetAllGrids())
            {
                if (grid.ParentMapId != mapId || !_entityManager.TryGetComponent(grid.GridEntityId, out PhysicsComponent? gridBody))
                {
                    continue;
                }
                var aabb = gridBody.GetWorldAABB();
                playableArea = playableArea?.Union(aabb) ?? aabb;
            }

            if (playableArea == null)
            {
                EndAfter = float.MinValue;
                return;
            }

            var minimumDistance = (playableArea.Value.TopRight - playableArea.Value.Center).Length + 50f;
            var maximumDistance = minimumDistance + 100f;

            var center = playableArea.Value.Center;

            for (var i = 0; i < MeteorsPerWave; i++)
            {
                var angle         = new Angle(_robustRandom.NextFloat() * MathF.Tau);
                var offset        = angle.RotateVec(new Vector2((maximumDistance - minimumDistance) * _robustRandom.NextFloat() + minimumDistance, 0));
                var spawnPosition = new MapCoordinates(center + offset, mapId);
                var meteor        = _entityManager.SpawnEntity("MeteorLarge", spawnPosition);
                var physics       = _entityManager.GetComponent <PhysicsComponent>(meteor.Uid);
                physics.BodyStatus     = BodyStatus.InAir;
                physics.LinearDamping  = 0f;
                physics.AngularDamping = 0f;
                physics.ApplyLinearImpulse(-offset.Normalized * MeteorVelocity * physics.Mass);
                physics.ApplyAngularImpulse(
                    // Get a random angular velocity.
                    physics.Mass * ((MaxAngularVelocity - MinAngularVelocity) * _robustRandom.NextFloat() +
                                    MinAngularVelocity));
                // TODO: God this disgusts me but projectile needs a refactor.
                meteor.GetComponent <ProjectileComponent>().TimeLeft = 120f;
            }
        }
        private DockingComponent?GetDockable(PhysicsComponent body, TransformComponent dockingXform)
        {
            // Did you know Saltern is the most dockable station?

            // Assume the docking port itself (and its body) is valid

            if (!_mapManager.TryGetGrid(dockingXform.GridID, out var grid) ||
                !HasComp <ShuttleComponent>(grid.GridEntityId))
            {
                return(null);
            }

            var transform      = body.GetTransform();
            var dockingFixture = _fixtureSystem.GetFixtureOrNull(body, DockingFixture);

            if (dockingFixture == null)
            {
                DebugTools.Assert(false);
                Logger.ErrorS("docking", $"Found null fixture on {(body).Owner}");
                return(null);
            }

            Box2?aabb = null;

            for (var i = 0; i < dockingFixture.Shape.ChildCount; i++)
            {
                aabb = aabb?.Union(dockingFixture.Shape.ComputeAABB(transform, i)) ?? dockingFixture.Shape.ComputeAABB(transform, i);
            }

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

            var enlargedAABB = aabb.Value.Enlarged(DockingRadius * 1.5f);

            // Get any docking ports in range on other grids.
            _mapManager.FindGridsIntersectingEnumerator(dockingXform.MapID, enlargedAABB, out var enumerator);

            while (enumerator.MoveNext(out var otherGrid))
            {
                if (otherGrid.Index == dockingXform.GridID)
                {
                    continue;
                }

                foreach (var ent in otherGrid.GetAnchoredEntities(enlargedAABB))
                {
                    if (!TryComp(ent, out DockingComponent? otherDocking) ||
                        !otherDocking.Enabled ||
                        !TryComp(ent, out PhysicsComponent? otherBody))
                    {
                        continue;
                    }

                    var otherTransform      = otherBody.GetTransform();
                    var otherDockingFixture = _fixtureSystem.GetFixtureOrNull(otherBody, DockingFixture);

                    if (otherDockingFixture == null)
                    {
                        DebugTools.Assert(false);
                        Logger.ErrorS("docking", $"Found null docking fixture on {ent}");
                        continue;
                    }

                    for (var i = 0; i < otherDockingFixture.Shape.ChildCount; i++)
                    {
                        var otherAABB = otherDockingFixture.Shape.ComputeAABB(otherTransform, i);

                        if (!aabb.Value.Intersects(otherAABB))
                        {
                            continue;
                        }

                        // TODO: Need CollisionManager's GJK for accurate bounds
                        // Realistically I want 2 fixtures anyway but I'll deal with that later.
                        return(otherDocking);
                    }
                }
            }

            return(null);
        }