示例#1
0
        public static LocationType Random(string seed = "", int?zone = null)
        {
            Debug.Assert(List.Count > 0, "LocationType.list.Count == 0, you probably need to initialize LocationTypes");

            if (!string.IsNullOrWhiteSpace(seed))
            {
                Rand.SetSyncedSeed(ToolBox.StringToInt(seed));
            }

            List <LocationType> allowedLocationTypes = zone.HasValue ? List.FindAll(lt => lt.CommonnessPerZone.ContainsKey(zone.Value)) : List;

            if (allowedLocationTypes.Count == 0)
            {
                DebugConsole.ThrowError("Could not generate a random location type - no location types for the zone " + zone + " found!");
            }

            if (zone.HasValue)
            {
                return(ToolBox.SelectWeightedRandom(
                           allowedLocationTypes,
                           allowedLocationTypes.Select(a => a.CommonnessPerZone[zone.Value]).ToList(),
                           Rand.RandSync.Server));
            }
            else
            {
                return(allowedLocationTypes[Rand.Int(allowedLocationTypes.Count, Rand.RandSync.Server)]);
            }
        }
 static void CheckEventSet(EventDebugStats stats, EventSet thisSet)
 {
     if (thisSet.ChooseRandom)
     {
         List <Pair <EventPrefab, float> > unusedEvents = new List <Pair <EventPrefab, float> >(thisSet.EventPrefabs);
         for (int i = 0; i < thisSet.EventCount; i++)
         {
             var eventPrefab = ToolBox.SelectWeightedRandom(unusedEvents, unusedEvents.Select(e => e.Second).ToList(), Rand.RandSync.Unsynced);
             if (eventPrefab != null)
             {
                 AddEvent(stats, eventPrefab.First);
                 unusedEvents.Remove(eventPrefab);
             }
         }
     }
     else
     {
         foreach (var eventPrefab in thisSet.EventPrefabs)
         {
             AddEvent(stats, eventPrefab.First);
         }
     }
     foreach (var childSet in thisSet.ChildSets)
     {
         CheckEventSet(stats, childSet);
     }
 }
示例#3
0
        public override void AddExtraMissions(LevelData levelData)
        {
            extraMissions.Clear();

            var currentLocation = Map.CurrentLocation;

            if (levelData.Type == LevelData.LevelType.Outpost)
            {
                //if there's an available mission that takes place in the outpost, select it
                var availableMissionsInLocation = currentLocation.AvailableMissions.Where(m => m.Locations[0] == currentLocation && m.Locations[1] == currentLocation);
                if (availableMissionsInLocation.Any())
                {
                    currentLocation.SelectedMission = availableMissionsInLocation.FirstOrDefault();
                }
                else
                {
                    currentLocation.SelectedMission = null;
                }
            }
            else
            {
                //if we had selected a mission that takes place in the outpost, deselect it when leaving the outpost
                if (currentLocation.SelectedMission?.Locations[0] == currentLocation &&
                    currentLocation.SelectedMission?.Locations[1] == currentLocation)
                {
                    currentLocation.SelectedMission = null;
                }

                if (levelData.HasBeaconStation && !levelData.IsBeaconActive)
                {
                    var beaconMissionPrefabs = MissionPrefab.List.FindAll(m => m.Tags.Any(t => t.Equals("beaconnoreward", StringComparison.OrdinalIgnoreCase)));
                    if (beaconMissionPrefabs.Any())
                    {
                        Random rand = new MTRandom(ToolBox.StringToInt(levelData.Seed));
                        var    beaconMissionPrefab = ToolBox.SelectWeightedRandom(beaconMissionPrefabs, beaconMissionPrefabs.Select(p => (float)p.Commonness).ToList(), rand);
                        if (!Missions.Any(m => m.Prefab.Type == beaconMissionPrefab.Type))
                        {
                            extraMissions.Add(beaconMissionPrefab.Instantiate(Map.SelectedConnection.Locations));
                        }
                    }
                }
                if (levelData.HasHuntingGrounds)
                {
                    var huntingGroundsMissionPrefabs = MissionPrefab.List.FindAll(m => m.Tags.Any(t => t.Equals("huntinggroundsnoreward", StringComparison.OrdinalIgnoreCase)));
                    if (!huntingGroundsMissionPrefabs.Any())
                    {
                        DebugConsole.AddWarning("Could not find a hunting grounds mission for the level. No mission with the tag \"huntinggroundsnoreward\" found.");
                    }
                    else
                    {
                        Random rand = new MTRandom(ToolBox.StringToInt(levelData.Seed));
                        var    huntingGroundsMissionPrefab = ToolBox.SelectWeightedRandom(huntingGroundsMissionPrefabs, huntingGroundsMissionPrefabs.Select(p => (float)p.Commonness).ToList(), rand);
                        if (!Missions.Any(m => m.Prefab.Tags.Any(t => t.Equals("huntinggrounds", StringComparison.OrdinalIgnoreCase))))
                        {
                            extraMissions.Add(huntingGroundsMissionPrefab.Instantiate(Map.SelectedConnection.Locations));
                        }
                    }
                }
            }
        }
示例#4
0
 static void CheckEventSet(EventDebugStats stats, EventSet thisSet)
 {
     if (thisSet.ChooseRandom)
     {
         var unusedEvents = thisSet.EventPrefabs.ToList();
         for (int i = 0; i < thisSet.EventCount; i++)
         {
             var eventPrefab = ToolBox.SelectWeightedRandom(unusedEvents, unusedEvents.Select(e => e.Commonness).ToList(), Rand.RandSync.Unsynced);
             if (eventPrefab.Prefabs.Any(p => p != null))
             {
                 AddEvents(stats, eventPrefab.Prefabs);
                 unusedEvents.Remove(eventPrefab);
             }
         }
     }
     else
     {
         foreach (var eventPrefab in thisSet.EventPrefabs)
         {
             AddEvents(stats, eventPrefab.Prefabs);
         }
     }
     foreach (var childSet in thisSet.ChildSets)
     {
         CheckEventSet(stats, childSet);
     }
 }
 public static CaveGenerationParams GetRandom(LevelGenerationParams generationParams, bool abyss, Rand.RandSync rand)
 {
     if (CaveParams.All(p => p.GetCommonness(generationParams, abyss) <= 0.0f))
     {
         return(CaveParams.First());
     }
     return(ToolBox.SelectWeightedRandom(CaveParams, CaveParams.Select(p => p.GetCommonness(generationParams, abyss)).ToList(), rand));
 }
示例#6
0
        public void GiveItems(Character character, Submarine submarine)
        {
            var spawnItems = ToolBox.SelectWeightedRandom(ItemSets.Keys.ToList(), ItemSets.Values.ToList(), Rand.RandSync.Unsynced);

            foreach (XElement itemElement in spawnItems.GetChildElements("item"))
            {
                InitializeItems(character, itemElement, submarine);
            }
        }
 private LevelObjectPrefab GetRandomPrefab(CaveGenerationParams caveParams, IList <LevelObjectPrefab> availablePrefabs)
 {
     if (availablePrefabs.Sum(p => p.GetCommonness(caveParams)) <= 0.0f)
     {
         return(null);
     }
     return(ToolBox.SelectWeightedRandom(
                availablePrefabs,
                availablePrefabs.Select(p => p.GetCommonness(caveParams)).ToList(), Rand.RandSync.Server));
 }
示例#8
0
        public static TraitorMissionPrefab RandomPrefab()
        {
            var selected = ToolBox.SelectWeightedRandom(List, List.Select(mission => Math.Max(mission.SelectedWeight, 0.1f)).ToList(), TraitorManager.Random);

            //the weight of the missions that didn't get selected keeps growing the make them more likely to get picked
            foreach (var mission in List)
            {
                mission.SelectedWeight += 10;
            }
            selected.SelectedWeight = 0.0f;
            return(selected.Prefab);
        }
        private SpawnPosition FindObjectPosition(List <SpawnPosition> availableSpawnPositions, Level level, LevelObjectPrefab prefab)
        {
            if (prefab.SpawnPos == LevelObjectPrefab.SpawnPosType.None)
            {
                return(null);
            }

            var suitableSpawnPositions = availableSpawnPositions.Where(sp =>
                                                                       prefab.SpawnPos.HasFlag(sp.SpawnPosType) && sp.Length >= prefab.MinSurfaceWidth && prefab.Alignment.HasFlag(sp.Alignment)).ToList();

            return(ToolBox.SelectWeightedRandom(suitableSpawnPositions, suitableSpawnPositions.Select(sp => sp.GetSpawnProbability(prefab)).ToList(), Rand.RandSync.Server));
        }
示例#10
0
        private static NPCConversation GetRandomConversation(List <NPCConversation> conversations, bool avoidPreviouslyUsed)
        {
            if (!avoidPreviouslyUsed)
            {
                return(conversations.Count == 0 ? null : conversations[Rand.Int(conversations.Count)]);
            }

            List <float> probabilities = new List <float>();

            foreach (NPCConversation conversation in conversations)
            {
                probabilities.Add(GetConversationProbability(conversation));
            }
            return(ToolBox.SelectWeightedRandom(conversations, probabilities, Rand.RandSync.Unsynced));
        }
示例#11
0
 static void CheckEventSet(EventDebugStats stats, ScriptedEventSet thisSet)
 {
     if (thisSet.ChooseRandom)
     {
         var eventPrefab = ToolBox.SelectWeightedRandom(thisSet.EventPrefabs, thisSet.EventPrefabs.Select(e => e.Commonness).ToList(), Rand.RandSync.Unsynced);
         if (eventPrefab != null)
         {
             AddEvent(stats, eventPrefab);
         }
     }
     else
     {
         foreach (var eventPrefab in thisSet.EventPrefabs)
         {
             AddEvent(stats, eventPrefab);
         }
     }
     foreach (var childSet in thisSet.ChildSets)
     {
         CheckEventSet(stats, childSet);
     }
 }
