예제 #1
0
    public override void Update(float frameTime)
    {
        base.Update(frameTime);

        foreach (var eggLayer in EntityQuery <EggLayerComponent>())
        {
            // Players should be using the action.
            if (HasComp <ActorComponent>(eggLayer.Owner))
            {
                return;
            }

            eggLayer.AccumulatedFrametime += frameTime;

            if (eggLayer.AccumulatedFrametime < eggLayer.CurrentEggLayCooldown)
            {
                continue;
            }

            eggLayer.AccumulatedFrametime -= eggLayer.CurrentEggLayCooldown;
            eggLayer.CurrentEggLayCooldown = _random.NextFloat(eggLayer.EggLayCooldownMin, eggLayer.EggLayCooldownMax);

            TryLayEgg(eggLayer.Owner, eggLayer);
        }
    }
예제 #2
0
    public override void Update(float frameTime)
    {
        foreach (var buffering in EntityQuery <BufferingComponent>())
        {
            if (buffering.BufferingIcon is not null)
            {
                buffering.BufferingTimer -= frameTime;
                if (!(buffering.BufferingTimer <= 0.0f))
                {
                    continue;
                }

                Del(buffering.BufferingIcon.Value);
                RemComp <AdminFrozenComponent>(buffering.Owner);
                buffering.TimeTilNextBuffer = _random.NextFloat(buffering.MinimumTimeTilNextBuffer, buffering.MaximumTimeTilNextBuffer);
                buffering.BufferingIcon     = null;
            }
            else
            {
                buffering.TimeTilNextBuffer -= frameTime;
                if (!(buffering.TimeTilNextBuffer <= 0.0f))
                {
                    continue;
                }

                buffering.BufferingTimer = _random.NextFloat(buffering.MinimumBufferTime, buffering.MaximumBufferTime);
                buffering.BufferingIcon  = Spawn("BufferingIcon", new EntityCoordinates(buffering.Owner, Vector2.Zero));
                EnsureComp <AdminFrozenComponent>(buffering.Owner);
            }
        }
    }
        private void Spawn(RandomSpawnerComponent component)
        {
            if (component.RarePrototypes.Count > 0 && (component.RareChance == 1.0f || _robustRandom.Prob(component.RareChance)))
            {
                EntityManager.SpawnEntity(_robustRandom.Pick(component.RarePrototypes), Transform(component.Owner).Coordinates);
                return;
            }

            if (component.Chance != 1.0f && !_robustRandom.Prob(component.Chance))
            {
                return;
            }

            if (component.Prototypes.Count == 0)
            {
                Logger.Warning($"Prototype list in RandomSpawnerComponent is empty! Entity: {component.Owner}");
                return;
            }

            if (Deleted(component.Owner))
            {
                return;
            }

            var offset  = component.Offset;
            var xOffset = _robustRandom.NextFloat(-offset, offset);
            var yOffset = _robustRandom.NextFloat(-offset, offset);

            var coordinates = Transform(component.Owner).Coordinates.Offset(new Vector2(xOffset, yOffset));

            EntityManager.SpawnEntity(_robustRandom.Pick(component.Prototypes), coordinates);
        }
    private void OnActivate(EntityUid uid, SpawnArtifactComponent component, ArtifactActivatedEvent args)
    {
        if (component.Prototype == null)
        {
            return;
        }
        if (component.SpawnsCount >= component.MaxSpawns)
        {
            return;
        }

        // select spawn position near artifact
        var artifactCord = Transform(uid).Coordinates;
        var dx           = _random.NextFloat(-component.Range, component.Range);
        var dy           = _random.NextFloat(-component.Range, component.Range);
        var spawnCord    = artifactCord.Offset(new Vector2(dx, dy));

        // spawn entity
        var spawned = EntityManager.SpawnEntity(component.Prototype, spawnCord);

        component.SpawnsCount++;

        // if there is an user - try to put spawned item in their hands
        // doesn't work for spawners
        _handsSystem.PickupOrDrop(args.Activator, spawned);
    }
