예제 #1
0
        private void CheckDoorwayCount(DungeonFlow flow, DungeonValidator validator)
        {
            var pathTileSets = new List <TileSet>();

            foreach (var node in flow.Nodes)
            {
                if (node.NodeType != NodeType.Start && node.NodeType != NodeType.Goal)
                {
                    pathTileSets.AddRange(node.TileSets);
                }
            }

            foreach (var line in flow.Lines)
            {
                foreach (var archetype in line.DungeonArchetypes)
                {
                    pathTileSets.AddRange(archetype.TileSets);
                }
            }


            var pathTiles = pathTileSets.SelectMany(ts => ts.TileWeights.Weights.Select(w => w.Value)).Where(t => t != null);

            foreach (var tile in pathTiles)
            {
                int doorwayCount = tile.GetComponentsInChildren <Doorway>(true).Count();

                if (doorwayCount < 2)
                {
                    validator.AddError("Tile '{0}' does not have enough doorways. Two doorways are required for all tiles except those that appear exclusively as a start node, goal node, or branch cap", tile, tile.name);
                }
            }
        }
예제 #2
0
        private void CheckArchetypes(DungeonFlow flow, DungeonValidator validator)
        {
            var archetypes = flow.GetUsedArchetypes();

            foreach (var archetype in archetypes)
            {
                if (archetype == null)
                {
                    continue;
                }

                if (archetype.TileSets.Count == 0)
                {
                    validator.AddError("The archetype '{0}' has no tile sets assigned", archetype, archetype.name);
                }
                else
                {
                    foreach (var tileSet in archetype.TileSets)
                    {
                        if (tileSet == null)
                        {
                            validator.AddError("The archetype '{0}' has a missing tile set", archetype, archetype.name);
                        }
                    }
                }

                foreach (var tileSet in archetype.BranchCapTileSets)
                {
                    if (tileSet == null)
                    {
                        validator.AddError("Archetype '{0}' has a missing branch cap tile set", archetype, archetype.name);
                    }
                }
            }
        }
예제 #3
0
        private void CheckDoorwayForwardVectors(DungeonFlow flow, DungeonValidator validator, Dictionary <GameObject, Doorway[]> tileDoorways)
        {
            foreach (var pair in tileDoorways)
            {
                var tile   = pair.Key;
                var bounds = UnityUtil.CalculateObjectBounds(tile, true, false);

                foreach (var doorway in pair.Value)
                {
                    Vector3 forwardVector = doorway.transform.forward;

                    if (!IsAxisAligned(forwardVector))
                    {
                        validator.AddError("Doorway '{0}' in tile '{1}' has an invalid rotation. the forward vector is not axis-aligned", tile, doorway.name, tile.name);
                    }
                    else
                    {
                        Vector3 centerToDoorway = (doorway.transform.position - bounds.center).normalized;
                        float   angle           = Vector3.Angle(centerToDoorway, forwardVector);

                        if (angle > 85f)
                        {
                            validator.AddError("Doorway '{0}' in tile '{1}' is facing the wrong way. Doorways should face outwards from the tile (local z-axis, blue line)", tile, doorway.name, tile.name);
                        }
                    }
                }
            }
        }
예제 #4
0
        private void CheckNodes(DungeonFlow flow, DungeonValidator validator)
        {
            if (flow.Nodes.Count < 2)
            {
                validator.AddError("The dungeon flow must contain at least two nodes");
            }

            foreach (var node in flow.Nodes)
            {
                if (node.TileSets.Count == 0)
                {
                    validator.AddError("The node '{0}' in the dungeon flow graph has no tile sets applied", node.Label);
                }
                else
                {
                    foreach (var tileSet in node.TileSets)
                    {
                        if (tileSet == null)
                        {
                            validator.AddError("Node '{0}' in your dungeon flow graph has an unset tileset value", node.Label);
                        }
                    }
                }
            }
        }
예제 #5
0
        private void CheckDoorwayUpVectors(DungeonFlow flow, DungeonValidator validator, Dictionary <GameObject, Doorway[]> tileDoorways)
        {
            var doorwaysByUpVector = new Dictionary <Vector3, List <DoorwayInfo> >();

            foreach (var pair in tileDoorways)
            {
                foreach (var doorway in pair.Value)
                {
                    Vector3 upVector = doorway.transform.up;

                    List <DoorwayInfo> doorwaySet = null;

                    foreach (var existingPair in doorwaysByUpVector)
                    {
                        if (Vector3.Angle(upVector, existingPair.Key) <= AngleThreshold)
                        {
                            doorwaySet = existingPair.Value;
                        }
                    }

                    if (doorwaySet == null)
                    {
                        doorwaySet = new List <DoorwayInfo>();
                        doorwaysByUpVector[upVector] = doorwaySet;
                    }

                    doorwaySet.Add(new DoorwayInfo(doorway, pair.Key));
                }
            }

            if (doorwaysByUpVector.Count > 1)
            {
                Vector3 mostCommonUpVector = doorwaysByUpVector.OrderByDescending(x => x.Value.Count).First().Key;

                if (!IsAxisAligned(mostCommonUpVector))
                {
                    validator.AddError("The most common doorway up vector is not axis-aligned");
                }

                foreach (var pair in doorwaysByUpVector)
                {
                    if (pair.Key == mostCommonUpVector)
                    {
                        continue;
                    }

                    foreach (var info in pair.Value)
                    {
                        validator.AddError("Doorway '{0}' in tile '{1}' has an invalid rotation. The most common up-vector among doorways is {2}", info.TilePrefab, info.Doorway.name, info.TilePrefab.name, mostCommonUpVector);
                    }
                }
            }
        }