示例#12
0
        public static LocationType Random(Random rand, int?zone = null)
        {
            Debug.Assert(List.Count > 0, "LocationType.list.Count == 0, you probably need to initialize LocationTypes");

            List <LocationType> allowedLocationTypes = zone.HasValue ? List.FindAll(lt => lt.CommonnessPerZone.ContainsKey(zone.Value)) : List;

            if (allowedLocationTypes.Count == 0)
            {
                DebugConsole.ThrowError("Could not generate a random location type - no location types for the zone " + zone + " found!");
            }

            if (zone.HasValue)
            {
                return(ToolBox.SelectWeightedRandom(
                           allowedLocationTypes,
                           allowedLocationTypes.Select(a => a.CommonnessPerZone[zone.Value]).ToList(),
                           rand));
            }
            else
            {
                return(allowedLocationTypes[rand.Next() % allowedLocationTypes.Count]);
            }
        }
示例#13
0
        private Hull FindRandomHull()
        {
            var  idCard          = character.Inventory.FindItemByIdentifier("idcard");
            Hull targetHull      = null;
            bool isCurrentHullOK = !HumanAIController.UnsafeHulls.Contains(character.CurrentHull) && !IsForbidden(character.CurrentHull);

            //random chance of navigating back to the room where the character spawned
            if (Rand.Int(5) == 1 && idCard != null)
            {
                foreach (WayPoint wp in WayPoint.WayPointList)
                {
                    if (wp.SpawnType != SpawnType.Human || wp.CurrentHull == null)
                    {
                        continue;
                    }

                    foreach (string tag in wp.IdCardTags)
                    {
                        if (idCard.HasTag(tag))
                        {
                            targetHull = wp.CurrentHull;
                        }
                    }
                }
            }
            if (targetHull == null)
            {
                targetHulls.Clear();
                hullWeights.Clear();
                foreach (var hull in Hull.hullList)
                {
                    if (HumanAIController.UnsafeHulls.Contains(hull))
                    {
                        continue;
                    }
                    if (hull.Submarine == null)
                    {
                        continue;
                    }
                    if (hull.Submarine.TeamID != character.TeamID)
                    {
                        continue;
                    }
                    // If the character is inside, only take connected hulls into account.
                    if (character.Submarine != null && !character.Submarine.IsEntityFoundOnThisSub(hull, true))
                    {
                        continue;
                    }
                    if (IsForbidden(hull))
                    {
                        continue;
                    }
                    // Ignore hulls that are too low to stand inside
                    if (character.AnimController is HumanoidAnimController animController)
                    {
                        if (hull.CeilingHeight < ConvertUnits.ToDisplayUnits(animController.HeadPosition.Value))
                        {
                            continue;
                        }
                    }
                    if (isCurrentHullOK)
                    {
                        // Check that there is no unsafe or forbidden hulls on the way to the target
                        // Only do this when the current hull is ok, because otherwise the would block all paths from the current hull to the target hull.
                        var path = PathSteering.PathFinder.FindPath(character.SimPosition, hull.SimPosition);
                        if (path.Unreachable)
                        {
                            continue;
                        }
                        if (path.Nodes.Any(n => HumanAIController.UnsafeHulls.Contains(n.CurrentHull) || IsForbidden(n.CurrentHull)))
                        {
                            continue;
                        }
                    }

                    // If we want to do a steering check, we should do it here, before setting the path
                    //if (path.Cost > 1000.0f) { continue; }

                    if (!targetHulls.Contains(hull))
                    {
                        targetHulls.Add(hull);
                        hullWeights.Add(hull.Volume);
                    }
                }
                return(ToolBox.SelectWeightedRandom(targetHulls, hullWeights, Rand.RandSync.Unsynced));
            }
            return(targetHull);
        }
 private LevelObjectPrefab GetRandomPrefab(string levelType, IList <LevelObjectPrefab> availablePrefabs)
 {
     return(ToolBox.SelectWeightedRandom(
                availablePrefabs,
                availablePrefabs.Select(p => p.GetCommonness(levelType)).ToList(), Rand.RandSync.Server));
 }
        public void PlaceObjects(Level level, int amount)
        {
            objectGrid = new List <LevelObject> [
                level.Size.X / GridSize,
                (level.Size.Y - level.BottomPos) / GridSize];

            List <SpawnPosition> availableSpawnPositions = new List <SpawnPosition>();
            var levelCells = level.GetAllCells();

            availableSpawnPositions.AddRange(GetAvailableSpawnPositions(levelCells, LevelObjectPrefab.SpawnPosType.Wall));
            availableSpawnPositions.AddRange(GetAvailableSpawnPositions(level.SeaFloor.Cells, LevelObjectPrefab.SpawnPosType.SeaFloor));

            foreach (RuinGeneration.Ruin ruin in level.Ruins)
            {
                foreach (var ruinShape in ruin.RuinShapes)
                {
                    foreach (var wall in ruinShape.Walls)
                    {
                        availableSpawnPositions.Add(new SpawnPosition(
                                                        new GraphEdge(wall.A, wall.B),
                                                        (wall.A + wall.B) / 2.0f - ruinShape.Center,
                                                        LevelObjectPrefab.SpawnPosType.RuinWall,
                                                        ruinShape.GetLineAlignment(wall)));
                    }
                }
            }

            foreach (var posOfInterest in level.PositionsOfInterest)
            {
                if (posOfInterest.PositionType != Level.PositionType.MainPath)
                {
                    continue;
                }

                availableSpawnPositions.Add(new SpawnPosition(
                                                new GraphEdge(posOfInterest.Position.ToVector2(), posOfInterest.Position.ToVector2() + Vector2.UnitX),
                                                Vector2.UnitY,
                                                LevelObjectPrefab.SpawnPosType.MainPath,
                                                Alignment.Top));
            }

            availableSpawnPositions.Add(new SpawnPosition(
                                            new GraphEdge(level.StartPosition - Vector2.UnitX, level.StartPosition + Vector2.UnitX),
                                            -Vector2.UnitY, LevelObjectPrefab.SpawnPosType.LevelStart, Alignment.Top));
            availableSpawnPositions.Add(new SpawnPosition(
                                            new GraphEdge(level.EndPosition - Vector2.UnitX, level.EndPosition + Vector2.UnitX),
                                            -Vector2.UnitY, LevelObjectPrefab.SpawnPosType.LevelEnd, Alignment.Top));

            var availablePrefabs = new List <LevelObjectPrefab>(LevelObjectPrefab.List);

            objects = new List <LevelObject>();

            Dictionary <LevelObjectPrefab, List <SpawnPosition> > suitableSpawnPositions = new Dictionary <LevelObjectPrefab, List <SpawnPosition> >();
            Dictionary <LevelObjectPrefab, List <float> >         spawnPositionWeights   = new Dictionary <LevelObjectPrefab, List <float> >();

            for (int i = 0; i < amount; i++)
            {
                //get a random prefab and find a place to spawn it
                LevelObjectPrefab prefab = GetRandomPrefab(level.GenerationParams.Identifier, availablePrefabs);
                if (prefab == null)
                {
                    continue;
                }
                if (!suitableSpawnPositions.ContainsKey(prefab))
                {
                    suitableSpawnPositions.Add(prefab, availableSpawnPositions.Where(sp =>
                                                                                     prefab.SpawnPos.HasFlag(sp.SpawnPosType) && (sp.Length >= prefab.MinSurfaceWidth && prefab.Alignment.HasFlag(sp.Alignment) || sp.SpawnPosType == LevelObjectPrefab.SpawnPosType.LevelEnd || sp.SpawnPosType == LevelObjectPrefab.SpawnPosType.LevelStart)).ToList());
                    spawnPositionWeights.Add(prefab,
                                             suitableSpawnPositions[prefab].Select(sp => sp.GetSpawnProbability(prefab)).ToList());
                }

                SpawnPosition spawnPosition = ToolBox.SelectWeightedRandom(suitableSpawnPositions[prefab], spawnPositionWeights[prefab], Rand.RandSync.Server);
                if (spawnPosition == null && prefab.SpawnPos != LevelObjectPrefab.SpawnPosType.None)
                {
                    continue;
                }

                float rotation = 0.0f;
                if (prefab.AlignWithSurface && spawnPosition != null)
                {
                    rotation = MathUtils.VectorToAngle(new Vector2(spawnPosition.Normal.Y, spawnPosition.Normal.X));
                }
                rotation += Rand.Range(prefab.RandomRotationRad.X, prefab.RandomRotationRad.Y, Rand.RandSync.Server);

                Vector2 position = Vector2.Zero;
                Vector2 edgeDir  = Vector2.UnitX;
                if (spawnPosition == null)
                {
                    position = new Vector2(
                        Rand.Range(0.0f, level.Size.X, Rand.RandSync.Server),
                        Rand.Range(0.0f, level.Size.Y, Rand.RandSync.Server));
                }
                else
                {
                    edgeDir  = (spawnPosition.GraphEdge.Point1 - spawnPosition.GraphEdge.Point2) / spawnPosition.Length;
                    position = spawnPosition.GraphEdge.Point2 + edgeDir * Rand.Range(prefab.MinSurfaceWidth / 2.0f, spawnPosition.Length - prefab.MinSurfaceWidth / 2.0f, Rand.RandSync.Server);
                }

                var newObject = new LevelObject(prefab,
                                                new Vector3(position, Rand.Range(prefab.DepthRange.X, prefab.DepthRange.Y, Rand.RandSync.Server)), Rand.Range(prefab.MinSize, prefab.MaxSize, Rand.RandSync.Server), rotation);
                AddObject(newObject, level);
                if (prefab.MaxCount < amount)
                {
                    if (objects.Count(o => o.Prefab == prefab) >= prefab.MaxCount)
                    {
                        availablePrefabs.Remove(prefab);
                    }
                }

                foreach (LevelObjectPrefab.ChildObject child in prefab.ChildObjects)
                {
                    int childCount = Rand.Range(child.MinCount, child.MaxCount, Rand.RandSync.Server);
                    for (int j = 0; j < childCount; j++)
                    {
                        var matchingPrefabs = LevelObjectPrefab.List.Where(p => child.AllowedNames.Contains(p.Name));
                        int prefabCount     = matchingPrefabs.Count();
                        var childPrefab     = prefabCount == 0 ? null : matchingPrefabs.ElementAt(Rand.Range(0, prefabCount, Rand.RandSync.Server));
                        if (childPrefab == null)
                        {
                            continue;
                        }

                        Vector2 childPos = position + edgeDir * Rand.Range(-0.5f, 0.5f, Rand.RandSync.Server) * prefab.MinSurfaceWidth;

                        var childObject = new LevelObject(childPrefab,
                                                          new Vector3(childPos, Rand.Range(childPrefab.DepthRange.X, childPrefab.DepthRange.Y, Rand.RandSync.Server)),
                                                          Rand.Range(childPrefab.MinSize, childPrefab.MaxSize, Rand.RandSync.Server),
                                                          rotation + Rand.Range(childPrefab.RandomRotationRad.X, childPrefab.RandomRotationRad.Y, Rand.RandSync.Server));

                        AddObject(childObject, level);
                    }
                }
            }
        }