예제 #5
0
    private void OnComponentInit(EntityUid uid, OrbitVisualsComponent component, ComponentInit args)
    {
        component.OrbitDistance =
            _robustRandom.NextFloat(0.75f * component.OrbitDistance, 1.25f * component.OrbitDistance);

        component.OrbitLength = _robustRandom.NextFloat(0.5f * component.OrbitLength, 1.5f * component.OrbitLength);

        if (TryComp <SpriteComponent>(uid, out var sprite))
        {
            sprite.EnableDirectionOverride = true;
            sprite.DirectionOverride       = Direction.South;
        }

        var animationPlayer = EntityManager.EnsureComponent <AnimationPlayerComponent>(uid);

        if (animationPlayer.HasRunningAnimation(_orbitAnimationKey))
        {
            return;
        }

        if (animationPlayer.HasRunningAnimation(_orbitStopKey))
        {
            animationPlayer.Stop(_orbitStopKey);
        }

        animationPlayer.Play(GetOrbitAnimation(component), _orbitAnimationKey);
    }
    private void FallOver(EntityUid uid, StandingStateComponent component, DropHandItemsEvent args)
    {
        var direction = EntityManager.TryGetComponent(uid, out PhysicsComponent? comp) ? comp.LinearVelocity / 50 : Vector2.Zero;
        var dropAngle = _random.NextFloat(0.8f, 1.2f);

        if (!TryComp(uid, out SharedHandsComponent? handsComp))
        {
            return;
        }

        var worldRotation = EntityManager.GetComponent <TransformComponent>(uid).WorldRotation.ToVec();

        foreach (var hand in handsComp.Hands.Values)
        {
            if (hand.HeldEntity is not EntityUid held)
            {
                continue;
            }

            if (!_handsSystem.TryDrop(uid, hand, null, checkActionBlocker: false, handsComp: handsComp))
            {
                continue;
            }

            _throwingSystem.TryThrow(held,
                                     _random.NextAngle().RotateVec(direction / dropAngle + worldRotation / 50),
                                     0.5f * dropAngle * _random.NextFloat(-0.9f, 1.1f),
                                     uid, 0);
        }
    }
예제 #7
0
    private void OnActivate(EntityUid uid, SpawnArtifactComponent component, ArtifactActivatedEvent args)
    {
        if (component.Prototype == null)
        {
            return;
        }
        if (component.SpawnsCount >= component.MaxSpawns)
        {
            return;
        }

        // select spawn position near artifact
        var artifactCord = Transform(uid).Coordinates;
        var dx           = _random.NextFloat(-component.Range, component.Range);
        var dy           = _random.NextFloat(-component.Range, component.Range);
        var spawnCord    = artifactCord.Offset(new Vector2(dx, dy));

        // spawn entity
        var spawned = EntityManager.SpawnEntity(component.Prototype, spawnCord);

        component.SpawnsCount++;

        // if there is an user - try to put spawned item in their hands
        // doesn't work for spawners
        if (args.Activator != null &&
            EntityManager.TryGetComponent(args.Activator.Value, out SharedHandsComponent? hands) &&
            EntityManager.HasComponent <ItemComponent>(spawned))
        {
            hands.TryPutInAnyHand(spawned);
        }
    }
        private void ShakeGrid(GridId gridId)
        {
            foreach (var player in _playerManager.GetAllPlayers())
            {
                if (player.AttachedEntity == null ||
                    player.AttachedEntity.Transform.GridID != gridId ||
                    !player.AttachedEntity.TryGetComponent(out CameraRecoilComponent recoil))
                {
                    continue;
                }

                recoil.Kick(new Vector2(_random.NextFloat(), _random.NextFloat()) * GravityKick);
            }
        }
예제 #9
0
        private void ShotTimerCallback(EmitterComponent component)
        {
            if (component.Deleted)
            {
                return;
            }

            // Any power-off condition should result in the timer for this method being cancelled
            // and thus not firing
            DebugTools.Assert(component.IsPowered);
            DebugTools.Assert(component.IsOn);
            DebugTools.Assert(component.PowerConsumer != null && (component.PowerConsumer.DrawRate <= component.PowerConsumer.ReceivedPower));

            Fire(component);

            TimeSpan delay;

            if (component.FireShotCounter < component.FireBurstSize)
            {
                component.FireShotCounter += 1;
                delay = component.FireInterval;
            }
            else
            {
                component.FireShotCounter = 0;
                var diff = component.FireBurstDelayMax - component.FireBurstDelayMin;
                // TIL you can do TimeSpan * double.
                delay = component.FireBurstDelayMin + _random.NextFloat() * diff;
            }

            // Must be set while emitter powered.
            DebugTools.AssertNotNull(component.TimerCancel);
            Timer.Spawn(delay, () => ShotTimerCallback(component), component.TimerCancel !.Token);
        }
