public void SpawnSpawnables(TrainingRoom room, System.Random rand)
    {
        var roomType = roomTypes.GetRandom(rand);
        HashSet <Vector2Int> floorTiles = new HashSet <Vector2Int>(room.unitSpaceFloors);
        HashSet <Vector2Int> wallTiles  = new HashSet <Vector2Int>(room.unitSpaceWalls);

        Debug.Log("LEVEL SPAWNED AT: " + transform.position);

        Vector2Int pos = new Vector2Int(Mathf.RoundToInt(transform.position.x), Mathf.RoundToInt(transform.position.z)) + room.Position;

        Debug.Log($"LEVEL SPAWN: {pos}");
        RoomType.RoomSet roomSet = roomType.roomSets.GetRandom(rand);
        var spawned = SpawnGenerator.SpawnItemsInRoom(rand, roomType, roomType.roomSets.GetRandom(rand), floorTiles, wallTiles, pos);

        foreach (var item in spawned)
        {
            item.transform.SetParent(room.transform);
        }
    }
示例#2
0
    const int MAX_ITEM_STACK = 3; // TODO: evaluate where to put this variable

    // place all the required items within a room
    public static HashSet <GameObject> SpawnItemsInRoom(Random rand, RoomType roomType, RoomType.RoomSet roomSet, HashSet <Vector2Int> floorPos, HashSet <Vector2Int> wallPos, Vector2Int finalizeOffset = default(Vector2Int)) //Defaults to zero
    {
        HashSet <GameObject> spawnedObjects = new HashSet <GameObject>();

        // we copying the list as we are changing the data of roomtype otherwise
        List <RoomType.SpawnListItem> workingList = new List <RoomType.SpawnListItem>(roomType.spawnList);

        if (roomSet.extraSpawnList != null)
        {
            workingList.AddRange(roomSet.extraSpawnList);
        }

        HashSet <Vector2Int> onTopPos     = new HashSet <Vector2Int>();
        HashSet <Vector2Int> workingFloor = new HashSet <Vector2Int>(floorPos);
        HashSet <Vector2Int> workingWall  = new HashSet <Vector2Int>(wallPos);


        for (int i = 0; i < workingList.Count; i++)
        {
            float relativeSpawnAmount = (500 / (workingFloor.Count + workingWall.Count));
            int   min = Mathf.RoundToInt(workingList[i].Min / relativeSpawnAmount);
            int   max = Mathf.RoundToInt(workingList[i].Max / relativeSpawnAmount);

            Debug.Log("onTop:" + workingList[i].Spawnable.spawnOnTop);
            HashSet <Vector2Int> allowedSpawnPos = new HashSet <Vector2Int>(); // HashSet has optimal lookuptimes   O(1)

            // TODO: validate that probability sum is one
            int totalPos = workingFloor.Count + wallPos.Count + onTopPos.Count;
            allowedSpawnPos.UnionWith(FindNewPos((int)Math.Round((totalPos * workingList[i].Spawnable.notWallProbability)), workingFloor, finalizeOffset, rand, 2));
            allowedSpawnPos.UnionWith(FindNewPos((int)Math.Round((totalPos * workingList[i].Spawnable.byWallProbability)), workingWall, finalizeOffset, rand, 2));
            allowedSpawnPos.UnionWith(FindNewPos((int)Math.Round((totalPos * workingList[i].Spawnable.spawnOnTop)), onTopPos, Vector2Int.zero, rand)); //NOTE CHANGE OFFSET TO 0

            // chose an amount to spawn a Spawnable type
            int spawnCount = rand.NextInclusive(min, max);


            for (int j = 0; j < spawnCount && allowedSpawnPos.Count > 0; j++)
            {
                // TODO: roll pos in tile
                Vector2Int tile          = allowedSpawnPos.GetRandom(rand);
                Vector3    spawnPosition = new Vector3(tile.x, 0, tile.y);

                Quaternion objectQuaternion = Quaternion.Euler(0, rand.NextInclusive(0, workingList[i].Spawnable.angleMaxOffset), 0);
                Vector3?   forward          = null;

                // if we are about to spawn on the side of a object, we need a forward vector
                bool isOnTopPos = onTopPos.Contains(tile);

                if (!isOnTopPos)
                {
                    forward = objectQuaternion * new Vector3(0, 0, 1);
                }


                if (TryResolvePositionPhysically(workingList[i].Spawnable, ref spawnPosition, forward, objectQuaternion))
                {
                    spawnedObjects.Add(GameObject.Instantiate(workingList[i].Spawnable.gameObject, spawnPosition, objectQuaternion));

                    // TODO: rounding bugs!!!
                    Vector2Int tileToRemove = new Vector2Int((int)(tile.x * 0.5f), (int)(tile.y * 0.5f));
                    workingFloor.RemoveWhere(pos => pos == tileToRemove);
                    workingWall.RemoveWhere(pos => pos == tileToRemove);

                    allowedSpawnPos.RemoveWhere(pos => pos == tile);

                    if (!workingList[i].Spawnable.allowOtherOnTop && isOnTopPos)
                    {
                        onTopPos.Remove(tile);
                    }
                    else if (workingList[i].Spawnable.allowOtherOnTop)
                    {
                        onTopPos.Add(tile);

                        if (workingList[i].Spawnable.spawnOnTop > rand.NextFloat())
                        {
                            allowedSpawnPos.Add(tile);
                        }
                    }

                    spawnCount -= SpawnRelatives(workingList[i].Spawnable, new Vector2(spawnPosition.x, spawnPosition.z), objectQuaternion, rand, ref spawnedObjects, ref workingList, min, max);
                }
            }
        }

        // if we are not debugging, we delete scripts used for placement
        if (Application.isPlaying)
        {
            foreach (var spawnedObject in spawnedObjects)
            {
                UnityEngine.Object.Destroy(spawnedObject.GetComponent <Spawnable>());
            }
        }


        return(spawnedObjects);
    }