示例#16
0
        private WreckAI(Submarine wreck)
        {
            Wreck  = wreck;
            Config = WreckAIConfig.GetRandom();
            if (Config == null)
            {
                DebugConsole.ThrowError("WreckAI: No wreck AI config found!");
                return;
            }
            var thalamusPrefabs = ItemPrefab.Prefabs.Where(p => IsThalamus(p));
            var brainPrefab     = thalamusPrefabs.GetRandom(i => i.Tags.Contains(Config.Brain), Rand.RandSync.Server);

            if (brainPrefab == null)
            {
                DebugConsole.ThrowError($"WreckAI: Could not find any brain prefab with the tag {Config.Brain}! Cannot continue. Failed to create wreck AI.");
                return;
            }
            allItems      = Wreck.GetItems(false);
            thalamusItems = allItems.FindAll(i => IsThalamus(i.prefab));
            hulls.AddRange(Wreck.GetHulls(false));
            var potentialBrainHulls = new List <(Hull hull, float weight)>();

            brain = new Item(brainPrefab, Vector2.Zero, Wreck);
            thalamusItems.Add(brain);
            Point minSize = brain.Rect.Size.Multiply(brain.Scale);
            // Bigger hulls are allowed, but not preferred more than what's sufficent.
            Vector2 sufficentSize = new Vector2(minSize.X * 2, minSize.Y * 1.1f);
            // Shrink the horizontal axis so that the brain is not placed in the left or right side, where we often have curved walls.
            Rectangle shrinkedBounds = ToolBox.GetWorldBounds(Wreck.WorldPosition.ToPoint(), new Point(Wreck.Borders.Width - 500, Wreck.Borders.Height));

            foreach (Hull hull in hulls)
            {
                float distanceFromCenter   = Vector2.Distance(Wreck.WorldPosition, hull.WorldPosition);
                float distanceFactor       = MathHelper.Lerp(1.0f, 0.5f, MathUtils.InverseLerp(0, Math.Max(shrinkedBounds.Width, shrinkedBounds.Height) / 2, distanceFromCenter));
                float horizontalSizeFactor = MathHelper.Lerp(0.5f, 1.0f, MathUtils.InverseLerp(minSize.X, sufficentSize.X, hull.Rect.Width));
                float verticalSizeFactor   = MathHelper.Lerp(0.5f, 1.0f, MathUtils.InverseLerp(minSize.Y, sufficentSize.Y, hull.Rect.Height));
                float weight = verticalSizeFactor * horizontalSizeFactor * distanceFactor;
                if (hull.GetLinkedEntities <Hull>().Any())
                {
                    // Ignore hulls that have any linked hulls to keep the calculations simple.
                    continue;
                }
                else if (hull.ConnectedGaps.Any(g => g.Open > 0 && (!g.IsRoomToRoom || g.Position.Y < hull.Position.Y)))
                {
                    // Ignore hulls that have open gaps to outside or below the center point, because we'll want the room to be full of water and not be accessible without breaking the wall.
                    continue;
                }
                else if (thalamusItems.Any(i => i.CurrentHull == hull))
                {
                    // Don't create the brain in a room that already has thalamus items inside it.
                    continue;
                }
                else if (hull.Rect.Width < minSize.X || hull.Rect.Height < minSize.Y)
                {
                    // Don't select too small rooms.
                    continue;
                }
                if (weight > 0)
                {
                    potentialBrainHulls.Add((hull, weight));
                }
            }
            Hull brainHull = ToolBox.SelectWeightedRandom(potentialBrainHulls.Select(pbh => pbh.hull).ToList(), potentialBrainHulls.Select(pbh => pbh.weight).ToList(), Rand.RandSync.Server);
            var  thalamusStructurePrefabs = StructurePrefab.Prefabs.Where(p => IsThalamus(p));

            if (brainHull == null)
            {
                DebugConsole.AddWarning("Wreck AI: Cannot find a proper room for the brain. Using a random room.");
                brainHull = hulls.GetRandom(Rand.RandSync.Server);
            }
            if (brainHull == null)
            {
                DebugConsole.ThrowError("Wreck AI: Cannot find any room for the brain! Failed to create the Thalamus.");
                return;
            }
            brainHull.WaterVolume = brainHull.Volume;
            brain.SetTransform(brainHull.SimPosition, rotation: 0, findNewHull: false);
            brain.CurrentHull = brainHull;
            var backgroundPrefab = thalamusStructurePrefabs.GetRandom(i => i.Tags.Contains(Config.BrainRoomBackground), Rand.RandSync.Server);

            if (backgroundPrefab != null)
            {
                new Structure(brainHull.Rect, backgroundPrefab, Wreck);
            }
            var horizontalWallPrefab = thalamusStructurePrefabs.GetRandom(p => p.Tags.Contains(Config.BrainRoomHorizontalWall), Rand.RandSync.Server);

            if (horizontalWallPrefab != null)
            {
                int height        = (int)horizontalWallPrefab.Size.Y;
                int halfHeight    = height / 2;
                int quarterHeight = halfHeight / 2;
                new Structure(new Rectangle(brainHull.Rect.Left, brainHull.Rect.Top + quarterHeight, brainHull.Rect.Width, height), horizontalWallPrefab, Wreck);
                new Structure(new Rectangle(brainHull.Rect.Left, brainHull.Rect.Top - brainHull.Rect.Height + halfHeight + quarterHeight, brainHull.Rect.Width, height), horizontalWallPrefab, Wreck);
            }
            var verticalWallPrefab = thalamusStructurePrefabs.GetRandom(p => p.Tags.Contains(Config.BrainRoomVerticalWall), Rand.RandSync.Server);

            if (verticalWallPrefab != null)
            {
                int width        = (int)verticalWallPrefab.Size.X;
                int halfWidth    = width / 2;
                int quarterWidth = halfWidth / 2;
                new Structure(new Rectangle(brainHull.Rect.Left - quarterWidth, brainHull.Rect.Top, width, brainHull.Rect.Height), verticalWallPrefab, Wreck);
                new Structure(new Rectangle(brainHull.Rect.Right - halfWidth - quarterWidth, brainHull.Rect.Top, width, brainHull.Rect.Height), verticalWallPrefab, Wreck);
            }
            foreach (Item item in allItems)
            {
                if (thalamusItems.Contains(item))
                {
                    // Ensure that thalamus items are visible
                    item.HiddenInGame = false;
                }
                else
                {
                    // Load regular turrets
                    var turret = item.GetComponent <Turret>();
                    if (turret != null)
                    {
                        foreach (var linkedItem in item.GetLinkedEntities <Item>())
                        {
                            var container = linkedItem.GetComponent <ItemContainer>();
                            if (container == null)
                            {
                                continue;
                            }
                            for (int i = 0; i < container.Inventory.Capacity; i++)
                            {
                                if (container.Inventory.GetItemAt(i) != null)
                                {
                                    continue;
                                }
                                if (MapEntityPrefab.List.GetRandom(e => e is ItemPrefab ip && container.CanBeContained(ip, i) &&
                                                                   Config.ForbiddenAmmunition.None(id => id.Equals(ip.Identifier, StringComparison.OrdinalIgnoreCase)), Rand.RandSync.Server) is ItemPrefab ammoPrefab)
                                {
                                    Item ammo = new Item(ammoPrefab, container.Item.WorldPosition, Wreck);
                                    if (!container.Inventory.TryPutItem(ammo, i, allowSwapping: false, allowCombine: false, user: null, createNetworkEvent: false))
                                    {
                                        item.Remove();
                                    }
                                }
                            }
                        }
                    }
                }
            }
            foreach (var item in allItems)
            {
                var turret = item.GetComponent <Turret>();
                if (turret != null)
                {
                    turrets.Add(turret);
                }
                if (item.HasTag(Config.Spawner))
                {
                    if (!spawnOrgans.Contains(item))
                    {
                        spawnOrgans.Add(item);
                        if (item.CurrentHull != null)
                        {
                            // Try to flood the hull so that the spawner won't die.
                            item.CurrentHull.WaterVolume = item.CurrentHull.Volume;
                        }
                    }
                }
            }
            wayPoints.AddRange(Wreck.GetWaypoints(false));
            IsAlive            = true;
            thalamusStructures = GetThalamusEntities <Structure>(Wreck, Config.Entity).ToList();
        }
