예제 #1
0
        private bool GetNextCollision(IReadOnlyList <Manifold> collisions, int counter, out Manifold collision)
        {
            // The *4 is completely arbitrary
            if (counter > collisions.Count * 4)
            {
                collision = default;
                return(false);
            }
            var indexes = new List <int>();

            for (int i = 0; i < collisions.Count; i++)
            {
                indexes.Add(i);
            }
            _random.Shuffle(indexes);
            foreach (var index in indexes)
            {
                if (collisions[index].Unresolved)
                {
                    collision = collisions[index];
                    return(true);
                }
            }

            collision = default;
            return(false);
        }
예제 #2
0
    public void SelectRandomMap()
    {
        var maps = CurrentlyEligibleMaps().ToList();

        _random.Shuffle(maps);
        _currentMap       = maps[0];
        _currentMapForced = false;
    }
예제 #3
0
    /// <summary>
    /// Finds 2-5 random, alive entities that can host diseases
    /// and gives them a randomly selected disease.
    /// They all get the same disease.
    /// </summary>
    public override void Startup()
    {
        base.Startup();
        HashSet <EntityUid>            stationsToNotify = new();
        List <DiseaseCarrierComponent> aliveList        = new();

        foreach (var(carrier, mobState) in _entityManager.EntityQuery <DiseaseCarrierComponent, MobStateComponent>())
        {
            if (!mobState.IsDead())
            {
                aliveList.Add(carrier);
            }
        }
        _random.Shuffle(aliveList);
        /// We're going to filter the above out to only alive mobs. Might change after future mobstate rework

        var toInfect = _random.Next(2, 5);

        var diseaseName = _random.Pick(NotTooSeriousDiseases);

        if (!_prototypeManager.TryIndex(diseaseName, out DiseasePrototype? disease))
        {
            return;
        }

        var diseaseSystem = EntitySystem.Get <DiseaseSystem>();
        var entSysMgr     = IoCManager.Resolve <IEntitySystemManager>();
        var stationSystem = entSysMgr.GetEntitySystem <StationSystem>();
        var chatSystem    = entSysMgr.GetEntitySystem <ChatSystem>();

        // Now we give it to people in the list of living disease carriers earlier
        foreach (var target in aliveList)
        {
            if (toInfect-- == 0)
            {
                break;
            }

            diseaseSystem.TryAddDisease(target.Owner, disease, target);

            var station = stationSystem.GetOwningStation(target.Owner);
            if (station == null)
            {
                continue;
            }
            stationsToNotify.Add((EntityUid)station);
        }

        if (!AnnounceEvent)
        {
            return;
        }
        foreach (var station in stationsToNotify)
        {
            chatSystem.DispatchStationAnnouncement(station, Loc.GetString("station-event-disease-outbreak-announcement"),
                                                   playDefaultSound: false, colorOverride: Color.YellowGreen);
        }
    }
예제 #4
0
    private void OnSpawnPlayer(PlayerSpawningEvent args)
    {
        // TODO: Cache all this if it ends up important.
        var points = EntityQuery <SpawnPointComponent>().ToList();

        _random.Shuffle(points);
        foreach (var spawnPoint in points)
        {
            var xform = Transform(spawnPoint.Owner);
            if (args.Station != null && _stationSystem.GetOwningStation(spawnPoint.Owner, xform) != args.Station)
            {
                continue;
            }

            if (_gameTicker.RunLevel == GameRunLevel.InRound && spawnPoint.SpawnType == SpawnPointType.LateJoin)
            {
                args.SpawnResult = _stationSpawning.SpawnPlayerMob(
                    xform.Coordinates,
                    args.Job,
                    args.HumanoidCharacterProfile,
                    args.Station);

                return;
            }
            else if (_gameTicker.RunLevel != GameRunLevel.InRound && spawnPoint.SpawnType == SpawnPointType.Job && (args.Job == null || spawnPoint.Job?.ID == args.Job.Prototype.ID))
            {
                args.SpawnResult = _stationSpawning.SpawnPlayerMob(
                    xform.Coordinates,
                    args.Job,
                    args.HumanoidCharacterProfile,
                    args.Station);

                return;
            }
        }

        // Ok we've still not returned, but we need to put them /somewhere/.
        // TODO: Refactor gameticker spawning code so we don't have to do this!
        foreach (var spawnPoint in points)
        {
            var xform = Transform(spawnPoint.Owner);
            args.SpawnResult = _stationSpawning.SpawnPlayerMob(
                xform.Coordinates,
                args.Job,
                args.HumanoidCharacterProfile,
                args.Station);

            return;
        }

        Logger.ErrorS("spawning", "No spawn points were available!");
    }