예제 #10
0
        private void ShotTimerCallback()
        {
            // Any power-off condition should result in the timer for this method being cancelled
            // and thus not firing
            DebugTools.Assert(_isPowered);
            DebugTools.Assert(_isOn);
            DebugTools.Assert(_powerConsumer.DrawRate <= _powerConsumer.ReceivedPower);

            Fire();

            TimeSpan delay;

            if (_fireShotCounter < _fireBurstSize)
            {
                _fireShotCounter += 1;
                delay             = _fireInterval;
            }
            else
            {
                _fireShotCounter = 0;
                var diff = _fireBurstDelayMax - _fireBurstDelayMin;
                // TIL you can do TimeSpan * double.
                delay = _fireBurstDelayMin + _robustRandom.NextFloat() * diff;
            }

            // Must be set while emitter powered.
            DebugTools.AssertNotNull(_timerCancel);
            Timer.Spawn(delay, ShotTimerCallback, _timerCancel !.Token);
        }
예제 #11
0
 private void SpawnPulse(IMapGrid mapGrid)
 {
     var pulse = _entityManager.SpawnEntity("RadiationPulse", FindRandomGrid(mapGrid));
     pulse.GetComponent<RadiationPulseComponent>().DoPulse();
     _timeUntilPulse = _robustRandom.NextFloat() * (MaxPulseDelay - MinPulseDelay) + MinPulseDelay;
     _pulsesRemaining -= 1;
 }
예제 #12
0
        private Animation GetAnimation(JitteringComponent jittering, ISpriteComponent sprite)
        {
            var amplitude = MathF.Min(4f, jittering.Amplitude / 100f + 1f) / 10f;
            var offset    = new Vector2(_random.NextFloat(amplitude / 4f, amplitude),
                                        _random.NextFloat(amplitude / 4f, amplitude / 3f));

            offset.X *= _random.Pick(_sign);
            offset.Y *= _random.Pick(_sign);

            if (Math.Sign(offset.X) == Math.Sign(jittering.LastJitter.X) ||
                Math.Sign(offset.Y) == Math.Sign(jittering.LastJitter.Y))
            {
                // If the sign is the same as last time on both axis we flip one randomly
                // to avoid jitter staying in one quadrant too much.
                if (_random.Prob(0.5f))
                {
                    offset.X *= -1;
                }
                else
                {
                    offset.Y *= -1;
                }
            }

            // Animation length shouldn't be too high so we will cap it at 2 seconds...
            var length = Math.Min((1f / jittering.Frequency), 2f);

            jittering.LastJitter = offset;

            return(new Animation()
            {
                Length = TimeSpan.FromSeconds(length),
                AnimationTracks =
                {
                    new AnimationTrackComponentProperty()
                    {
                        ComponentType = typeof(ISpriteComponent),
                        Property = nameof(ISpriteComponent.Offset),
                        KeyFrames =
                        {
                            new AnimationTrackProperty.KeyFrame(sprite.Offset,     0f),
                            new AnimationTrackProperty.KeyFrame(offset,        length),
                        }
                    }
                }
            });
        }