示例#17
0
        public void ProgressWorld()
        {
            foreach (Location location in Locations)
            {
                if (!location.Discovered)
                {
                    continue;
                }

                //find which types of locations this one can change to
                List <LocationTypeChange> allowedTypeChanges = new List <LocationTypeChange>();
                List <LocationTypeChange> readyTypeChanges   = new List <LocationTypeChange>();
                foreach (LocationTypeChange typeChange in location.Type.CanChangeTo)
                {
                    //check if there are any adjacent locations that would prevent the change
                    bool disallowedFound = false;
                    foreach (string disallowedLocationName in typeChange.DisallowedAdjacentLocations)
                    {
                        if (location.Connections.Any(c => c.OtherLocation(location).Type.Identifier.ToLowerInvariant() == disallowedLocationName.ToLowerInvariant()))
                        {
                            disallowedFound = true;
                            break;
                        }
                    }
                    if (disallowedFound)
                    {
                        continue;
                    }

                    //check that there's a required adjacent location present
                    bool requiredFound = false;
                    foreach (string requiredLocationName in typeChange.RequiredAdjacentLocations)
                    {
                        if (location.Connections.Any(c => c.OtherLocation(location).Type.Identifier.ToLowerInvariant() == requiredLocationName.ToLowerInvariant()))
                        {
                            requiredFound = true;
                            break;
                        }
                    }
                    if (!requiredFound && typeChange.RequiredAdjacentLocations.Count > 0)
                    {
                        continue;
                    }

                    allowedTypeChanges.Add(typeChange);

                    if (location.TypeChangeTimer >= typeChange.RequiredDuration)
                    {
                        readyTypeChanges.Add(typeChange);
                    }
                }

                //select a random type change
                if (Rand.Range(0.0f, 1.0f) < readyTypeChanges.Sum(t => t.Probability))
                {
                    var selectedTypeChange =
                        ToolBox.SelectWeightedRandom(readyTypeChanges, readyTypeChanges.Select(t => t.Probability).ToList(), Rand.RandSync.Unsynced);
                    if (selectedTypeChange != null)
                    {
                        string prevName = location.Name;
                        location.ChangeType(LocationType.List.Find(lt => lt.Identifier.ToLowerInvariant() == selectedTypeChange.ChangeToType.ToLowerInvariant()));
                        ChangeLocationType(location, prevName, selectedTypeChange);
                        location.TypeChangeTimer = -1;
                        break;
                    }
                }

                if (allowedTypeChanges.Count > 0)
                {
                    location.TypeChangeTimer++;
                }
                else
                {
                    location.TypeChangeTimer = 0;
                }
            }
        }
示例#18
0
        protected override void Act(float deltaTime)
        {
            if (PathSteering == null)
            {
                return;
            }

            //don't keep dragging others when idling
            if (character.SelectedCharacter != null)
            {
                character.DeselectCharacter();
            }
            if (!character.IsClimbing)
            {
                character.SelectedConstruction = null;
            }

            bool currentHullForbidden = IsForbidden(character.CurrentHull);

            if (!currentHullForbidden && !character.AnimController.InWater && !character.IsClimbing && HumanAIController.ObjectiveManager.WaitTimer > 0)
            {
                SteeringManager.Reset();
                return;
            }

            bool currentTargetIsInvalid = currentTarget == null || IsForbidden(currentTarget) ||
                                          (PathSteering.CurrentPath != null && PathSteering.CurrentPath.Nodes.Any(n => HumanAIController.UnsafeHulls.Contains(n.CurrentHull)));

            if (currentTargetIsInvalid || (currentTarget == null && currentHullForbidden))
            {
                newTargetTimer  = 0;
                standStillTimer = 0;
            }
            else if (character.IsClimbing)
            {
                if (currentTarget == null)
                {
                    newTargetTimer = 0;
                }
                else
                {
                    // Don't allow new targets when climbing.
                    newTargetTimer = Math.Max(newTargetIntervalMin, newTargetTimer);
                }
            }
            else if (character.AnimController.InWater)
            {
                if (currentTarget == null)
                {
                    newTargetTimer = 0;
                }
            }
            if (newTargetTimer <= 0.0f)
            {
                if (!searchingNewHull)
                {
                    //find all available hulls first
                    FindTargetHulls();
                    searchingNewHull = true;
                    return;
                }
                else if (targetHulls.Count > 0)
                {
                    //choose a random available hull
                    var randomHull = ToolBox.SelectWeightedRandom(targetHulls, hullWeights, Rand.RandSync.Unsynced);

                    bool isCurrentHullOK = !HumanAIController.UnsafeHulls.Contains(character.CurrentHull) && !IsForbidden(character.CurrentHull);
                    if (isCurrentHullOK)
                    {
                        // Check that there is no unsafe or forbidden hulls on the way to the target
                        // Only do this when the current hull is ok, because otherwise the would block all paths from the current hull to the target hull.
                        var path = PathSteering.PathFinder.FindPath(character.SimPosition, randomHull.SimPosition);
                        if (path.Unreachable ||
                            path.Nodes.Any(n => HumanAIController.UnsafeHulls.Contains(n.CurrentHull) || IsForbidden(n.CurrentHull)))
                        {
                            //can't go to this room, remove it from the list and try another room next frame
                            int index = targetHulls.IndexOf(randomHull);
                            targetHulls.RemoveAt(index);
                            hullWeights.RemoveAt(index);
                            PathSteering.Reset();
                            return;
                        }
                    }
                    currentTarget    = randomHull;
                    searchingNewHull = false;
                }

                if (currentTarget != null)
                {
                    character.AIController.SelectTarget(currentTarget.AiTarget);
                    string errorMsg = null;
#if DEBUG
                    bool isRoomNameFound = currentTarget.RoomName != null;
                    errorMsg = "(Character " + character.Name + " idling, target " + (isRoomNameFound ? currentTarget.RoomName : currentTarget.ToString()) + ")";
#endif
                    var path = PathSteering.PathFinder.FindPath(character.SimPosition, currentTarget.SimPosition, errorMsg);
                    PathSteering.SetPath(path);
                }

                newTargetTimer = currentTarget != null && character.AnimController.InWater ? newTargetIntervalMin : Rand.Range(newTargetIntervalMin, newTargetIntervalMax);
            }

            newTargetTimer -= deltaTime;

            //wander randomly
            // - if reached the end of the path
            // - if the target is unreachable
            // - if the path requires going outside
            if (!character.IsClimbing)
            {
                if (SteeringManager != PathSteering || (PathSteering.CurrentPath != null &&
                                                        (PathSteering.CurrentPath.NextNode == null || PathSteering.CurrentPath.Unreachable || PathSteering.CurrentPath.HasOutdoorsNodes)))
                {
                    if (!character.AnimController.InWater)
                    {
                        standStillTimer -= deltaTime;
                        if (standStillTimer > 0.0f)
                        {
                            walkDuration = Rand.Range(walkDurationMin, walkDurationMax);
                            PathSteering.Reset();
                            return;
                        }
                        if (standStillTimer < -walkDuration)
                        {
                            standStillTimer = Rand.Range(standStillMin, standStillMax);
                        }
                    }
                    Wander(deltaTime);
                    return;
                }
            }

            if (currentTarget != null)
            {
                character.AIController.SteeringManager.SteeringSeek(currentTarget.SimPosition);
            }
        }
        public void PlaceObjects(Level level, int amount)
        {
            objectGrid = new List <LevelObject> [
                level.Size.X / GridSize,
                (level.Size.Y - level.BottomPos) / GridSize];

            List <SpawnPosition> availableSpawnPositions = new List <SpawnPosition>();
            var levelCells = level.GetAllCells();

            availableSpawnPositions.AddRange(GetAvailableSpawnPositions(levelCells, LevelObjectPrefab.SpawnPosType.Wall));
            availableSpawnPositions.AddRange(GetAvailableSpawnPositions(level.SeaFloor.Cells, LevelObjectPrefab.SpawnPosType.SeaFloor));

            foreach (Structure structure in Structure.WallList)
            {
                if (!structure.HasBody || structure.HiddenInGame)
                {
                    continue;
                }
                if (level.Ruins.Any(r => r.Submarine == structure.Submarine))
                {
                    if (structure.IsHorizontal)
                    {
                        bool topHull    = Hull.FindHull(structure.WorldPosition + Vector2.UnitY * 64) != null;
                        bool bottomHull = Hull.FindHull(structure.WorldPosition - Vector2.UnitY * 64) != null;
                        if (topHull && bottomHull)
                        {
                            continue;
                        }

                        availableSpawnPositions.Add(new SpawnPosition(
                                                        new GraphEdge(new Vector2(structure.WorldRect.X, structure.WorldPosition.Y), new Vector2(structure.WorldRect.Right, structure.WorldPosition.Y)),
                                                        bottomHull ? Vector2.UnitY : -Vector2.UnitY,
                                                        LevelObjectPrefab.SpawnPosType.RuinWall,
                                                        bottomHull ? Alignment.Bottom : Alignment.Top));
                    }
                    else
                    {
                        bool rightHull = Hull.FindHull(structure.WorldPosition + Vector2.UnitX * 64) != null;
                        bool leftHull  = Hull.FindHull(structure.WorldPosition - Vector2.UnitX * 64) != null;
                        if (rightHull && leftHull)
                        {
                            continue;
                        }

                        availableSpawnPositions.Add(new SpawnPosition(
                                                        new GraphEdge(new Vector2(structure.WorldPosition.X, structure.WorldRect.Y), new Vector2(structure.WorldPosition.X, structure.WorldRect.Y - structure.WorldRect.Height)),
                                                        leftHull ? Vector2.UnitX : -Vector2.UnitX,
                                                        LevelObjectPrefab.SpawnPosType.RuinWall,
                                                        leftHull ? Alignment.Left : Alignment.Right));
                    }
                }
            }

            foreach (var posOfInterest in level.PositionsOfInterest)
            {
                if (posOfInterest.PositionType != Level.PositionType.MainPath && posOfInterest.PositionType != Level.PositionType.SidePath)
                {
                    continue;
                }

                availableSpawnPositions.Add(new SpawnPosition(
                                                new GraphEdge(posOfInterest.Position.ToVector2(), posOfInterest.Position.ToVector2() + Vector2.UnitX),
                                                Vector2.UnitY,
                                                LevelObjectPrefab.SpawnPosType.MainPath,
                                                Alignment.Top));
            }

            availableSpawnPositions.Add(new SpawnPosition(
                                            new GraphEdge(level.StartPosition - Vector2.UnitX, level.StartPosition + Vector2.UnitX),
                                            -Vector2.UnitY, LevelObjectPrefab.SpawnPosType.LevelStart, Alignment.Top));
            availableSpawnPositions.Add(new SpawnPosition(
                                            new GraphEdge(level.EndPosition - Vector2.UnitX, level.EndPosition + Vector2.UnitX),
                                            -Vector2.UnitY, LevelObjectPrefab.SpawnPosType.LevelEnd, Alignment.Top));

            var availablePrefabs = new List <LevelObjectPrefab>(LevelObjectPrefab.List);

            objects           = new List <LevelObject>();
            updateableObjects = new List <LevelObject>();

            Dictionary <LevelObjectPrefab, List <SpawnPosition> > suitableSpawnPositions = new Dictionary <LevelObjectPrefab, List <SpawnPosition> >();
            Dictionary <LevelObjectPrefab, List <float> >         spawnPositionWeights   = new Dictionary <LevelObjectPrefab, List <float> >();

            for (int i = 0; i < amount; i++)
            {
                //get a random prefab and find a place to spawn it
                LevelObjectPrefab prefab = GetRandomPrefab(level.GenerationParams, availablePrefabs);
                if (prefab == null)
                {
                    continue;
                }
                if (!suitableSpawnPositions.ContainsKey(prefab))
                {
                    float minDistance = level.Size.X * 0.2f;

                    suitableSpawnPositions.Add(prefab,
                                               availableSpawnPositions.Where(sp =>
                                                                             sp.SpawnPosTypes.Any(type => prefab.SpawnPos.HasFlag(type)) &&
                                                                             sp.Length >= prefab.MinSurfaceWidth &&
                                                                             (prefab.AllowAtStart || !level.IsCloseToStart(sp.GraphEdge.Center, minDistance)) &&
                                                                             (prefab.AllowAtEnd || !level.IsCloseToEnd(sp.GraphEdge.Center, minDistance)) &&
                                                                             (sp.Alignment == Alignment.Any || prefab.Alignment.HasFlag(sp.Alignment))).ToList());

                    spawnPositionWeights.Add(prefab,
                                             suitableSpawnPositions[prefab].Select(sp => sp.GetSpawnProbability(prefab)).ToList());
                }

                SpawnPosition spawnPosition = ToolBox.SelectWeightedRandom(suitableSpawnPositions[prefab], spawnPositionWeights[prefab], Rand.RandSync.Server);
                if (spawnPosition == null && prefab.SpawnPos != LevelObjectPrefab.SpawnPosType.None)
                {
                    continue;
                }
                PlaceObject(prefab, spawnPosition, level);
                if (prefab.MaxCount < amount)
                {
                    if (objects.Count(o => o.Prefab == prefab) >= prefab.MaxCount)
                    {
                        availablePrefabs.Remove(prefab);
                    }
                }
            }

            foreach (Level.Cave cave in level.Caves)
            {
                availablePrefabs = new List <LevelObjectPrefab>(LevelObjectPrefab.List.FindAll(p => p.SpawnPos.HasFlag(LevelObjectPrefab.SpawnPosType.CaveWall)));
                availableSpawnPositions.Clear();
                suitableSpawnPositions.Clear();
                spawnPositionWeights.Clear();

                var caveCells = cave.Tunnels.SelectMany(t => t.Cells);
                List <VoronoiCell> caveWallCells = new List <VoronoiCell>();
                foreach (var edge in caveCells.SelectMany(c => c.Edges))
                {
                    if (!edge.NextToCave)
                    {
                        continue;
                    }
                    if (edge.Cell1?.CellType == CellType.Solid)
                    {
                        caveWallCells.Add(edge.Cell1);
                    }
                    if (edge.Cell2?.CellType == CellType.Solid)
                    {
                        caveWallCells.Add(edge.Cell2);
                    }
                }
                availableSpawnPositions.AddRange(GetAvailableSpawnPositions(caveWallCells.Distinct(), LevelObjectPrefab.SpawnPosType.CaveWall));

                for (int i = 0; i < cave.CaveGenerationParams.LevelObjectAmount; i++)
                {
                    //get a random prefab and find a place to spawn it
                    LevelObjectPrefab prefab = GetRandomPrefab(cave.CaveGenerationParams, availablePrefabs, requireCaveSpecificOverride: true);
                    if (prefab == null)
                    {
                        continue;
                    }
                    if (!suitableSpawnPositions.ContainsKey(prefab))
                    {
                        suitableSpawnPositions.Add(prefab,
                                                   availableSpawnPositions.Where(sp =>
                                                                                 sp.Length >= prefab.MinSurfaceWidth &&
                                                                                 (sp.Alignment == Alignment.Any || prefab.Alignment.HasFlag(sp.Alignment))).ToList());
                        spawnPositionWeights.Add(prefab,
                                                 suitableSpawnPositions[prefab].Select(sp => sp.GetSpawnProbability(prefab)).ToList());
                    }
                    SpawnPosition spawnPosition = ToolBox.SelectWeightedRandom(suitableSpawnPositions[prefab], spawnPositionWeights[prefab], Rand.RandSync.Server);
                    if (spawnPosition == null && prefab.SpawnPos != LevelObjectPrefab.SpawnPosType.None)
                    {
                        continue;
                    }
                    PlaceObject(prefab, spawnPosition, level, cave);
                    if (prefab.MaxCount < amount)
                    {
                        if (objects.Count(o => o.Prefab == prefab && o.ParentCave == cave) >= prefab.MaxCount)
                        {
                            availablePrefabs.Remove(prefab);
                        }
                    }
                }
            }
        }