예제 #5
0
        /// <summary>
        /// Finds 1-3 random, dead entities accross the station
        /// and turns them into zombies.
        /// </summary>
        public override void Startup()
        {
            base.Startup();
            HashSet <EntityUid>      stationsToNotify = new();
            List <MobStateComponent> deadList         = new();

            foreach (var mobState in _entityManager.EntityQuery <MobStateComponent>())
            {
                if (mobState.IsDead() || mobState.IsCritical())
                {
                    deadList.Add(mobState);
                }
            }
            _random.Shuffle(deadList);

            var toInfect = _random.Next(1, 3);

            var zombifysys = _entityManager.EntitySysManager.GetEntitySystem <ZombifyOnDeathSystem>();

            // Now we give it to people in the list of dead entities earlier.
            var entSysMgr     = IoCManager.Resolve <IEntitySystemManager>();
            var stationSystem = entSysMgr.GetEntitySystem <StationSystem>();
            var chatSystem    = entSysMgr.GetEntitySystem <ChatSystem>();

            foreach (var target in deadList)
            {
                if (toInfect-- == 0)
                {
                    break;
                }

                zombifysys.ZombifyEntity(target.Owner);

                var station = stationSystem.GetOwningStation(target.Owner);
                if (station == null)
                {
                    continue;
                }
                stationsToNotify.Add((EntityUid)station);
            }

            if (!AnnounceEvent)
            {
                return;
            }
            foreach (var station in stationsToNotify)
            {
                chatSystem.DispatchStationAnnouncement((EntityUid)station, Loc.GetString("station-event-zombie-outbreak-announcement"),
                                                       playDefaultSound: false, colorOverride: Color.DarkMagenta);
            }
        }
예제 #6
0
        public ObjectivePrototype?GetRandomObjective(Mind mind)
        {
            var objectives = GetAllPossibleObjectives(mind).ToList();

            _random.Shuffle(objectives);

            //to prevent endless loops
            foreach (var objective in objectives)
            {
                if (!_random.Prob(objective.Probability))
                {
                    continue;
                }
                return(objective);
            }

            return(null);
        }
예제 #7
0
    public override void Startup()
    {
        base.Startup();

        var targetList = _entityManager.EntityQuery <SentienceTargetComponent>().ToList();

        _random.Shuffle(targetList);

        var toMakeSentient = _random.Next(2, 5);
        var groups         = new HashSet <string>();

        foreach (var target in targetList)
        {
            if (toMakeSentient-- == 0)
            {
                break;
            }

            MakeSentientCommand.MakeSentient(target.Owner, _entityManager);
            _entityManager.RemoveComponent <SentienceTargetComponent>(target.Owner);
            var comp = _entityManager.AddComponent <GhostTakeoverAvailableComponent>(target.Owner);
            comp.RoleName        = _entityManager.GetComponent <MetaDataComponent>(target.Owner).EntityName;
            comp.RoleDescription = Loc.GetString("station-event-random-sentience-role-description", ("name", comp.RoleName));
            groups.Add(target.FlavorKind);
        }

        if (groups.Count == 0)
        {
            return;
        }

        var groupList = groups.ToList();
        var kind1     = groupList.Count > 0 ? groupList[0] : "???";
        var kind2     = groupList.Count > 1 ? groupList[1] : "???";
        var kind3     = groupList.Count > 2 ? groupList[2] : "???";

        _chatManager.DispatchStationAnnouncement(
            Loc.GetString("station-event-random-sentience-announcement",
                          ("kind1", kind1), ("kind2", kind2), ("kind3", kind3), ("amount", groupList.Count),
                          ("data", Loc.GetString($"random-sentience-event-data-{_random.Next(1, 6)}")),
                          ("strength", Loc.GetString($"random-sentience-event-strength-{_random.Next(1, 8)}")))
            );
    }
