Beispiel #1
0
    public static void AttachNewSquadTo(CommanderAgent commander, GameObject[] unitPrefabs,
                                        HashSet <Vector2Int> tiles, Vector2Int minMax, System.Random random, Room room, Vector2Int offset, GameObject player)
    {
        if (unitPrefabs == null)
        {
            Debug.LogError("create squad need unit prefab");
            return;
        }

        //Cleanup of previous squad============================
        foreach (var unit in commander.squad.units)
        {
            if (unit != null)
            {
                commander.squad.MarkDead(unit.squadUnitIndex);
                Object.Destroy(unit.gameObject);
            }
        }
        //commander.squad.units.Clear(); -> after array conversion we leave garbage here...
        //=====================================================

        commander.squad = new Squad()
        {
            currentRoom = room,
            squadSensor = commander.GetComponent <SquadSensor>(),
        };

        commander.squadColor = Random.ColorHSV(0, 1, 0.25f, 1f);

        int squadSize    = random.NextInclusive(minMax.x, minMax.y);
        int tilesPerUnit = 6;
        int maxUnits     = tiles.Count / tilesPerUnit;

        if (squadSize > maxUnits)
        {
            squadSize = maxUnits;
        }
        if (squadSize > CommanderAgent.MAX_SQUAD_SIZE)
        {
            squadSize = CommanderAgent.MAX_SQUAD_SIZE;
        }

        for (int i = 0; i < squadSize; i++)
        {
            Vector2 tile       = tiles.GetRandom(random);
            Vector3 position   = new Vector3((tile.x * 2) + offset.x, 1.055f, (tile.y * 2) + offset.y);
            var     newUnit    = Object.Instantiate(unitPrefabs.GetRandom(random), position, Quaternion.identity, commander.transform).GetComponent <SquadUnit>();
            var     unitSensor = newUnit.GetComponent <UnitSensor>();
            unitSensor.player = player;
            unitSensor.headColliderTransform = player.transform;
            SetMaterialColor(newUnit, commander.squadColor);
            commander.squad.AddUnit(newUnit);
        }
        return;
    }
Beispiel #2
0
    //TODO add support for multiple
    public static void CreateNewSquad(GameObject squad, GameObject unitPrefab, HashSet <Vector2Int> tiles,
                                      Vector2Int minMax, System.Random random, MLAgents.Brain Brain, Room room, Vector2Int offset, GameObject player)
    {
        if (unitPrefab == null)
        {
            Debug.LogError("create squad need unit prefab");
            return;
        }
        CommanderAgent prefabCommander = squad.GetComponent <CommanderAgent>();

        if (prefabCommander == null)
        {
            Debug.LogError("create squad need squad prefab");
            return;
        }
        if (prefabCommander.squad.units.Length > 0)
        {
            Debug.LogError("squad prefab needs to contain no units");
            return;
        }
        if (player == null)
        {
            Debug.LogError("Squad needs to be initialized with player reference");
            return;
        }

        GameObject     newSquadObject = Object.Instantiate(squad, Vector3.zero, Quaternion.identity);
        CommanderAgent commanderAgent = newSquadObject.GetComponent <CommanderAgent>();

        commanderAgent.squad.currentRoom = room;
        commanderAgent.GiveBrain(Brain);
        commanderAgent.squadColor = Random.ColorHSV(0, 1, 0.25f, 1f);

        int squadSize    = random.NextInclusive(minMax.x, minMax.y);
        int tilesPerUnit = 6;
        int maxUnits     = tiles.Count / tilesPerUnit;

        if (squadSize > maxUnits)
        {
            squadSize = maxUnits;
        }
        if (squadSize > CommanderAgent.MAX_SQUAD_SIZE)
        {
            squadSize = CommanderAgent.MAX_SQUAD_SIZE;
        }



        for (int i = 0; i < squadSize; i++)
        {
            Vector2   tile       = tiles.GetRandom(random);
            Vector3   position   = new Vector3((tile.x * 2) + offset.x, 1.055f, (tile.y * 2) + offset.y);
            var       unit       = Object.Instantiate(unitPrefab, position, Quaternion.identity, newSquadObject.transform);
            SquadUnit newUnit    = unit.GetComponent <SquadUnit>();
            var       unitSensor = newUnit.GetComponent <UnitSensor>();
            unitSensor.player = player;
            unitSensor.headColliderTransform = player.transform;
            SetMaterialColor(newUnit, commanderAgent.squadColor);
            commanderAgent.squad.AddUnit(newUnit);
        }

        return;
    }