예제 #13
0
        public void TryEjectVendorItem(EntityUid uid, string itemId, bool throwItem, VendingMachineComponent?vendComponent = null)
        {
            if (!Resolve(uid, ref vendComponent))
            {
                return;
            }

            if (vendComponent.Ejecting || vendComponent.Broken || !IsPowered(uid, vendComponent))
            {
                return;
            }

            var entry = vendComponent.Inventory.Find(x => x.ID == itemId);

            if (entry == null)
            {
                _popupSystem.PopupEntity(Loc.GetString("vending-machine-component-try-eject-invalid-item"), uid, Filter.Pvs(uid));
                Deny(uid, vendComponent);
                return;
            }

            if (entry.Amount <= 0)
            {
                _popupSystem.PopupEntity(Loc.GetString("vending-machine-component-try-eject-out-of-stock"), uid, Filter.Pvs(uid));
                Deny(uid, vendComponent);
                return;
            }

            if (entry.ID == null)
            {
                return;
            }

            if (!TryComp <TransformComponent>(vendComponent.Owner, out var transformComp))
            {
                return;
            }

            // Start Ejecting, and prevent users from ordering while anim playing
            vendComponent.Ejecting = true;
            entry.Amount--;
            vendComponent.UserInterface?.SendMessage(new VendingMachineInventoryMessage(vendComponent.Inventory));
            TryUpdateVisualState(uid, VendingMachineVisualState.Eject, vendComponent);
            vendComponent.Owner.SpawnTimer(vendComponent.AnimationDuration, () =>
            {
                vendComponent.Ejecting = false;
                TryUpdateVisualState(uid, VendingMachineVisualState.Normal, vendComponent);
                var ent = EntityManager.SpawnEntity(entry.ID, transformComp.Coordinates);
                if (throwItem)
                {
                    float range       = vendComponent.NonLimitedEjectRange;
                    Vector2 direction = new Vector2(_random.NextFloat(-range, range), _random.NextFloat(-range, range));
                    _throwingSystem.TryThrow(ent, direction, vendComponent.NonLimitedEjectForce);
                }
            });
            SoundSystem.Play(Filter.Pvs(vendComponent.Owner), vendComponent.SoundVend.GetSound(), vendComponent.Owner, AudioParams.Default.WithVolume(-2f));
        }
예제 #14
0
        private Vector2 RandomOffset()
        {
            return(new Vector2(RandomOffset(), RandomOffset()));

            float RandomOffset()
            {
                var size = 15.0F;

                return((_robustRandom.NextFloat() * size) - size / 2);
            }
        }
예제 #15
0
    private void OnComponentInit(EntityUid uid, OrbitVisualsComponent component, ComponentInit args)
    {
        component.OrbitDistance =
            _robustRandom.NextFloat(0.75f * component.OrbitDistance, 1.25f * component.OrbitDistance);

        component.OrbitLength = _robustRandom.NextFloat(0.5f * component.OrbitLength, 1.5f * component.OrbitLength);

        var animationPlayer = EntityManager.EnsureComponent <AnimationPlayerComponent>(uid);

        if (animationPlayer.HasRunningAnimation(_orbitAnimationKey))
        {
            return;
        }

        if (animationPlayer.HasRunningAnimation(_orbitStopKey))
        {
            animationPlayer.Stop(_orbitStopKey);
        }

        animationPlayer.Play(GetOrbitAnimation(component), _orbitAnimationKey);
    }
예제 #16
0
        public void CreateSparks(GridCoordinates coords, int minAmount, int maxAmount)
        {
            var amount = _random.Next(minAmount, maxAmount);

            for (var i = amount; i > 0; i--)
            {
                var spark = _entityManager.SpawnEntity("SparkEffect", coords);
                spark.GetComponent <SparkComponent>().Lifetime = Math.Min(0.5f, _random.NextFloat());
                spark.TryGetComponent <ICollidableComponent>(out var collidable);
                collidable.EnsureController <MoverController>().Push(Angle.FromDegrees(_random.Next(360)).ToVec(), 3.0f);
            }
        }
예제 #17
0
        /// <summary>
        /// Drops a single cartridge / shell
        /// Made as a static function just because multiple places need it
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="playSound"></param>
        /// <param name="robustRandom"></param>
        /// <param name="prototypeManager"></param>
        /// <param name="ejectDirections"></param>
        public static void EjectCasing(
            IEntity entity,
            bool playSound                     = true,
            IRobustRandom robustRandom         = null,
            IPrototypeManager prototypeManager = null,
            Direction[] ejectDirections        = null)
        {
            if (robustRandom == null)
            {
                robustRandom = IoCManager.Resolve <IRobustRandom>();
            }

            if (ejectDirections == null)
            {
                ejectDirections = new[] { Direction.East, Direction.North, Direction.South, Direction.West };
            }

            const float ejectOffset = 0.2f;
            var         ammo        = entity.GetComponent <AmmoComponent>();
            var         offsetPos   = (robustRandom.NextFloat() * ejectOffset, robustRandom.NextFloat() * ejectOffset);

            entity.Transform.Coordinates   = entity.Transform.Coordinates.Offset(offsetPos);
            entity.Transform.LocalRotation = robustRandom.Pick(ejectDirections).ToAngle();

            if (ammo.SoundCollectionEject == null || !playSound)
            {
                return;
            }

            if (prototypeManager == null)
            {
                prototypeManager = IoCManager.Resolve <IPrototypeManager>();
            }

            var soundCollection = prototypeManager.Index <SoundCollectionPrototype>(ammo.SoundCollectionEject);
            var randomFile      = robustRandom.Pick(soundCollection.PickFiles);

            SoundSystem.Play(Filter.Broadcast(), randomFile, entity.Transform.Coordinates, AudioParams.Default.WithVolume(-1));
        }