示例#20
0
        private void CreateEvents(EventSet eventSet)
        {
            if (level == null)
            {
                return;
            }
            int applyCount = 1;

            if (eventSet.PerRuin)
            {
                applyCount = Level.Loaded.Ruins.Count();
            }
            else if (eventSet.PerWreck)
            {
                applyCount = Submarine.Loaded.Count(s => s.Info.IsWreck && (s.WreckAI == null || !s.WreckAI.IsAlive));
            }
            for (int i = 0; i < applyCount; i++)
            {
                if (eventSet.ChooseRandom)
                {
                    if (eventSet.EventPrefabs.Count > 0)
                    {
                        int seed = ToolBox.StringToInt(level.Seed);
                        foreach (var previousEvent in level.LevelData.EventHistory)
                        {
                            seed |= ToolBox.StringToInt(previousEvent.Identifier);
                        }

                        MTRandom rand = new MTRandom(seed);
                        List <Pair <EventPrefab, float> > unusedEvents = new List <Pair <EventPrefab, float> >(eventSet.EventPrefabs);
                        for (int j = 0; j < eventSet.EventCount; j++)
                        {
                            var eventPrefab = ToolBox.SelectWeightedRandom(unusedEvents, unusedEvents.Select(e => CalculateCommonness(e)).ToList(), rand);
                            if (eventPrefab != null)
                            {
                                var newEvent = eventPrefab.First.CreateInstance();
                                newEvent.Init(true);
                                DebugConsole.Log("Initialized event " + newEvent.ToString());
                                if (!selectedEvents.ContainsKey(eventSet))
                                {
                                    selectedEvents.Add(eventSet, new List <Event>());
                                }
                                selectedEvents[eventSet].Add(newEvent);
                                unusedEvents.Remove(eventPrefab);
                            }
                        }
                    }
                    if (eventSet.ChildSets.Count > 0)
                    {
                        var newEventSet = SelectRandomEvents(eventSet.ChildSets);
                        if (newEventSet != null)
                        {
                            CreateEvents(newEventSet);
                        }
                    }
                }
                else
                {
                    foreach (Pair <EventPrefab, float> eventPrefab in eventSet.EventPrefabs)
                    {
                        var newEvent = eventPrefab.First.CreateInstance();
                        newEvent.Init(true);
                        DebugConsole.Log("Initialized event " + newEvent.ToString());
                        if (!selectedEvents.ContainsKey(eventSet))
                        {
                            selectedEvents.Add(eventSet, new List <Event>());
                        }
                        selectedEvents[eventSet].Add(newEvent);
                    }

                    foreach (EventSet childEventSet in eventSet.ChildSets)
                    {
                        CreateEvents(childEventSet);
                    }
                }
            }
        }