예제 #8
0
    public override void Startup()
    {
        base.Startup();

        var apcSys    = EntitySystem.Get <ApcSystem>();
        var allApcs   = _entityManager.EntityQuery <ApcComponent>().ToList();
        var toDisable = Math.Min(_random.Next(3, 7), allApcs.Count);

        if (toDisable == 0)
        {
            return;
        }

        _random.Shuffle(allApcs);

        for (var i = 0; i < toDisable; i++)
        {
            apcSys.ApcToggleBreaker(allApcs[i].Owner, allApcs[i]);
        }
    }
예제 #9
0
    public override void Startup()
    {
        base.Startup();

        var spawnLocations = _entityManager.EntityQuery <VentCritterSpawnLocationComponent, TransformComponent>().ToList();

        _random.Shuffle(spawnLocations);

        var spawnAmount = _random.Next(7, 15); // A small colony of critters.

        for (int i = 0; i < spawnAmount && i < spawnLocations.Count - 1; i++)
        {
            var spawnChoice = _random.Pick(SpawnedPrototypeChoices);
            if (_random.Prob(0.01f) || i == 0) //small chance for multiple, but always at least 1
            {
                spawnChoice = "MobRatKing";
            }

            _entityManager.SpawnEntity(spawnChoice, spawnLocations[i].Item2.Coordinates);
        }
    }
예제 #10
0
    public override void Startup()
    {
        base.Startup();
        var spawnChoice    = _random.Pick(SpawnedPrototypeChoices);
        var spawnLocations = _entityManager.EntityQuery <VentCritterSpawnLocationComponent>().ToList();

        _random.Shuffle(spawnLocations);

        var spawnAmount = _random.Next(4, 12); // A small colony of critters.

        foreach (var location in spawnLocations)
        {
            if (spawnAmount-- == 0)
            {
                break;
            }

            var coords = _entityManager.GetComponent <TransformComponent>(location.Owner);

            _entityManager.SpawnEntity(spawnChoice, coords.Coordinates);
        }
    }