예제 #18
0
    private void OnMapInit(EntityUid uid, GasArtifactComponent component, MapInitEvent args)
    {
        if (component.SpawnGas == null && component.PossibleGases.Length != 0)
        {
            var gas = _random.Pick(component.PossibleGases);
            component.SpawnGas = gas;
        }

        if (component.SpawnTemperature == null)
        {
            var temp = _random.NextFloat(component.MinRandomTemperature, component.MaxRandomTemperature);
            component.SpawnTemperature = temp;
        }
    }
    private void FallOver(EntityUid uid, StandingStateComponent component, DropHandItemsEvent args)
    {
        var direction = EntityManager.TryGetComponent(uid, out PhysicsComponent? comp) ? comp.LinearVelocity / 50 : Vector2.Zero;
        var dropAngle = _random.NextFloat(0.8f, 1.2f);

        if (!EntityManager.TryGetComponent(uid, out HandsComponent? hands))
        {
            return;
        }

        foreach (var heldItem in hands.GetAllHeldItems())
        {
            if (!hands.Drop(heldItem.Owner))
            {
                continue;
            }

            var worldRotation = EntityManager.GetComponent <TransformComponent>(uid).WorldRotation.ToVec();
            Throwing.ThrowHelper.TryThrow(heldItem.Owner,
                                          _random.NextAngle().RotateVec(direction / dropAngle + worldRotation / 50),
                                          0.5f * dropAngle * _random.NextFloat(-0.9f, 1.1f),
                                          uid, 0);
        }
    }
        public override void UpdateBeforeSolve(bool prediction, float frameTime)
        {
            base.UpdateBeforeSolve(prediction, frameTime);

            foreach (var(singularity, physics) in EntityManager.EntityQuery <ServerSingularityComponent, PhysicsComponent>())
            {
                if (EntityManager.HasComponent <ActorComponent>(singularity.Owner) ||
                    singularity.BeingDeletedByAnotherSingularity)
                {
                    continue;
                }

                singularity.MoveAccumulator -= frameTime;

                if (singularity.MoveAccumulator > 0f)
                {
                    continue;
                }

                singularity.MoveAccumulator = _robustRandom.NextFloat(MinMoveCooldown, MaxMoveCooldown);

                MoveSingulo(singularity, physics);
            }
        }
예제 #21
0
        private void Spark()
        {
            var atmosphereSystem = EntitySystem.Get <AtmosphereSystem>();

            if (_robustRandom.NextFloat() <= SparkChance)
            {
                if (!_foundTile ||
                    _targetGrid == default ||
                    (!_entityManager.EntityExists(_targetGrid) ? EntityLifeStage.Deleted : _entityManager.GetComponent <MetaDataComponent>(_targetGrid).EntityLifeStage) >= EntityLifeStage.Deleted ||
                    !atmosphereSystem.IsSimulatedGrid(_entityManager.GetComponent <TransformComponent>(_targetGrid).GridID))
                {
                    return;
                }

                // Don't want it to be so obnoxious as to instantly murder anyone in the area but enough that
                // it COULD start potentially start a bigger fire.
                atmosphereSystem.HotspotExpose(_entityManager.GetComponent <TransformComponent>(_targetGrid).GridID, _targetTile, 700f, 50f, true);
                SoundSystem.Play(Filter.Pvs(_targetCoords), "/Audio/Effects/sparks4.ogg", _targetCoords);
            }
        }