Beispiel #3
0
    // This function is tasked with spawning items relative to already placed item
    // will return a list of spawned items so that SpawnItemsInRoom know what's left to spawn
    public static int SpawnRelatives(Spawnable spawned, Vector2 spawnedPos, Quaternion spawnedRot, Random rand,
                                     ref HashSet <GameObject> spawnedObjects, ref List <RoomType.SpawnListItem> availableItems,
                                     int min, int max, int currentRecusion = 0)
    {
        int spawnedOfSameCount = 0;

        if (currentRecusion < 2)
        {
            int spawnedIndex = availableItems.FindIndex(spawnableItem => spawnableItem.Spawnable == spawned);

            for (int i = 0; i < spawned.relativeSpawnList.Length; i++)
            {
                int relationIndex = availableItems.FindIndex(spawnableItem => spawnableItem.Spawnable == spawned.relativeSpawnList[i].Spawnable);
                if (relationIndex != -1 && spawnedIndex <= relationIndex)
                {
                    int spawnCount          = rand.NextInclusive(min, max);
                    int spawnedObjectsCount = 0;

                    // if the rotation is set (not random)
                    if (spawned.relativeSpawnList[i].AngleIteration != 0)
                    {
                        for (int j = 0; j < spawnCount && Math.Abs(j * spawned.relativeSpawnList[i].AngleIteration) < 360; j++)
                        {
                            Quaternion objectQuaternion = Quaternion.Euler(0, j * spawned.relativeSpawnList[i].AngleIteration + spawnedRot.eulerAngles.y, 0);
                            Vector3    spawnPosition    = new Vector3(spawnedPos.x, 0, spawnedPos.y);
                            Vector3    forward          = objectQuaternion * new Vector3(0, 0, 1);
                            if (TryResolvePositionPhysically(spawned.relativeSpawnList[i].Spawnable, ref spawnPosition, -forward, objectQuaternion))
                            {
                                spawnedObjects.Add(GameObject.Instantiate(spawned.relativeSpawnList[i].Spawnable.gameObject, spawnPosition, objectQuaternion));
                                SpawnRelatives(spawned.relativeSpawnList[i].Spawnable, new Vector2Int((int)spawnPosition.x, (int)spawnPosition.z), objectQuaternion, rand, ref spawnedObjects, ref availableItems, min, max, ++currentRecusion);
                            }

                            spawnedObjectsCount = j;
                        }

                        int newMin = ((min - spawnedObjectsCount) > 0) ? min - spawnedObjectsCount : 0;
                        int newMax = ((max - spawnedObjectsCount) > 0) ? max - spawnedObjectsCount : 0;

                        RoomType.SpawnListItem updatedItem = new RoomType.SpawnListItem(availableItems[relationIndex].AngleIteration, new Vector2Int(newMin, newMax), availableItems[relationIndex].Spawnable);
                        availableItems[relationIndex] = updatedItem;

                        if (spawnedIndex == relationIndex)
                        {
                            spawnedOfSameCount++;
                        }
                    }
                    else
                    {
                        for (int j = 0; j < spawnCount; j++)
                        {
                            Quaternion objectQuaternion = Quaternion.Euler(0, rand.NextInclusive(0, availableItems[relationIndex].Spawnable.angleMaxOffset), 0);
                            float      xPos             = spawnedPos.x + (rand.NextFloat() * (spawned.neededSpawnSpace.extents.x * 0.75f)) * (rand.NextBool() ? -1 : 1);
                            float      zPos             = spawnedPos.y + (rand.NextFloat() * (spawned.neededSpawnSpace.extents.z * 0.75f)) * (rand.NextBool() ? -1 : 1);
                            Vector3    spawnPosition    = new Vector3(xPos, 0, zPos);

                            if (TryResolvePositionPhysically(spawned.relativeSpawnList[i].Spawnable, ref spawnPosition, null, objectQuaternion))
                            {
                                spawnedObjects.Add(GameObject.Instantiate(spawned.relativeSpawnList[i].Spawnable.gameObject, spawnPosition, objectQuaternion));
                                SpawnRelatives(spawned.relativeSpawnList[i].Spawnable, new Vector2Int((int)spawnPosition.x, (int)spawnPosition.z), objectQuaternion, rand, ref spawnedObjects, ref availableItems, min, max, ++currentRecusion);
                            }

                            spawnedObjectsCount = j;
                        }

                        int newMin = ((min - spawnedObjectsCount) > 0) ? min - spawnedObjectsCount : 0;
                        int newMax = ((max - spawnedObjectsCount) > 0) ? max - spawnedObjectsCount : 0;

                        RoomType.SpawnListItem updatedItem = new RoomType.SpawnListItem(availableItems[relationIndex].AngleIteration, new Vector2Int(newMin, newMax), availableItems[relationIndex].Spawnable);
                        availableItems[relationIndex] = updatedItem;

                        if (spawnedIndex == relationIndex)
                        {
                            spawnedOfSameCount++;
                        }
                    }
                }
            }
        }

        return(spawnedOfSameCount);
    }
Beispiel #4
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);
    }