示例#21
0
        private void ProgressLocationTypeChanges(Location location)
        {
            location.TimeSinceLastTypeChange++;

            if (location.PendingLocationTypeChange != null)
            {
                if (location.PendingLocationTypeChange.First.DetermineProbability(location) <= 0.0f)
                {
                    //remove pending type change if it's no longer allowed
                    location.PendingLocationTypeChange = null;
                }
                else
                {
                    location.PendingLocationTypeChange.Second--;
                    if (location.PendingLocationTypeChange.Second <= 0)
                    {
                        ChangeLocationType(location, location.PendingLocationTypeChange.First);
                    }
                    return;
                }
            }

            //find which types of locations this one can change to
            Dictionary <LocationTypeChange, float> allowedTypeChanges = new Dictionary <LocationTypeChange, float>();

            foreach (LocationTypeChange typeChange in location.Type.CanChangeTo)
            {
                float probability = typeChange.DetermineProbability(location);
                if (probability <= 0.0f)
                {
                    continue;
                }
                allowedTypeChanges.Add(typeChange, probability);
            }

            //select a random type change
            if (Rand.Range(0.0f, 1.0f) < allowedTypeChanges.Sum(change => change.Value))
            {
                var selectedTypeChange =
                    ToolBox.SelectWeightedRandom(
                        allowedTypeChanges.Keys.ToList(),
                        allowedTypeChanges.Values.ToList(),
                        Rand.RandSync.Unsynced);
                if (selectedTypeChange != null)
                {
                    if (selectedTypeChange.RequiredDurationRange.X > 0)
                    {
                        location.PendingLocationTypeChange = new Pair <LocationTypeChange, int>(
                            selectedTypeChange,
                            Rand.Range(selectedTypeChange.RequiredDurationRange.X, selectedTypeChange.RequiredDurationRange.Y));
                    }
                    else
                    {
                        ChangeLocationType(location, selectedTypeChange);
                    }
                    return;
                }
            }

            foreach (LocationTypeChange typeChange in location.Type.CanChangeTo)
            {
                if (typeChange.AnyWithinDistance(
                        location,
                        typeChange.RequiredProximityForProbabilityIncrease,
                        (otherLocation) => { return(typeChange.RequiredLocations.Contains(otherLocation.Type.Identifier)); }))
                {
                    if (!location.ProximityTimer.ContainsKey(typeChange))
                    {
                        location.ProximityTimer[typeChange] = 0;
                    }
                    location.ProximityTimer[typeChange] += 1;
                }
                else
                {
                    location.ProximityTimer.Remove(typeChange);
                }
            }
        }
示例#22
0
        public void StartRound(Level level)
        {
            this.level = level;

            if (isClient)
            {
                return;
            }

            pendingEventSets.Clear();
            selectedEvents.Clear();
            activeEvents.Clear();

            pathFinder      = new PathFinder(WayPoint.WayPointList, false);
            totalPathLength = 0.0f;
            if (level != null)
            {
                var steeringPath = pathFinder.FindPath(ConvertUnits.ToSimUnits(level.StartPosition), ConvertUnits.ToSimUnits(level.EndPosition));
                totalPathLength = steeringPath.TotalLength;
            }

            SelectSettings();

            int seed = 0;

            if (level != null)
            {
                seed = ToolBox.StringToInt(level.Seed);
                foreach (var previousEvent in level.LevelData.EventHistory)
                {
                    seed ^= ToolBox.StringToInt(previousEvent.Identifier);
                }
            }
            MTRandom rand = new MTRandom(seed);

            EventSet initialEventSet = SelectRandomEvents(EventSet.List, rand);
            EventSet additiveSet     = null;

            if (initialEventSet != null && initialEventSet.Additive)
            {
                additiveSet     = initialEventSet;
                initialEventSet = SelectRandomEvents(EventSet.List.FindAll(e => !e.Additive), rand);
            }
            if (initialEventSet != null)
            {
                pendingEventSets.Add(initialEventSet);
                CreateEvents(initialEventSet, rand);
            }
            if (additiveSet != null)
            {
                pendingEventSets.Add(additiveSet);
                CreateEvents(additiveSet, rand);
            }

            if (level?.LevelData?.Type == LevelData.LevelType.Outpost)
            {
                //if the outpost is connected to a locked connection, create an event to unlock it
                if (level.StartLocation?.Connections.Any(c => c.Locked && level.StartLocation.MapPosition.X < c.OtherLocation(level.StartLocation).MapPosition.X) ?? false)
                {
                    var unlockPathPrefabs         = EventSet.PrefabList.FindAll(e => e.UnlockPathEvent);
                    var unlockPathPrefabsForBiome = unlockPathPrefabs.FindAll(e =>
                                                                              string.IsNullOrEmpty(e.BiomeIdentifier) ||
                                                                              e.BiomeIdentifier.Equals(level.LevelData.Biome.Identifier, StringComparison.OrdinalIgnoreCase));

                    var unlockPathEventPrefab = unlockPathPrefabsForBiome.Any() ?
                                                ToolBox.SelectWeightedRandom(unlockPathPrefabsForBiome, unlockPathPrefabsForBiome.Select(b => b.Commonness).ToList(), rand) :
                                                ToolBox.SelectWeightedRandom(unlockPathPrefabs, unlockPathPrefabs.Select(b => b.Commonness).ToList(), rand);
                    if (unlockPathEventPrefab != null)
                    {
                        var newEvent = unlockPathEventPrefab.CreateInstance();
                        newEvent.Init(true);
                        ActiveEvents.Add(newEvent);
                    }
                    else
                    {
                        //if no event that unlocks the path can be found, unlock it automatically
                        level.StartLocation.Connections.ForEach(c => c.Locked = false);
                    }
                }

                level.LevelData.EventHistory.AddRange(selectedEvents.Values.SelectMany(v => v).Select(e => e.Prefab).Where(e => !level.LevelData.EventHistory.Contains(e)));
                if (level.LevelData.EventHistory.Count > MaxEventHistory)
                {
                    level.LevelData.EventHistory.RemoveRange(0, level.LevelData.EventHistory.Count - MaxEventHistory);
                }
                AddChildEvents(initialEventSet);
                void AddChildEvents(EventSet eventSet)
                {
                    if (eventSet == null)
                    {
                        return;
                    }
                    if (eventSet.OncePerOutpost)
                    {
                        foreach (EventPrefab ep in eventSet.EventPrefabs.SelectMany(e => e.Prefabs))
                        {
                            if (!level.LevelData.NonRepeatableEvents.Contains(ep))
                            {
                                level.LevelData.NonRepeatableEvents.Add(ep);
                            }
                        }
                    }
                    foreach (EventSet childSet in eventSet.ChildSets)
                    {
                        AddChildEvents(childSet);
                    }
                }
            }

            PreloadContent(GetFilesToPreload());

            roundDuration        = 0.0f;
            isCrewAway           = false;
            crewAwayDuration     = 0.0f;
            crewAwayResetTimer   = 0.0f;
            intensityUpdateTimer = 0.0f;
            CalculateCurrentIntensity(0.0f);
            currentIntensity = targetIntensity;
            eventCoolDown    = 0.0f;
        }
        private void CreateEvents(EventSet eventSet, Random rand)
        {
            if (level == null)
            {
                return;
            }
            int applyCount = 1;
            List <Func <Level.InterestingPosition, bool> > spawnPosFilter = new List <Func <Level.InterestingPosition, bool> >();

            if (eventSet.PerRuin)
            {
                applyCount = Level.Loaded.Ruins.Count();
                foreach (var ruin in Level.Loaded.Ruins)
                {
                    spawnPosFilter.Add((Level.InterestingPosition pos) => { return(pos.Ruin == ruin); });
                }
            }
            else if (eventSet.PerCave)
            {
                applyCount = Level.Loaded.Caves.Count();
                foreach (var cave in Level.Loaded.Caves)
                {
                    spawnPosFilter.Add((Level.InterestingPosition pos) => { return(pos.Cave == cave); });
                }
            }
            else if (eventSet.PerWreck)
            {
                var wrecks = Submarine.Loaded.Where(s => s.Info.IsWreck && (s.WreckAI == null || !s.WreckAI.IsAlive));
                applyCount = wrecks.Count();
                foreach (var wreck in wrecks)
                {
                    spawnPosFilter.Add((Level.InterestingPosition pos) => { return(pos.Submarine == wreck); });
                }
            }
            for (int i = 0; i < applyCount; i++)
            {
                if (eventSet.ChooseRandom)
                {
                    if (eventSet.EventPrefabs.Count > 0)
                    {
                        List <Pair <EventPrefab, float> > unusedEvents = new List <Pair <EventPrefab, float> >(eventSet.EventPrefabs);
                        for (int j = 0; j < eventSet.EventCount; j++)
                        {
                            var eventPrefab = ToolBox.SelectWeightedRandom(unusedEvents, unusedEvents.Select(e => CalculateCommonness(e)).ToList(), rand);
                            if (eventPrefab != null)
                            {
                                var newEvent = eventPrefab.First.CreateInstance();
                                if (newEvent == null)
                                {
                                    continue;
                                }
                                newEvent.Init(true);
                                if (i < spawnPosFilter.Count)
                                {
                                    newEvent.SpawnPosFilter = spawnPosFilter[i];
                                }
                                DebugConsole.Log("Initialized event " + newEvent.ToString());
                                if (!selectedEvents.ContainsKey(eventSet))
                                {
                                    selectedEvents.Add(eventSet, new List <Event>());
                                }
                                selectedEvents[eventSet].Add(newEvent);
                                unusedEvents.Remove(eventPrefab);
                            }
                        }
                    }
                    if (eventSet.ChildSets.Count > 0)
                    {
                        var newEventSet = SelectRandomEvents(eventSet.ChildSets);
                        if (newEventSet != null)
                        {
                            CreateEvents(newEventSet, rand);
                        }
                    }
                }
                else
                {
                    foreach (Pair <EventPrefab, float> eventPrefab in eventSet.EventPrefabs)
                    {
                        var newEvent = eventPrefab.First.CreateInstance();
                        if (newEvent == null)
                        {
                            continue;
                        }
                        newEvent.Init(true);
                        DebugConsole.Log("Initialized event " + newEvent.ToString());
                        if (!selectedEvents.ContainsKey(eventSet))
                        {
                            selectedEvents.Add(eventSet, new List <Event>());
                        }
                        selectedEvents[eventSet].Add(newEvent);
                    }

                    foreach (EventSet childEventSet in eventSet.ChildSets)
                    {
                        CreateEvents(childEventSet, rand);
                    }
                }
            }
        }