예제 #11
0
        public ObjectivePrototype[] GetRandomObjectives(Mind mind, float maxDifficulty = 3)
        {
            var objectives = GetAllPossibleObjectives(mind);

            //to prevent endless loops
            if (objectives.Length == 0 || objectives.Sum(o => o.Difficulty) == 0f)
            {
                return(objectives);
            }

            var result            = new List <ObjectivePrototype>();
            var currentDifficulty = 0f;

            _random.Shuffle(objectives);
            while (currentDifficulty < maxDifficulty)
            {
                foreach (var objective in objectives)
                {
                    if (!_random.Prob(objective.Probability))
                    {
                        continue;
                    }

                    result.Add(objective);
                    currentDifficulty += objective.Difficulty;
                    if (currentDifficulty >= maxDifficulty)
                    {
                        break;
                    }
                }
            }

            if (currentDifficulty > maxDifficulty) //will almost always happen
            {
                result.Pop();
            }

            return(result.ToArray());
        }
    /// <summary>
    /// Finds 2-5 random, alive entities that can host diseases
    /// and gives them a randomly selected disease.
    /// They all get the same disease.
    /// </summary>
    public override void Startup()
    {
        base.Startup();
        List <DiseaseCarrierComponent> aliveList = new();

        foreach (var(carrier, mobState) in _entityManager.EntityQuery <DiseaseCarrierComponent, MobStateComponent>())
        {
            if (!mobState.IsDead())
            {
                aliveList.Add(carrier);
            }
        }
        _random.Shuffle(aliveList);
        /// We're going to filter the above out to only alive mobs. Might change after future mobstate rework

        var toInfect = _random.Next(2, 5);

        var diseaseName = _random.Pick(NotTooSeriousDiseases);

        if (!_prototypeManager.TryIndex(diseaseName, out DiseasePrototype? disease))
        {
            return;
        }

        var diseaseSystem = EntitySystem.Get <DiseaseSystem>();

        /// Now we give it to people in the list of living disease carriers earlier
        foreach (var target in aliveList)
        {
            if (toInfect-- == 0)
            {
                break;
            }

            diseaseSystem.TryAddDisease(target.Owner, disease, target);
        }
        _chatManager.DispatchStationAnnouncement(Loc.GetString("station-event-disease-outbreak-announcement"));
    }
    public void Initialize()
    {
        _configurationManager.OnValueChanged(CCVars.GameMap, value =>
        {
            if (TryLookupMap(value, out var map))
            {
                _currentMap = map;
            }
            else
            {
                throw new ArgumentException($"Unknown map prototype {value} was selected!");
            }
        }, true);
        _configurationManager.OnValueChanged(CCVars.GameMapForced, value => _currentMapForced     = value, true);
        _configurationManager.OnValueChanged(CCVars.GameMapRotation, value => _mapRotationEnabled = value, true);
        _configurationManager.OnValueChanged(CCVars.GameMapMemoryDepth, value =>
        {
            _mapQueueDepth = value;
            // Drain excess.
            while (_previousMaps.Count > _mapQueueDepth)
            {
                _previousMaps.Dequeue();
            }
        }, true);

        var maps = AllVotableMaps().ToArray();

        _random.Shuffle(maps);
        foreach (var map in maps)
        {
            if (_previousMaps.Count >= _mapQueueDepth)
            {
                break;
            }
            _previousMaps.Enqueue(map.ID);
        }
    }
    public override void Startup()
    {
        base.Startup();
        HashSet <EntityUid> stationsToNotify = new();

        var targetList = _entityManager.EntityQuery <SentienceTargetComponent>().ToList();

        _random.Shuffle(targetList);

        var toMakeSentient = _random.Next(2, 5);
        var groups         = new HashSet <string>();

        foreach (var target in targetList)
        {
            if (toMakeSentient-- == 0)
            {
                break;
            }

            MakeSentientCommand.MakeSentient(target.Owner, _entityManager);
            _entityManager.RemoveComponent <SentienceTargetComponent>(target.Owner);
            var comp = _entityManager.AddComponent <GhostTakeoverAvailableComponent>(target.Owner);
            comp.RoleName        = _entityManager.GetComponent <MetaDataComponent>(target.Owner).EntityName;
            comp.RoleDescription = Loc.GetString("station-event-random-sentience-role-description", ("name", comp.RoleName));
            groups.Add(target.FlavorKind);
        }

        if (groups.Count == 0)
        {
            return;
        }

        var groupList = groups.ToList();
        var kind1     = groupList.Count > 0 ? groupList[0] : "???";
        var kind2     = groupList.Count > 1 ? groupList[1] : "???";
        var kind3     = groupList.Count > 2 ? groupList[2] : "???";

        var entSysMgr     = IoCManager.Resolve <IEntitySystemManager>();
        var stationSystem = entSysMgr.GetEntitySystem <StationSystem>();
        var chatSystem    = entSysMgr.GetEntitySystem <ChatSystem>();

        foreach (var target in targetList)
        {
            var station = stationSystem.GetOwningStation(target.Owner);
            if (station == null)
            {
                continue;
            }
            stationsToNotify.Add((EntityUid)station);
        }
        foreach (var station in stationsToNotify)
        {
            chatSystem.DispatchStationAnnouncement(
                (EntityUid)station,
                Loc.GetString("station-event-random-sentience-announcement",
                              ("kind1", kind1), ("kind2", kind2), ("kind3", kind3), ("amount", groupList.Count),
                              ("data", Loc.GetString($"random-sentience-event-data-{_random.Next(1, 6)}")),
                              ("strength", Loc.GetString($"random-sentience-event-strength-{_random.Next(1, 8)}"))),
                playDefaultSound: false,
                colorOverride: Color.Gold
                );
        }
    }
        private void TryMetabolize(EntityUid uid, MetabolizerComponent?meta = null, MechanismComponent?mech = null)
        {
            if (!Resolve(uid, ref meta))
            {
                return;
            }

            Resolve(uid, ref mech, false);

            // First step is get the solution we actually care about
            Solution? solution          = null;
            EntityUid?solutionEntityUid = null;
            EntityUid?bodyEntityUid     = mech?.Body?.Owner;

            SolutionContainerManagerComponent?manager = null;

            if (meta.SolutionOnBody)
            {
                if (mech != null)
                {
                    var body = mech.Body;

                    if (body != null)
                    {
                        if (!Resolve((body).Owner, ref manager, false))
                        {
                            return;
                        }
                        _solutionContainerSystem.TryGetSolution((body).Owner, meta.SolutionName, out solution, manager);
                        solutionEntityUid = body.Owner;
                    }
                }
            }
            else
            {
                if (!Resolve(uid, ref manager, false))
                {
                    return;
                }
                _solutionContainerSystem.TryGetSolution(uid, meta.SolutionName, out solution, manager);
                solutionEntityUid = uid;
            }

            if (solutionEntityUid == null || solution == null)
            {
                return;
            }

            // randomize the reagent list so we don't have any weird quirks
            // like alphabetical order or insertion order mattering for processing
            var list = solution.Contents.ToArray();

            _random.Shuffle(list);

            int reagents = 0;

            foreach (var reagent in list)
            {
                if (!_prototypeManager.TryIndex <ReagentPrototype>(reagent.ReagentId, out var proto))
                {
                    continue;
                }

                FixedPoint2 mostToRemove = FixedPoint2.Zero;
                if (proto.Metabolisms == null)
                {
                    if (meta.RemoveEmpty)
                    {
                        _solutionContainerSystem.TryRemoveReagent(solutionEntityUid.Value, solution, reagent.ReagentId, FixedPoint2.New(1));
                    }
                    continue;
                }

                // we're done here entirely if this is true
                if (reagents >= meta.MaxReagentsProcessable)
                {
                    return;
                }
                reagents += 1;

                // loop over all our groups and see which ones apply
                if (meta.MetabolismGroups == null)
                {
                    continue;
                }

                foreach (var group in meta.MetabolismGroups)
                {
                    if (!proto.Metabolisms.Keys.Contains(group.Id))
                    {
                        continue;
                    }

                    var entry = proto.Metabolisms[group.Id];

                    // we don't remove reagent for every group, just whichever had the biggest rate
                    if (entry.MetabolismRate > mostToRemove)
                    {
                        mostToRemove = entry.MetabolismRate;
                    }

                    mostToRemove *= group.MetabolismRateModifier;

                    mostToRemove = FixedPoint2.Clamp(mostToRemove, 0, reagent.Quantity);

                    // if it's possible for them to be dead, and they are,
                    // then we shouldn't process any effects, but should probably
                    // still remove reagents
                    if (EntityManager.TryGetComponent <MobStateComponent>(solutionEntityUid.Value, out var state))
                    {
                        if (state.IsDead())
                        {
                            continue;
                        }
                    }

                    var actualEntity = bodyEntityUid != null ? bodyEntityUid.Value : solutionEntityUid.Value;
                    var args         = new ReagentEffectArgs(actualEntity, (meta).Owner, solution, proto, mostToRemove,
                                                             EntityManager, null);

                    // do all effects, if conditions apply
                    foreach (var effect in entry.Effects)
                    {
                        if (!effect.ShouldApply(args, _random))
                        {
                            continue;
                        }

                        if (effect.ShouldLog)
                        {
                            _adminLogger.Add(LogType.ReagentEffect, effect.LogImpact,
                                             $"Metabolism effect {effect.GetType().Name:effect} of reagent {args.Reagent.LocalizedName:reagent} applied on entity {actualEntity:entity} at {Transform(actualEntity).Coordinates:coordinates}");
                        }

                        effect.Effect(args);
                    }
                }

                // remove a certain amount of reagent
                if (mostToRemove > FixedPoint2.Zero)
                {
                    _solutionContainerSystem.TryRemoveReagent(solutionEntityUid.Value, solution, reagent.ReagentId, mostToRemove);
                }
            }
        }