예제 #6
0
        public void Validate(DungeonFlow flow, DungeonValidator validator)
        {
            // Check DungeonFlow
            if (flow == null)
            {
                validator.AddError("No DungeonFlow is assigned");
                return;
            }

            CheckLineSegments(flow, validator);
            CheckNodes(flow, validator);
            CheckArchetypes(flow, validator);
            CheckTileSets(flow, validator);
        }
예제 #7
0
        private void CheckDoorwaySockets(DungeonFlow flow, DungeonValidator validator, Dictionary <GameObject, Doorway[]> tileDoorways)
        {
            foreach (var pair in tileDoorways)
            {
                var tile = pair.Key;

                foreach (var doorway in pair.Value)
                {
                    if (!doorway.HasSocketAssigned)
                    {
                        validator.AddWarning("Doorway '{0}' in tile '{1}' has no socket assigned. The default socket will be used.", tile, doorway.name, tile.name);
                    }
                }
            }
        }
예제 #8
0
        public void Validate(DungeonFlow flow, DungeonValidator validator)
        {
            var tiles = flow.GetUsedTileSets()
                        .SelectMany(ts => ts.TileWeights.Weights.Select(w => w.Value))
                        .Where(t => t != null);

            var tileDoorways = new Dictionary <GameObject, Doorway[]>();

            foreach (var tile in tiles)
            {
                tileDoorways[tile] = tile.GetComponentsInChildren <Doorway>(true);
            }

            CheckDoorwayCount(flow, validator);
            CheckDoorwayUpVectors(flow, validator, tileDoorways);
            CheckDoorwayForwardVectors(flow, validator, tileDoorways);
            CheckDoorwaySockets(flow, validator, tileDoorways);
        }
예제 #9
0
        private void CheckTileSets(DungeonFlow flow, DungeonValidator validator)
        {
            var tileSets = flow.GetUsedTileSets();

            foreach (var tileSet in tileSets)
            {
                if (tileSet == null)
                {
                    continue;
                }

                foreach (var tileWeight in tileSet.TileWeights.Weights)
                {
                    if (tileWeight.Value == null)
                    {
                        validator.AddWarning("The tile set '{0}' has a missing tile", tileSet, tileSet.name);
                    }

                    if (tileWeight.MainPathWeight <= 0f && tileWeight.BranchPathWeight <= 0f)
                    {
                        validator.AddWarning("Tile set '{0}' has a tile ({1}) set up with a main path weight and branch path weight of zero. This tile will never appear in the dungeon", tileSet, tileSet.name, (tileWeight.Value == null) ? "NULL" : tileWeight.Value.name);
                    }

                    if (tileWeight.DepthWeightScale != null)
                    {
                        bool hasNonZeroKeyframe = false;

                        foreach (var key in tileWeight.DepthWeightScale.keys)
                        {
                            if (key.value > 0f)
                            {
                                hasNonZeroKeyframe = true;
                                break;
                            }
                        }

                        if (!hasNonZeroKeyframe)
                        {
                            validator.AddWarning("Tile set '{0}' has a tile ({1}) set up with a depth curve that will always return zero. This tile will never appear in the dungeon", tileSet, tileSet.name, tileWeight.Value.name);
                        }
                    }
                }
            }
        }
예제 #10
0
        private void CheckLineSegments(DungeonFlow flow, DungeonValidator validator)
        {
            if (flow.Lines.Count < 1)
            {
                validator.AddError("The dungeon flow must contain at least one line segment");
            }

            foreach (var line in flow.Lines)
            {
                if (line.DungeonArchetypes.Count == 0)
                {
                    validator.AddError("A line segments in your dungeon flow graph has no archetype applied");
                }

                foreach (var archetype in line.DungeonArchetypes)
                {
                    if (archetype == null)
                    {
                        validator.AddError("A line segment in your dungeon flow graph has an unset archetype value");
                    }
                }
            }
        }