예제 #22
0
        private void OnMicrowaved(EntityUid uid, IdCardComponent component, BeingMicrowavedEvent args)
        {
            if (TryComp <AccessComponent>(uid, out var access))
            {
                float randomPick = _random.NextFloat();
                // if really unlucky, burn card
                if (randomPick <= 0.15f)
                {
                    TryComp <TransformComponent>(uid, out TransformComponent? transformComponent);
                    if (transformComponent != null)
                    {
                        _popupSystem.PopupCoordinates(Loc.GetString("id-card-component-microwave-burnt", ("id", uid)),
                                                      transformComponent.Coordinates, Filter.Pvs(uid));
                        EntityManager.SpawnEntity("FoodBadRecipe",
                                                  transformComponent.Coordinates);
                    }
                    EntityManager.QueueDeleteEntity(uid);
                    return;
                }
                // If they're unlucky, brick their ID
                if (randomPick <= 0.25f)
                {
                    _popupSystem.PopupEntity(Loc.GetString("id-card-component-microwave-bricked", ("id", uid)),
                                             uid, Filter.Pvs(uid));
                    access.Tags.Clear();
                }
                else
                {
                    _popupSystem.PopupEntity(Loc.GetString("id-card-component-microwave-safe", ("id", uid)),
                                             uid, Filter.Pvs(uid));
                }

                // Give them a wonderful new access to compensate for everything
                var random = _random.Pick(_prototypeManager.EnumeratePrototypes <AccessLevelPrototype>().ToArray());
                access.Tags.Add(random.ID);
            }
        }
        public override void Initialize()
        {
            base.Initialize();

            var currentTime = _gameTiming.CurTime;
            var duration    =
                TimeSpan.FromSeconds(
                    _random.NextFloat() * (MaxPulseLifespan - MinPulseLifespan) +
                    MinPulseLifespan);

            _endTime = currentTime + duration;

            Timer.Spawn(duration,
                        () =>
            {
                if (!Owner.Deleted)
                {
                    Owner.Delete();
                }
            });

            EntitySystem.Get <AudioSystem>().PlayAtCoords("/Audio/Weapons/Guns/Gunshots/laser3.ogg", Owner.Transform.Coordinates);
            Dirty();
        }
예제 #24
0
    private void OnActivate(EntityUid uid, TelepathicArtifactComponent component, ArtifactActivatedEvent args)
    {
        // try to find victims nearby
        var victims = _lookup.GetEntitiesInRange(uid, component.Range);

        foreach (var victimUid in victims)
        {
            if (!EntityManager.HasComponent <ActorComponent>(victimUid))
            {
                continue;
            }

            // roll if msg should be usual or drastic
            var isDrastic = _random.NextFloat() <= component.DrasticMessageProb;
            var msgArr    = isDrastic ? component.DrasticMessages : component.Messages;

            // pick a random message
            var msgId = _random.Pick(msgArr);
            var msg   = Loc.GetString(msgId);

            // show it as a popup, but only for the victim
            _popupSystem.PopupEntity(msg, victimUid, Filter.Entities(victimUid));
        }
    }
 private float CalcBulletOffset()
 {
     return(_bulletDropRandom.NextFloat() * (BulletOffset * 2) - BulletOffset);
 }
 private void ResetTimeUntilPulse()
 {
     _timeUntilPulse = _robustRandom.NextFloat() * (MaxPulseDelay - MinPulseDelay) + MinPulseDelay;
 }
예제 #27
0
    private void OnComponentInit(EntityUid uid, ImmovableRodComponent component, ComponentInit args)
    {
        if (EntityManager.TryGetComponent(uid, out PhysicsComponent? phys))
        {
            phys.LinearDamping = 0f;
            phys.Friction      = 0f;
            phys.BodyStatus    = BodyStatus.InAir;

            if (!component.RandomizeVelocity)
            {
                return;
            }

            var xform = Transform(uid);
            var vel   = component.DirectionOverride.Degrees switch
            {
                0f => _random.NextVector2(component.MinSpeed, component.MaxSpeed),
                _ => xform.WorldRotation.RotateVec(component.DirectionOverride.ToVec()) * _random.NextFloat(component.MinSpeed, component.MaxSpeed)
            };

            phys.ApplyLinearImpulse(vel);
            xform.LocalRotation = (vel - xform.WorldPosition).ToWorldAngle() + MathHelper.PiOver2;
        }
    }
예제 #28
0
 private void UpdateCooldown(RechargeBasicEntityAmmoComponent component)
 {
     component.NextRechargeTime = _random.NextFloat(component.MinRechargeCooldown, component.MaxRechargeCooldown);
 }
예제 #29
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;
            }
        }