示例#24
0
        private void CreateEvents(EventSet eventSet, Random rand)
        {
            if (level == null)
            {
                return;
            }
            if (level.LevelData.HasHuntingGrounds && eventSet.DisableInHuntingGrounds)
            {
                return;
            }
#if DEBUG
            DebugConsole.NewMessage($"Loading event set {eventSet.DebugIdentifier}", Color.LightBlue);
#else
            DebugConsole.Log($"Loading event set {eventSet.DebugIdentifier}");
#endif
            int applyCount = 1;
            List <Func <Level.InterestingPosition, bool> > spawnPosFilter = new List <Func <Level.InterestingPosition, bool> >();
            if (eventSet.PerRuin)
            {
                applyCount = level.Ruins.Count();
                foreach (var ruin in level.Ruins)
                {
                    spawnPosFilter.Add((Level.InterestingPosition pos) => { return(pos.Ruin == ruin); });
                }
            }
            else if (eventSet.PerCave)
            {
                applyCount = level.Caves.Count();
                foreach (var cave in level.Caves)
                {
                    spawnPosFilter.Add((Level.InterestingPosition pos) => { return(pos.Cave == cave); });
                }
            }
            else if (eventSet.PerWreck)
            {
                var wrecks = Submarine.Loaded.Where(s => s.Info.IsWreck && (s.WreckAI == null || !s.WreckAI.IsAlive));
                applyCount = wrecks.Count();
                foreach (var wreck in wrecks)
                {
                    spawnPosFilter.Add((Level.InterestingPosition pos) => { return(pos.Submarine == wreck); });
                }
            }

            bool isPrefabSuitable(EventPrefab p)
            => string.IsNullOrEmpty(p.BiomeIdentifier) ||
            p.BiomeIdentifier.Equals(level.LevelData?.Biome?.Identifier, StringComparison.OrdinalIgnoreCase);

            var suitablePrefabSubsets = eventSet.EventPrefabs
                                        .FindAll(p => p.Prefabs.Any(isPrefabSuitable));

            for (int i = 0; i < applyCount; i++)
            {
                if (eventSet.ChooseRandom)
                {
                    if (suitablePrefabSubsets.Count > 0)
                    {
                        var unusedEvents = suitablePrefabSubsets.ToList();
                        for (int j = 0; j < eventSet.EventCount; j++)
                        {
                            if (unusedEvents.All(e => e.Prefabs.All(p => CalculateCommonness(p, e.Commonness) <= 0.0f)))
                            {
                                break;
                            }
                            EventSet.SubEventPrefab subEventPrefab = ToolBox.SelectWeightedRandom(unusedEvents, unusedEvents.Select(e => e.Prefabs.Max(p => CalculateCommonness(p, e.Commonness))).ToList(), rand);
                            (IEnumerable <EventPrefab> eventPrefabs, float commonness, float probability) = subEventPrefab;
                            if (eventPrefabs != null && rand.NextDouble() <= probability)
                            {
                                var finalPrefabs            = eventPrefabs.Where(isPrefabSuitable).ToArray();
                                var finalPrefabCommonnesses = finalPrefabs.Select(p => p.Commonness).ToArray();
                                var eventPrefab             = ToolBox.SelectWeightedRandom(finalPrefabs, finalPrefabCommonnesses, rand);

                                var newEvent = eventPrefab.CreateInstance();
                                if (newEvent == null)
                                {
                                    continue;
                                }
                                newEvent.Init(true);
                                if (i < spawnPosFilter.Count)
                                {
                                    newEvent.SpawnPosFilter = spawnPosFilter[i];
                                }
#if DEBUG
                                DebugConsole.NewMessage($"Initialized event {newEvent}");
#else
                                DebugConsole.Log($"Initialized event {newEvent}");
#endif
                                if (!selectedEvents.ContainsKey(eventSet))
                                {
                                    selectedEvents.Add(eventSet, new List <Event>());
                                }
                                selectedEvents[eventSet].Add(newEvent);
                                unusedEvents.Remove(subEventPrefab);
                            }
                        }
                    }
                    if (eventSet.ChildSets.Count > 0)
                    {
                        var newEventSet = SelectRandomEvents(eventSet.ChildSets, rand);
                        if (newEventSet != null)
                        {
                            CreateEvents(newEventSet, rand);
                        }
                    }
                }
                else
                {
                    foreach ((IEnumerable <EventPrefab> eventPrefabs, float commonness, float probability) in suitablePrefabSubsets)
                    {
                        if (rand.NextDouble() > probability)
                        {
                            continue;
                        }

                        var finalPrefabs            = eventPrefabs.Where(isPrefabSuitable).ToArray();
                        var finalPrefabCommonnesses = finalPrefabs.Select(p => p.Commonness).ToArray();
                        var eventPrefab             = ToolBox.SelectWeightedRandom(finalPrefabs, finalPrefabCommonnesses, rand);
                        var newEvent = eventPrefab.CreateInstance();
                        if (newEvent == null)
                        {
                            continue;
                        }
                        newEvent.Init(true);
#if DEBUG
                        DebugConsole.NewMessage($"Initialized event {newEvent}");
#else
                        DebugConsole.Log($"Initialized event {newEvent}");
#endif
                        if (!selectedEvents.ContainsKey(eventSet))
                        {
                            selectedEvents.Add(eventSet, new List <Event>());
                        }
                        selectedEvents[eventSet].Add(newEvent);
                    }

                    foreach (EventSet childEventSet in eventSet.ChildSets)
                    {
                        CreateEvents(childEventSet, rand);
                    }
                }
            }
        }
        public void SpawnCreatures(Level level, int count, Vector2?position = null)
        {
            creatures.Clear();

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

            count = Math.Min(count, MaxCreatures);

            List <BackgroundCreaturePrefab> availablePrefabs = new List <BackgroundCreaturePrefab>(prefabs);

            for (int i = 0; i < count; i++)
            {
                Vector2 pos = Vector2.Zero;
                if (position == null)
                {
                    var wayPoints = WayPoint.WayPointList.FindAll(wp => wp.Submarine == null);
                    if (wayPoints.Any())
                    {
                        WayPoint wp = wayPoints[Rand.Int(wayPoints.Count, Rand.RandSync.ClientOnly)];
                        pos  = new Vector2(wp.Rect.X, wp.Rect.Y);
                        pos += Rand.Vector(200.0f, Rand.RandSync.ClientOnly);
                    }
                    else
                    {
                        pos = Rand.Vector(2000.0f, Rand.RandSync.ClientOnly);
                    }
                }
                else
                {
                    pos = (Vector2)position;
                }

                var prefab = ToolBox.SelectWeightedRandom(availablePrefabs, availablePrefabs.Select(p => p.GetCommonness(level.GenerationParams)).ToList(), Rand.RandSync.ClientOnly);
                if (prefab == null)
                {
                    break;
                }

                int amount = Rand.Range(prefab.SwarmMin, prefab.SwarmMax, Rand.RandSync.ClientOnly);
                List <BackgroundCreature> swarmMembers = new List <BackgroundCreature>();
                for (int n = 0; n < amount; n++)
                {
                    var creature = new BackgroundCreature(prefab, pos + Rand.Vector(Rand.Range(0.0f, prefab.SwarmRadius, Rand.RandSync.ClientOnly), Rand.RandSync.ClientOnly));
                    creatures.Add(creature);
                    swarmMembers.Add(creature);
                }
                if (amount > 1)
                {
                    new Swarm(swarmMembers, prefab.SwarmRadius, prefab.SwarmCohesion);
                }
                if (creatures.Count(c => c.Prefab == prefab) > prefab.MaxCount)
                {
                    availablePrefabs.Remove(prefab);
                    if (availablePrefabs.Count <= 0)
                    {
                        break;
                    }
                }
            }
        }
示例#26
0
        public static NPCPersonalityTrait GetRandom(string seed)
        {
            var rand = new MTRandom(ToolBox.StringToInt(seed));

            return(ToolBox.SelectWeightedRandom(list, list.Select(t => t.commonness).ToList(), rand));
        }
示例#27
0
        private void CreateEvents(ScriptedEventSet eventSet)
        {
            int applyCount = 1;

            if (eventSet.PerRuin)
            {
                applyCount = Level.Loaded.Ruins.Count();
            }
            else if (eventSet.PerWreck)
            {
                applyCount = Submarine.Loaded.Count(s => s.Info.IsWreck && (s.WreckAI == null || !s.WreckAI.IsAlive));
            }
            for (int i = 0; i < applyCount; i++)
            {
                if (eventSet.ChooseRandom)
                {
                    if (eventSet.EventPrefabs.Count > 0)
                    {
                        MTRandom rand        = new MTRandom(ToolBox.StringToInt(level.Seed));
                        var      eventPrefab = ToolBox.SelectWeightedRandom(eventSet.EventPrefabs, eventSet.EventPrefabs.Select(e => e.Commonness).ToList(), rand);
                        if (eventPrefab != null)
                        {
                            var newEvent = eventPrefab.CreateInstance();
                            newEvent.Init(true);
                            DebugConsole.Log("Initialized event " + newEvent.ToString());
                            if (!selectedEvents.ContainsKey(eventSet))
                            {
                                selectedEvents.Add(eventSet, new List <ScriptedEvent>());
                            }
                            selectedEvents[eventSet].Add(newEvent);
                        }
                    }
                    if (eventSet.ChildSets.Count > 0)
                    {
                        var newEventSet = SelectRandomEvents(eventSet.ChildSets);
                        if (newEventSet != null)
                        {
                            CreateEvents(newEventSet);
                        }
                    }
                }
                else
                {
                    foreach (ScriptedEventPrefab eventPrefab in eventSet.EventPrefabs)
                    {
                        var newEvent = eventPrefab.CreateInstance();
                        newEvent.Init(true);
                        DebugConsole.Log("Initialized event " + newEvent.ToString());
                        if (!selectedEvents.ContainsKey(eventSet))
                        {
                            selectedEvents.Add(eventSet, new List <ScriptedEvent>());
                        }
                        selectedEvents[eventSet].Add(newEvent);
                    }

                    foreach (ScriptedEventSet childEventSet in eventSet.ChildSets)
                    {
                        CreateEvents(childEventSet);
                    }
                }
            }
        }
        public void PlaceObjects(Level level, int amount)
        {
            objectGrid = new List <LevelObject> [
                level.Size.X / GridSize,
                (level.Size.Y - level.BottomPos) / GridSize];

            List <SpawnPosition> availableSpawnPositions = new List <SpawnPosition>();
            var levelCells = level.GetAllCells();

            availableSpawnPositions.AddRange(GetAvailableSpawnPositions(levelCells, LevelObjectPrefab.SpawnPosType.Wall));
            availableSpawnPositions.AddRange(GetAvailableSpawnPositions(level.SeaFloor.Cells, LevelObjectPrefab.SpawnPosType.SeaFloor));

            foreach (RuinGeneration.Ruin ruin in level.Ruins)
            {
                foreach (var ruinShape in ruin.RuinShapes)
                {
                    foreach (var wall in ruinShape.Walls)
                    {
                        availableSpawnPositions.Add(new SpawnPosition(
                                                        new GraphEdge(wall.A, wall.B),
                                                        (wall.A + wall.B) / 2.0f - ruinShape.Center,
                                                        LevelObjectPrefab.SpawnPosType.RuinWall,
                                                        ruinShape.GetLineAlignment(wall)));
                    }
                }
            }

            foreach (var posOfInterest in level.PositionsOfInterest)
            {
                if (posOfInterest.PositionType != Level.PositionType.MainPath && posOfInterest.PositionType != Level.PositionType.SidePath)
                {
                    continue;
                }

                availableSpawnPositions.Add(new SpawnPosition(
                                                new GraphEdge(posOfInterest.Position.ToVector2(), posOfInterest.Position.ToVector2() + Vector2.UnitX),
                                                Vector2.UnitY,
                                                LevelObjectPrefab.SpawnPosType.MainPath,
                                                Alignment.Top));
            }

            availableSpawnPositions.Add(new SpawnPosition(
                                            new GraphEdge(level.StartPosition - Vector2.UnitX, level.StartPosition + Vector2.UnitX),
                                            -Vector2.UnitY, LevelObjectPrefab.SpawnPosType.LevelStart, Alignment.Top));
            availableSpawnPositions.Add(new SpawnPosition(
                                            new GraphEdge(level.EndPosition - Vector2.UnitX, level.EndPosition + Vector2.UnitX),
                                            -Vector2.UnitY, LevelObjectPrefab.SpawnPosType.LevelEnd, Alignment.Top));

            var availablePrefabs = new List <LevelObjectPrefab>(LevelObjectPrefab.List);

            objects           = new List <LevelObject>();
            updateableObjects = new List <LevelObject>();

            Dictionary <LevelObjectPrefab, List <SpawnPosition> > suitableSpawnPositions = new Dictionary <LevelObjectPrefab, List <SpawnPosition> >();
            Dictionary <LevelObjectPrefab, List <float> >         spawnPositionWeights   = new Dictionary <LevelObjectPrefab, List <float> >();

            for (int i = 0; i < amount; i++)
            {
                //get a random prefab and find a place to spawn it
                LevelObjectPrefab prefab = GetRandomPrefab(level.GenerationParams, availablePrefabs);
                if (prefab == null)
                {
                    continue;
                }
                if (!suitableSpawnPositions.ContainsKey(prefab))
                {
                    suitableSpawnPositions.Add(prefab,
                                               availableSpawnPositions.Where(sp =>
                                                                             sp.SpawnPosTypes.Any(type => prefab.SpawnPos.HasFlag(type)) &&
                                                                             sp.Length >= prefab.MinSurfaceWidth &&
                                                                             (sp.Alignment == Alignment.Any || prefab.Alignment.HasFlag(sp.Alignment))).ToList());
                    spawnPositionWeights.Add(prefab,
                                             suitableSpawnPositions[prefab].Select(sp => sp.GetSpawnProbability(prefab)).ToList());
                }

                SpawnPosition spawnPosition = ToolBox.SelectWeightedRandom(suitableSpawnPositions[prefab], spawnPositionWeights[prefab], Rand.RandSync.Server);
                if (spawnPosition == null && prefab.SpawnPos != LevelObjectPrefab.SpawnPosType.None)
                {
                    continue;
                }
                PlaceObject(prefab, spawnPosition, level);
                if (prefab.MaxCount < amount)
                {
                    if (objects.Count(o => o.Prefab == prefab) >= prefab.MaxCount)
                    {
                        availablePrefabs.Remove(prefab);
                    }
                }
            }

            foreach (Level.Cave cave in level.Caves)
            {
                availablePrefabs = new List <LevelObjectPrefab>(LevelObjectPrefab.List.FindAll(p => p.SpawnPos.HasFlag(LevelObjectPrefab.SpawnPosType.CaveWall)));
                availableSpawnPositions.Clear();
                suitableSpawnPositions.Clear();
                spawnPositionWeights.Clear();

                var caveCells = cave.Tunnels.SelectMany(t => t.Cells);
                List <VoronoiCell> caveWallCells = new List <VoronoiCell>();
                foreach (var edge in caveCells.SelectMany(c => c.Edges))
                {
                    if (!edge.NextToCave)
                    {
                        continue;
                    }
                    if (edge.Cell1?.CellType == CellType.Solid)
                    {
                        caveWallCells.Add(edge.Cell1);
                    }
                    if (edge.Cell2?.CellType == CellType.Solid)
                    {
                        caveWallCells.Add(edge.Cell2);
                    }
                }
                availableSpawnPositions.AddRange(GetAvailableSpawnPositions(caveWallCells.Distinct(), LevelObjectPrefab.SpawnPosType.CaveWall));

                for (int i = 0; i < cave.CaveGenerationParams.LevelObjectAmount; i++)
                {
                    //get a random prefab and find a place to spawn it
                    LevelObjectPrefab prefab = GetRandomPrefab(cave.CaveGenerationParams, availablePrefabs);
                    if (prefab == null)
                    {
                        continue;
                    }
                    if (!suitableSpawnPositions.ContainsKey(prefab))
                    {
                        suitableSpawnPositions.Add(prefab,
                                                   availableSpawnPositions.Where(sp =>
                                                                                 sp.Length >= prefab.MinSurfaceWidth &&
                                                                                 (sp.Alignment == Alignment.Any || prefab.Alignment.HasFlag(sp.Alignment))).ToList());
                        spawnPositionWeights.Add(prefab,
                                                 suitableSpawnPositions[prefab].Select(sp => sp.GetSpawnProbability(prefab)).ToList());
                    }
                    SpawnPosition spawnPosition = ToolBox.SelectWeightedRandom(suitableSpawnPositions[prefab], spawnPositionWeights[prefab], Rand.RandSync.Server);
                    if (spawnPosition == null && prefab.SpawnPos != LevelObjectPrefab.SpawnPosType.None)
                    {
                        continue;
                    }
                    PlaceObject(prefab, spawnPosition, level);
                    if (prefab.MaxCount < amount)
                    {
                        if (objects.Count(o => o.Prefab == prefab) >= prefab.MaxCount)
                        {
                            availablePrefabs.Remove(prefab);
                        }
                    }
                }
            }
        }
 private LevelObjectPrefab GetRandomPrefab(string levelType)
 {
     return(ToolBox.SelectWeightedRandom(
                LevelObjectPrefab.List,
                LevelObjectPrefab.List.Select(p => p.GetCommonness(levelType)).ToList(), Rand.RandSync.Server));
 }
示例#30
0
            protected List <Tuple <string, Tuple <Client, Character> > > AssignTraitors(GameServer server, TraitorManager traitorManager, Character.TeamType team)
            {
                List <Character> characters = FindCharacters();

#if !ALLOW_SOLO_TRAITOR
                if (characters.Count < 2)
                {
                    return(null);
                }
#endif
                var roleCandidates = new Dictionary <string, HashSet <Tuple <Client, Character> > >();
                foreach (var role in Roles)
                {
                    roleCandidates.Add(role.Key, new HashSet <Tuple <Client, Character> >(FindTraitorCandidates(server, team, role.Value)));
                    if (roleCandidates[role.Key].Count <= 0)
                    {
                        return(null);
                    }
                }
                var candidateRoleCounts = new Dictionary <Tuple <Client, Character>, int>();
                foreach (var candidateEntry in roleCandidates)
                {
                    foreach (var candidate in candidateEntry.Value)
                    {
                        candidateRoleCounts[candidate] = candidateRoleCounts.TryGetValue(candidate, out var count) ? count + 1 : 1;
                    }
                }
                var unassignedRoles = new List <string>(roleCandidates.Keys);
                unassignedRoles.Sort((a, b) => roleCandidates[a].Count - roleCandidates[b].Count);
                var assignedCandidates = new List <Tuple <string, Tuple <Client, Character> > >();
                while (unassignedRoles.Count > 0)
                {
                    var currentRole         = unassignedRoles[0];
                    var availableCandidates = roleCandidates[currentRole].ToList();
                    if (availableCandidates.Count <= 0)
                    {
                        break;
                    }
                    unassignedRoles.RemoveAt(0);
                    availableCandidates.Sort((a, b) => candidateRoleCounts[b] - candidateRoleCounts[a]);
                    unassignedRoles.Sort((a, b) => roleCandidates[a].Count - roleCandidates[b].Count);

                    int numCandidates = 1;
                    for (int i = 1; i < availableCandidates.Count && candidateRoleCounts[availableCandidates[i]] == candidateRoleCounts[availableCandidates[0]]; ++i)
                    {
                        ++numCandidates;
                    }

                    var selected = ToolBox.SelectWeightedRandom(availableCandidates, availableCandidates.Select(c => Math.Max(c.Item1.RoundsSincePlayedAsTraitor, 0.1f)).ToList(), TraitorManager.Random);
                    assignedCandidates.Add(Tuple.Create(currentRole, selected));
                    foreach (var candidate in roleCandidates.Values)
                    {
                        candidate.Remove(selected);
                    }
                }
                if (unassignedRoles.Count > 0)
                {
                    return(null);
                }
                return(assignedCandidates);
            }