Example #1
0
        protected List <Coord> findNearestEnemies(Coord start)
        {
            int[,] moveDirs = new int[, ] {
                { 0, 1 }, { 0, -1 }, { 1, 0 }, { -1, 0 }
            };
            HashSet <Coord> visited   = new HashSet <Coord>();
            Queue <Coord>   moveQueue = new Queue <Coord>();

            moveQueue.Enqueue(start);
            visited.Add(start);

            List <Coord> enemies = new List <Coord>();
            int          minDist = Int32.MaxValue;

            while (moveQueue.Count() > 0)
            {
                Coord curCoord = moveQueue.Dequeue();

                if (manhattanDistance(start, curCoord) > minDist)
                {
                    return(enemies);
                }

                IBattlefieldItem item = battlefield.battlefieldItemAt(curCoord.x, curCoord.y, 0);
                if (item is Unit)
                {
                    Unit unit = item as Unit;
                    if (!battlefield.charactersUnits[character].Contains(unit))
                    {
                        enemies.Add(curCoord);
                        if (minDist == Int32.MaxValue)
                        {
                            minDist = manhattanDistance(start, curCoord);
                        }
                    }
                }


                for (int x = 0; x < moveDirs.GetLength(0); x++)
                {
                    Coord nextCoord = new Coord(curCoord.x + moveDirs[x, 0], curCoord.y + moveDirs[x, 1]);
                    if (nextCoord.x >= 0 && nextCoord.y >= 0 && nextCoord.x < battlefield.map.GetLength(0) && nextCoord.y < battlefield.map.GetLength(1))
                    {
                        if (!visited.Contains(nextCoord))
                        {
                            visited.Add(nextCoord);
                            moveQueue.Enqueue(nextCoord);
                        }
                    }
                }
            }

            return(enemies);
        }
Example #2
0
        protected Unit coordToUnit(Coord coord)
        {
            IBattlefieldItem item = battlefield.battlefieldItemAt(coord.x, coord.y, 0);

            if (item is Unit)
            {
                return(item as Unit);
            }
            else
            {
                return(null);
            }
        }
Example #3
0
        // Replaced findEnemiesWithinDistance. Use with filterEnemies to achieve the same result.
        protected List <Coord> findUnitsWithinDistance(Coord start, int minDist)
        {
            int[,] moveDirs = new int[, ] {
                { 0, 1 }, { 0, -1 }, { 1, 0 }, { -1, 0 }
            };
            HashSet <Coord> visited   = new HashSet <Coord>();
            Queue <Coord>   moveQueue = new Queue <Coord>();

            moveQueue.Enqueue(start);
            visited.Add(start);

            List <Coord> units = new List <Coord> ();

            while (moveQueue.Count() > 0)
            {
                Coord curCoord = moveQueue.Dequeue();

                if (manhattanDistance(start, curCoord) > minDist)
                {
                    return(units);
                }

                IBattlefieldItem item = battlefield.battlefieldItemAt(curCoord.x, curCoord.y, 0);
                if (item is Unit)
                {
                    Unit unit = item as Unit;
                    units.Add(curCoord);
                }

                for (int x = 0; x < moveDirs.GetLength(0); x++)
                {
                    Coord nextCoord = new Coord(curCoord.x + moveDirs[x, 0], curCoord.y + moveDirs[x, 1]);
                    if (nextCoord.x >= 0 && nextCoord.y >= 0 && nextCoord.x < battlefield.map.GetLength(0) && nextCoord.y < battlefield.map.GetLength(1))
                    {
                        if (!visited.Contains(nextCoord))
                        {
                            visited.Add(nextCoord);
                            moveQueue.Enqueue(nextCoord);
                        }
                    }
                }
            }
            return(units);
        }
Example #4
0
        // Update is called once per frame
        async void Update()
        {
            switch (battleStage)
            {
            case BattleLoopStage.Initial:
                if (!cutscene.isRunning)
                {
                    CameraController.inputEnabled = true;
                    cutsceneCamera.enabled        = false;
                    mainCamera.enabled            = true;
                    advanceBattleStage();
                }
                break;

            case BattleLoopStage.Pick:
                advanceBattleStage();
                break;

            case BattleLoopStage.BattleLoopStart:
                advanceBattleStage();
                break;

            case BattleLoopStage.TurnChange:
                //If we've already entered this we're awaiting. Don't call it again every frame.
                if (!battleStageChanged)
                {
                    break;
                }
                battleStageChanged = false;

                currentCharacter    = (currentCharacter + 1) % level.characters.Length;
                turnPlayerText.text =
                    level.characters[currentCharacter].name + "'s turn\n" +
                    "Turns remaining:  " + (objective.maxHalfTurns - ((halfTurnsElapsed / 2) + 1));
                turnPlayerText.enabled       = true;
                turnChangeBackground.enabled = true;
                Util.setTimeout(advanceBattleStage, 1000);

                break;

            case BattleLoopStage.TurnChangeEnd:
                turnPlayerText.enabled       = false;
                turnChangeBackground.enabled = false;
                advanceBattleStage();
                break;

            case BattleLoopStage.UnitSelection:
                advanceBattleStage();
                break;

            case BattleLoopStage.ActionSelection:
                //If we've already entered this we're awaiting. Don't call it again every frame.
                if (!battleStageChanged)
                {
                    break;
                }
                battleStageChanged = false;

                //Character.getMove() is responsible for validation so we assume the move to be legal
                Move             move         = await level.characters[currentCharacter].getMove();
                Unit             ourUnit      = battlefield.units[move.from.x, move.from.y];
                IBattlefieldItem selectedItem = battlefield.battlefieldItemAt(move.to.x, move.to.y);

                if (selectedItem is Tile)
                {
                    //We selected a tile! lets move to it
                    moveUnit(ourUnit, move.to.x, move.to.y);

                    if (ourUnit.getTargets(move.to.x, move.to.y, battlefield, level.characters[currentCharacter]).Count == 0)
                    {
                        ourUnit.greyOut();
                    }
                }
                else if (selectedItem is Unit)
                {
                    //Targeted a hostile unit! fight!
                    Unit selectedUnit = selectedItem as Unit;

                    bool defenderDefeated = ourUnit.doBattleWith(
                        selectedUnit,
                        battlefield.map[move.to.x, move.to.y].Peek(),
                        battlefield);

                    await Task.Delay(TimeSpan.FromMilliseconds(250));

                    if (!defenderDefeated && (selectedItem is MeleeUnit) && (ourUnit is MeleeUnit))
                    {
                        //Counterattack applied only when both units are Melee
                        selectedUnit.doBattleWith(
                            ourUnit,
                            battlefield.map[move.from.x, move.from.y].Peek(),
                            battlefield);
                    }

                    ourUnit.setHasAttackedThisTurn(true);
                    await Task.Delay(TimeSpan.FromMilliseconds(250));
                }
                else
                {
                    Debug.LogWarning("Item of unrecognized type clicked on.");
                }

                checkWinAndLose();

                //If all of our units have moved advance. Otherwise, go back to unit selection.
                ourUnit.hasMovedThisTurn = true;
                if (battlefield.charactersUnits[level.characters[currentCharacter]].All(unit => {
                    //I know this looks inelegant but it avoid calling getUnitCoords if necessary
                    if (!unit.hasMovedThisTurn)
                    {
                        return(false);
                    }
                    else if (unit.getHasAttackedThisTurn())
                    {
                        return(true);
                    }
                    else
                    {
                        Coord coord = battlefield.getUnitCoords(unit);
                        return(unit.getTargets(coord.x, coord.y, battlefield, level.characters[currentCharacter]).Count == 0);
                    }
                }))
                {
                    advanceBattleStage();
                }
                else
                {
                    setBattleLoopStage(BattleLoopStage.UnitSelection);
                }

                break;

            case BattleLoopStage.EndTurn:
                //If we've already entered this we're awaiting. Don't call it again every frame.
                if (!battleStageChanged)
                {
                    break;
                }
                battleStageChanged = false;

                foreach (Unit unit in battlefield.charactersUnits[level.characters[currentCharacter]])
                {
                    unit.hasMovedThisTurn = false;
                    unit.setHasAttackedThisTurn(false);
                }

                bool endGame = checkWinAndLose();
                if (!endGame)
                {
                    advanceBattleStage();
                }

                halfTurnsElapsed++;

                break;
            }
        }
Example #5
0
        public void getSelectionPhase(Move currentMove)
        {
            RaycastHit hit;
            Ray        ray = Camera.main.ScreenPointToRay(Input.mousePosition);

            if (Physics.Raycast(ray, out hit, 1000.0f))
            {
                Vector3Int       tileCoords   = Util.WorldToGrid(hit.transform.position);
                IBattlefieldItem selectedItem = battlefield.battlefieldItemAt(tileCoords.x, tileCoords.y, tileCoords.z);

                if (selectedItem is Tile)
                {
                    //Selected a tile, show info abt that tile
                    //TODO: Show info about tile if a tile is clicked
                    Tile selectedTile = selectedItem as Tile;
                    unhighlightAll();
                    highlight(selectedTile.gameObject);

                    //This method will get called again because we didn't find a valid selection
                }
                else if (selectedItem is Unit)
                {
                    Unit selectedUnit = selectedItem as Unit;

                    if (selectedUnit.getCharacter(battlefield) == this.character &&
                        (!selectedUnit.hasMovedThisTurn || (!selectedUnit.getHasAttackedThisTurn() &&
                                                            selectedUnit.getTargets(tileCoords.x, tileCoords.y, battlefield, character).Count != 0)))
                    {
                        //Selected friendly unit. Valid selection, store selection coords.
                        currentMove.from = new Coord(tileCoords.x, tileCoords.y);

                        //show move options
                        unhighlightAll();
                        highlight(selectedUnit, 1);

                        this.highlightedFriendlyUnit = selectedUnit;

                        moveOptions = selectedUnit.getValidMoves(tileCoords.x, tileCoords.y, battlefield);

                        foreach (Coord moveOption in moveOptions)
                        {
                            highlight(battlefield.map[moveOption.x, moveOption.y].Peek().gameObject, 1);
                        }

                        this.targetableUnits = selectedUnit.getTargets(tileCoords.x, tileCoords.y, battlefield, this.character);

                        foreach (Coord targetableUnit in targetableUnits)
                        {
                            int colorIndex = selectedUnit is Cleric ? 3 : 2;
                            highlight(battlefield.units[targetableUnit.x, targetableUnit.y], colorIndex);
                            highlight(battlefield.map[targetableUnit.x, targetableUnit.y].Peek().gameObject, colorIndex);
                        }
                    }
                    else
                    {
                        //Selected enemy unit. Show unit and its move options.
                        unhighlightAll();
                        highlight(selectedUnit, 2);

                        moveOptions = selectedUnit.getValidMoves(tileCoords.x, tileCoords.y, battlefield);

                        foreach (Coord moveOption in moveOptions)
                        {
                            highlight(battlefield.map[moveOption.x, moveOption.y].Peek().gameObject, 2);
                        }

                        this.targetableUnits = selectedUnit.getTargets(tileCoords.x, tileCoords.y, battlefield, selectedUnit.getCharacter(battlefield));

                        foreach (Coord targetableUnit in targetableUnits)
                        {
                            int colorIndex = selectedUnit is Cleric ? 3 : 2;
                            highlight(battlefield.units[targetableUnit.x, targetableUnit.y], colorIndex);
                            highlight(battlefield.map[targetableUnit.x, targetableUnit.y].Peek().gameObject, colorIndex);
                        }
                    }
                }
                else if (selectedItem == null)
                {
                    //Clicked on empty space! Nbd, don't do anything.
                    Debug.Log("Clicked on empty space");
                }
                else
                {
                    Debug.LogWarning("Item of unrecognized type clicked on.");
                }
            }
        }
Example #6
0
        public void getMovePhase(Move currentMove)
        {
            RaycastHit hit;
            Ray        ray = Camera.main.ScreenPointToRay(Input.mousePosition);

            if (Physics.Raycast(ray, out hit, 1000.0f))
            {
                Vector3Int       tileCoords   = Util.WorldToGrid(hit.transform.position);
                IBattlefieldItem selectedItem = battlefield.battlefieldItemAt(tileCoords.x, tileCoords.y, tileCoords.z);
                if (selectedItem is Tile)
                {
                    //We selected a tile! lets move to it
                    if (moveOptions.Any(move => (move.x == tileCoords.x && move.y == tileCoords.y)))
                    {
                        currentMove.to = new Coord(tileCoords.x, tileCoords.y);
                    }
                    else
                    {
                        //Clicked on invalid tile, restart.
                        currentMove.from = null;
                    }
                    unhighlightAll();
                }
                else if (selectedItem == null)
                {
                    //Clicked on empty space, deselect
                    unhighlightAll();
                    currentMove.from = null;
                }
                else if (selectedItem is Unit)
                {
                    Unit selectedUnit = selectedItem as Unit;

                    if (highlightedFriendlyUnit == selectedUnit)
                    {
                        //clicked on the same unit, return the "do nothing" move
                        unhighlightAll();
                        currentMove.to = new Coord(tileCoords.x, tileCoords.y);
                    }
                    else if (selectedUnit.getCharacter(battlefield) == this.character && !(highlightedFriendlyUnit is Cleric))
                    {
                        //Clicked on a friendly unit. Deselect the current one.
                        unhighlightAll();
                        currentMove.from = null;
                    }
                    else
                    {
                        //Clicked on a hostile unit! fight!
                        if (targetableUnits.Any(coord => coord.x == tileCoords.x && coord.y == tileCoords.y))
                        {
                            currentMove.to = new Coord(tileCoords.x, tileCoords.y);
                        }
                        else
                        {
                            //Clicked on invalid enemy unit, restart.
                            currentMove.from = null;
                        }
                        unhighlightAll();
                    }
                }
                else
                {
                    Debug.LogWarning("Item of unrecognized type clicked on.");
                }
            }
        }
Example #7
0
        // Poor man's state machine. in retrospect i have no idea why i didn't use a proper one. oh well, next game.
        async void Update()
        {
            switch (battleStage)
            {
            case BattleLoopStage.Initial:
                if (!battleStageChanged)
                {
                    break;
                }
                battleStageChanged = false;

                playBgm();

                turnPlayerText.text =
                    "Battle objective:\n" +
                    objective.getName();
                turnPlayerText.enabled       = true;
                turnChangeBackground.enabled = true;
                await Task.Delay(3000);

                advanceBattleStage();
                break;

            case BattleLoopStage.Pick:
                advanceBattleStage();
                turnPlayerText.enabled       = false;
                turnChangeBackground.enabled = false;

                break;

            case BattleLoopStage.BattleLoopStart:
                if (!battleStageChanged)
                {
                    break;
                }
                battleStageChanged = false;
                //Check for cutscenes every start phase
                await runAppropriateCutscenes();

                advanceBattleStage();
                break;

            case BattleLoopStage.TurnChange:
                //If we've already entered this we're awaiting. Don't call it again every frame.
                if (!battleStageChanged)
                {
                    break;
                }
                battleStageChanged = false;

                currentCharacter    = (currentCharacter + 1) % level.characters.Length;
                turnPlayerText.text =
                    level.characters[currentCharacter].name + "'s turn\n" +
                    "Turns remaining:  " + (objective.maxHalfTurns - halfTurnsElapsed);
                turnPlayerText.enabled       = true;
                turnChangeBackground.enabled = true;

                await Task.Delay(1000);

                advanceBattleStage();
                break;

            case BattleLoopStage.TurnChangeEnd:
                turnPlayerText.enabled       = false;
                turnChangeBackground.enabled = false;
                advanceBattleStage();
                break;

            case BattleLoopStage.UnitSelection:
                advanceBattleStage();
                break;

            case BattleLoopStage.ActionSelection:
                //If we've already entered this we're awaiting. Don't call it again every frame.
                if (!battleStageChanged)
                {
                    break;
                }
                battleStageChanged = false;

                //The getMove function returns null if no move should be made,
                //possibly in the event of the selection loop being interrupted by a manually ended turn
                Move move = await level.characters[currentCharacter].getMove();
                //Since no move occurs, nothing else needs to be done this turn (since nothing changed).
                if (move == null)
                {
                    break;
                }

                Unit ourUnit = battlefield.units[move.from.x, move.from.y];

                if (ourUnit == null)
                {
                    Debug.LogWarning("In BattleControl.update(), a move originated from a nonexistent unit, probably due to an ended turn.");
                    break;
                }

                IBattlefieldItem selectedItem = battlefield.battlefieldItemAt(move.to.x, move.to.y);
                if (move.from.Equals(move.to))
                {
                    //This is the null move. just do nothing!
                    ourUnit.hasMovedThisTurn = true;
                    ourUnit.setHasAttackedThisTurn(true);
                    ourUnit.greyOut();
                }
                else if (selectedItem is Tile)
                {
                    //We selected a tile! lets move to it
                    await moveUnit(ourUnit, move.to);

                    if (ourUnit.getTargets(move.to.x, move.to.y, battlefield, level.characters[currentCharacter]).Count == 0)
                    {
                        ourUnit.greyOut();
                        ourUnit.setHasAttackedThisTurn(true);
                    }
                }
                else if (selectedItem is Unit)
                {
                    //Targeted a hostile unit! fight!
                    Unit selectedUnit = selectedItem as Unit;

                    await rotateUnit(ourUnit, battlefield.getUnitCoords(selectedUnit));

                    bool defenderDefeated = await ourUnit.doBattleWith(
                        selectedUnit,
                        battlefield.map[move.to.x, move.to.y].Peek(),
                        battlefield);

                    if (!defenderDefeated && (selectedItem is MeleeUnit) && (ourUnit is MeleeUnit))
                    {
                        await rotateUnit(selectedUnit, battlefield.getUnitCoords(ourUnit));

                        //Counterattack applied only when both units are Melee
                        await selectedUnit.doBattleWith(
                            ourUnit,
                            battlefield.map[move.from.x, move.from.y].Peek(),
                            battlefield);
                    }

                    //Re-grey model if needed... I'm regretting my desire to make the health ui manager stateless :p
                    if (ourUnit is HealerUnit)
                    {
                        if ((selectedUnit.hasMovedThisTurn &&
                             selectedUnit.getTargets(move.to.x, move.to.y, battlefield, level.characters[currentCharacter]).Count == 0) ||
                            selectedUnit.getHasAttackedThisTurn())
                        {
                            selectedUnit.greyOut();
                        }
                    }

                    ourUnit.setHasAttackedThisTurn(true);
                    // await Task.Delay(TimeSpan.FromMilliseconds(turnDelayMs));
                }
                else
                {
                    Debug.LogWarning("Item of unrecognized type clicked on.");
                }


                ourUnit.hasMovedThisTurn = true;

                await runAppropriateCutscenes();

                //Check if we eliminated the last unit.
                await checkWinAndLose();

                // Update AI capture point if Intercept mission
                if (objective is InterceptObjective)
                {
                    foreach (Character c in level.characters)
                    {
                        if (c.agent is DefendAgent)
                        {
                            (c.agent as DefendAgent).capturePoint = battlefield.getUnitCoords((objective as InterceptObjective).vips[0]);
                        }
                    }
                }

                //If all of our units have moved advance. Otherwise, go back to unit selection.
                if (battlefield.charactersUnits[level.characters[currentCharacter]].All(unit => {
                    //I know this looks inelegant but it avoid calling getUnitCoords if necessary
                    if (!unit.hasMovedThisTurn)
                    {
                        return(false);
                    }
                    else if (unit.getHasAttackedThisTurn())
                    {
                        return(true);
                    }
                    else
                    {
                        Coord coord = battlefield.getUnitCoords(unit);
                        return(unit.getTargets(coord.x, coord.y, battlefield, level.characters[currentCharacter]).Count == 0);
                    }
                }))
                {
                    advanceBattleStage();
                }
                else
                {
                    setBattleLoopStage(BattleLoopStage.UnitSelection);
                }

                break;

            case BattleLoopStage.EndTurn:
                //If we've already entered this we're awaiting. Don't call it again every frame.
                if (!battleStageChanged)
                {
                    break;
                }
                battleStageChanged = false;

                //Check cutscenes every end phase
                await runAppropriateCutscenes();

                foreach (Unit unit in battlefield.charactersUnits[level.characters[currentCharacter]])
                {
                    Coord coord = battlefield.getUnitCoords(unit);
                    Tile  tile  = battlefield.map[coord.x, coord.y].Peek();
                    await checkTile(tile, unit);

                    unit.hasMovedThisTurn = false;
                    unit.setHasAttackedThisTurn(false);
                }

                bool endGame = await checkWinAndLose();

                if (!endGame)
                {
                    advanceBattleStage();
                }

                halfTurnsElapsed++;

                break;
            }
        }
        public async Task <Move> getSelectionPhase(Move currentMove)
        {
            //Await player input. But. Unity doesn't really support async await.
            //I'm feeling kinda dumb for not just learning coroutines. Next time!
            while (!Input.GetButtonDown("Select"))
            {
                await Task.Delay(1);
            }

            RaycastHit hit;
            Ray        ray = Camera.main.ScreenPointToRay(Input.mousePosition);

            if (Physics.Raycast(ray, out hit, 1000.0f))
            {
                Vector3Int       tileCoords   = Util.WorldToGrid(hit.transform.position);
                IBattlefieldItem selectedItem = battlefield.battlefieldItemAt(tileCoords.x, tileCoords.y, tileCoords.z);

                if (selectedItem is Tile)
                {
                    //Selected a tile, show info abt that tile
                    //TODO: Show info about tile if a tile is clicked
                    Tile selectedTile = selectedItem as Tile;
                    highlightSingleObject(selectedTile.gameObject);

                    //This method will get called again because we didn't find a valid selection
                }
                else if (selectedItem is Unit)
                {
                    Unit selectedUnit = selectedItem as Unit;

                    if (selectedUnit.getCharacter(battlefield) == this.character && !selectedUnit.hasMovedThisTurn)
                    {
                        //Selected friendly unit. Valid selection, store selection coords.
                        currentMove.fromX = tileCoords.x;
                        currentMove.fromY = tileCoords.y;

                        //show move options
                        highlightSingleObject(selectedUnit.gameObject, 1);
                        this.highlightedFriendlyUnit = selectedUnit;

                        moveOptions = selectedUnit.getValidMoves(tileCoords.x, tileCoords.y, battlefield);
                        foreach (Coord moveOption in moveOptions)
                        {
                            highlightMultipleObjects(battlefield.map[moveOption.x, moveOption.y].Peek().gameObject);
                        }

                        this.highlightedEnemyUnits = selectedUnit.getTargets(tileCoords.x, tileCoords.y, battlefield, this.character);
                        foreach (Unit targetableUnit in highlightedEnemyUnits)
                        {
                            highlightMultipleObjects(targetableUnit.gameObject, 2);
                        }
                    }
                    else
                    {
                        //Selected enemy unit. Show unit and its move options.
                        //TODO: highlight enemy's valid move tiles. don't assign currentMove.fromX or fromY, bc not valid advancement criteria
                    }
                }
                else if (selectedItem == null)
                {
                    //Clicked on empty space! Nbd, don't do anything.
                    Debug.Log("Clicked on empty space");
                }
                else
                {
                    Debug.LogWarning("Item of unrecognized type clicked on.");
                }
            }

            return(currentMove);
        }
        public async Task <Move> getMovePhase(Move currentMove)
        {
            //Await player input.
            while (!Input.GetButtonDown("Select"))
            {
                await Task.Delay(1);
            }

            RaycastHit hit;
            Ray        ray = Camera.main.ScreenPointToRay(Input.mousePosition);

            if (Physics.Raycast(ray, out hit, 1000.0f))
            {
                Vector3Int       tileCoords   = Util.WorldToGrid(hit.transform.position);
                IBattlefieldItem selectedItem = battlefield.battlefieldItemAt(tileCoords.x, tileCoords.y, tileCoords.z);
                if (selectedItem is Tile)
                {
                    //We selected a tile! lets move to it
                    if (moveOptions.Any(move => (move.x == tileCoords.x && move.y == tileCoords.y)))
                    {
                        currentMove.toX = tileCoords.x;
                        currentMove.toY = tileCoords.y;

                        deselectMoveOptions();
                    }
                }
                else if (selectedItem == null)
                {
                    //Clicked on empty space, deselect
                    deselectMoveOptions();
                    currentMove = goBackToSelectionPhase();
                }
                else if (selectedItem is Unit)
                {
                    Unit selectedUnit = selectedItem as Unit;

                    if (highlightedFriendlyUnit == selectedUnit)
                    {
                        //clicked on the same unit, deselect
                        deselectMoveOptions();
                        currentMove = goBackToSelectionPhase();
                    }
                    else if (selectedUnit.getCharacter(battlefield) == this.character)
                    {
                        //Clicked on a friendly unit. Deselect the current one.
                        deselectMoveOptions();
                        currentMove = goBackToSelectionPhase();
                    }
                    else
                    {
                        //Clicked on a hostile unit! fight!
                        deselectMoveOptions();
                        currentMove.toX = tileCoords.x;
                        currentMove.toY = tileCoords.y;
                    }
                }
                else
                {
                    Debug.LogWarning("Item of unrecognized type clicked on.");
                }
            }

            return(currentMove);
        }
Example #10
0
        // Update is called once per frame
        async void Update()
        {
            switch (battleStage)
            {
            case BattleLoopStage.Initial:
                if (!cutscene.inProgress)
                {
                    advanceBattleStage();
                }
                break;

            case BattleLoopStage.Pick:
                //TODO This is temp just for testing until pick phase gets built.
                addUnit(UnitType.Knight, level.characters[0], 0, 0);
                addUnit(UnitType.Knight, level.characters[0], 1, 0);
                addUnit(UnitType.Knight, level.characters[0], 0, 1);
                addUnit(UnitType.Knight, level.characters[1], 3, 7);
                addUnit(UnitType.Knight, level.characters[1], 4, 7);
                foreach (Unit unit in battlefield.charactersUnits[level.characters[1]])
                {
                    Renderer rend = unit.gameObject.GetComponent <Renderer>();
                    rend.material.shader = Shader.Find("_Color");
                    rend.material.SetColor("_Color", Color.green);
                    rend.material.shader = Shader.Find("Specular");
                    rend.material.SetColor("_SpecColor", Color.green);
                }

                advanceBattleStage();
                break;

            case BattleLoopStage.BattleLoopStart:
                advanceBattleStage();
                break;

            case BattleLoopStage.TurnChange:
                //There's probably a less fragile way of doing this. It's just to make sure this call only happens once per turn loop.
                if (!turnPlayerText.enabled)
                {
                    currentCharacter             = (currentCharacter + 1) % level.characters.Length;
                    turnPlayerText.text          = level.characters[currentCharacter].name + "'s turn";
                    turnPlayerText.enabled       = true;
                    turnChangeBackground.enabled = true;
                    Util.setTimeout(advanceBattleStage, 1000);
                }
                break;

            case BattleLoopStage.TurnChangeEnd:
                turnPlayerText.enabled       = false;
                turnChangeBackground.enabled = false;
                advanceBattleStage();
                break;

            case BattleLoopStage.UnitSelection:
                //Player input. LMB
                if (Input.GetButtonDown("Select"))
                {
                    RaycastHit hit;
                    Ray        ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                    if (Physics.Raycast(ray, out hit, 1000.0f))
                    {
                        Vector3Int       tileCoords   = Util.WorldToGrid(hit.transform.position);
                        IBattlefieldItem selectedItem = battlefield.battlefieldItemAt(tileCoords.x, tileCoords.y, tileCoords.z);
                        if (selectedItem is Tile)
                        {
                            //Selected a tile, show info abt that tile
                            //TODO: Show info about tile if a tile is clicked
                            Tile selectedTile = selectedItem as Tile;
                            highlightSingleObject(selectedTile.gameObject);
                        }
                        else if (selectedItem is Unit)
                        {
                            Unit selectedUnit = selectedItem as Unit;

                            if (selectedUnit.getCharacter(battlefield) == level.characters[currentCharacter] && !selectedUnit.hasMovedThisTurn)
                            {
                                //Selected friendly unit. show move options.
                                highlightSingleObject(selectedUnit.gameObject, 1);
                                this.highlightedFriendlyUnit = selectedUnit;

                                moveOptions = selectedUnit.getValidMoves(tileCoords.x, tileCoords.y, battlefield);
                                foreach (Coord moveOption in moveOptions)
                                {
                                    highlightMultipleObjects(battlefield.map[moveOption.x, moveOption.y].Peek().gameObject);
                                }

                                this.highlightedEnemyUnits = selectedUnit.getTargets(tileCoords.x, tileCoords.y, battlefield, level.characters[currentCharacter]);
                                foreach (Unit targetableUnit in highlightedEnemyUnits)
                                {
                                    highlightMultipleObjects(targetableUnit.gameObject, 2);
                                }

                                advanceBattleStage();
                            }
                            else
                            {
                                //Selected enemy unit. Show unit and its move options.
                                //TODO: highlight enemy's valid move tiles.
                            }
                        }
                        else if (selectedItem == null)
                        {
                            //Clicked on empty space! Nbd, don't do anything.
                            Debug.Log("Clicked on empty space");
                        }
                        else
                        {
                            Debug.LogWarning("Item of unrecognized type clicked on.");
                        }
                    }
                }


                //If player has selected a move:
                //TODO play the animation
                break;

            case BattleLoopStage.ActionSelection:
                if (Input.GetButtonDown("Select"))
                {
                    RaycastHit hit;
                    Ray        ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                    if (Physics.Raycast(ray, out hit, 1000.0f))
                    {
                        Vector3Int       tileCoords   = Util.WorldToGrid(hit.transform.position);
                        IBattlefieldItem selectedItem = battlefield.battlefieldItemAt(tileCoords.x, tileCoords.y, tileCoords.z);
                        if (selectedItem is Tile)
                        {
                            //We selected a tile! lets move to it
                            if (moveOptions.Any(move => (move.x == tileCoords.x && move.y == tileCoords.y)))
                            {
                                moveUnit(highlightedFriendlyUnit, tileCoords);
                                deselectMoveOptions();

                                highlightedFriendlyUnit.hasMovedThisTurn = true;

                                if (battlefield.charactersUnits[level.characters[currentCharacter]].All(unit => unit.hasMovedThisTurn))
                                {
                                    advanceBattleStage();
                                }
                                else
                                {
                                    this.battleStage = BattleLoopStage.UnitSelection;
                                }
                            }
                        }
                        else if (selectedItem == null)
                        {
                            //Clicked on empty space, deselect
                            deselectMoveOptions();
                            battleStage = BattleLoopStage.UnitSelection;
                        }
                        else if (selectedItem is Unit)
                        {
                            Unit selectedUnit = selectedItem as Unit;

                            if (highlightedFriendlyUnit == selectedUnit)
                            {
                                //clicked on the same unit, deselect
                                deselectMoveOptions();
                                battleStage = BattleLoopStage.UnitSelection;
                            }
                            else if (selectedUnit.getCharacter(battlefield) == level.characters[currentCharacter])
                            {
                                //Clicked on a friendly unit. Deselect the current one.
                                deselectMoveOptions();
                                battleStage = BattleLoopStage.UnitSelection;
                            }
                            else
                            {
                                //Clicked on a hostile unit! fight!
                                if (highlightedEnemyUnits.Contains(selectedUnit))
                                {
                                    bool defenderDefeated = highlightedFriendlyUnit.doBattleWith(
                                        selectedUnit,
                                        battlefield.map[tileCoords.x, tileCoords.y].Peek(),
                                        battlefield);

                                    await Task.Delay(TimeSpan.FromMilliseconds(250));

                                    if (defenderDefeated)
                                    {
                                        highlightedEnemyUnits.RemoveAll(units => units == null);
                                    }
                                    else
                                    {
                                        //Counterattack
                                        Coord unitCoords = battlefield.getUnitCoords(highlightedFriendlyUnit);
                                        selectedUnit.doBattleWith(
                                            highlightedFriendlyUnit,
                                            battlefield.map[unitCoords.x, unitCoords.y].Peek(),
                                            battlefield);
                                    }
                                    checkWinAndLose();

                                    highlightedFriendlyUnit.hasMovedThisTurn = true;
                                    await Task.Delay(TimeSpan.FromMilliseconds(250));

                                    deselectMoveOptions();

                                    //If all of our units have moved advance. Otherwise, go back to unit selection.
                                    if (battlefield.charactersUnits[level.characters[currentCharacter]].All(unit => unit.hasMovedThisTurn))
                                    {
                                        advanceBattleStage();
                                    }
                                    else
                                    {
                                        this.battleStage = BattleLoopStage.UnitSelection;
                                    }
                                }
                            }
                        }
                        else
                        {
                            Debug.LogWarning("Item of unrecognized type clicked on.");
                        }
                    }
                }

                break;

            case BattleLoopStage.EndTurn:
                foreach (Unit unit in battlefield.charactersUnits[level.characters[currentCharacter]])
                {
                    unit.hasMovedThisTurn = false;
                }

                checkWinAndLose();
                advanceBattleStage();
                break;
            }
        }
        // Update is called once per frame
        async void Update()
        {
            switch (battleStage)
            {
            case BattleLoopStage.Initial:
                if (!cutscene.inProgress)
                {
                    advanceBattleStage();
                }
                break;

            case BattleLoopStage.Pick:
                //TODO This is temp just for testing until pick phase gets built.
                addUnit(UnitType.Knight, level.characters[0], 0, 0);
                addUnit(UnitType.Knight, level.characters[0], 1, 0);
                addUnit(UnitType.Knight, level.characters[0], 0, 1);
                addUnit(UnitType.Knight, level.characters[1], 3, 7);
                addUnit(UnitType.Knight, level.characters[1], 4, 7);
                foreach (Unit unit in battlefield.charactersUnits[level.characters[1]])
                {
                    Renderer rend = unit.gameObject.GetComponent <Renderer>();
                    rend.material.shader = Shader.Find("_Color");
                    rend.material.SetColor("_Color", Color.green);
                    rend.material.shader = Shader.Find("Specular");
                    rend.material.SetColor("_SpecColor", Color.green);
                }

                advanceBattleStage();
                break;

            case BattleLoopStage.BattleLoopStart:
                advanceBattleStage();
                break;

            case BattleLoopStage.TurnChange:
                //There's probably a less fragile way of doing this. It's just to make sure this call only happens once per turn loop.
                if (!turnPlayerText.enabled)
                {
                    currentCharacter             = (currentCharacter + 1) % level.characters.Length;
                    turnPlayerText.text          = level.characters[currentCharacter].name + "'s turn";
                    turnPlayerText.enabled       = true;
                    turnChangeBackground.enabled = true;
                    Util.setTimeout(advanceBattleStage, 1000);
                }
                break;

            case BattleLoopStage.TurnChangeEnd:
                turnPlayerText.enabled       = false;
                turnChangeBackground.enabled = false;
                advanceBattleStage();
                break;

            case BattleLoopStage.UnitSelection:
                advanceBattleStage();
                break;

            case BattleLoopStage.ActionSelection:
                //If we've already entered this we're awaiting. Don't call it again this frame.
                if (!battleStageChanged)
                {
                    break;
                }
                battleStageChanged = false;

                //Character.getMove() is responsible for validation so we assume the move to be legal
                Move             move         = await level.characters[currentCharacter].getMove();
                Unit             ourUnit      = battlefield.units[move.fromX, move.fromY];
                IBattlefieldItem selectedItem = battlefield.battlefieldItemAt(move.toX, move.toY);

                if (selectedItem is Tile)
                {
                    //We selected a tile! lets move to it
                    moveUnit(ourUnit, move.toX, move.toY);
                }
                else if (selectedItem is Unit)
                {
                    //Targeted a hostile unit! fight!
                    Unit selectedUnit = selectedItem as Unit;

                    bool defenderDefeated = ourUnit.doBattleWith(
                        selectedUnit,
                        battlefield.map[move.toX, move.toY].Peek(),
                        battlefield);

                    await Task.Delay(TimeSpan.FromMilliseconds(250));

                    if (!defenderDefeated)
                    {
                        //Counterattack
                        selectedUnit.doBattleWith(
                            ourUnit,
                            battlefield.map[move.fromX, move.fromY].Peek(),
                            battlefield);
                    }

                    await Task.Delay(TimeSpan.FromMilliseconds(250));
                }
                else
                {
                    Debug.LogWarning("Item of unrecognized type clicked on.");
                }

                checkWinAndLose();

                //If all of our units have moved advance. Otherwise, go back to unit selection.
                ourUnit.hasMovedThisTurn = true;
                if (battlefield.charactersUnits[level.characters[currentCharacter]].All(unit => unit.hasMovedThisTurn))
                {
                    advanceBattleStage();
                }
                else
                {
                    setBattleLoopStage(BattleLoopStage.UnitSelection);
                }

                break;

            case BattleLoopStage.EndTurn:
                foreach (Unit unit in battlefield.charactersUnits[level.characters[currentCharacter]])
                {
                    unit.hasMovedThisTurn = false;
                }

                checkWinAndLose();
                advanceBattleStage();
                break;
            }
        }
Example #12
0
        public async Task getMovePhase(Move currentMove)
        {
            //Await player input.
            while (!Input.GetButtonDown("Select"))
            {
                await Task.Delay(1);
            }

            RaycastHit hit;
            Ray        ray = Camera.main.ScreenPointToRay(Input.mousePosition);

            if (Physics.Raycast(ray, out hit, 1000.0f))
            {
                Vector3Int       tileCoords   = Util.WorldToGrid(hit.transform.position);
                IBattlefieldItem selectedItem = battlefield.battlefieldItemAt(tileCoords.x, tileCoords.y, tileCoords.z);
                if (selectedItem is Tile)
                {
                    //We selected a tile! lets move to it
                    if (moveOptions.Any(move => (move.x == tileCoords.x && move.y == tileCoords.y)))
                    {
                        currentMove.to = new Coord(tileCoords.x, tileCoords.y);
                    }
                    else
                    {
                        //Clicked on invalid tile, restart.
                        currentMove.from = null;
                    }
                    unhighlightAll();
                }
                else if (selectedItem == null)
                {
                    //Clicked on empty space, deselect
                    unhighlightAll();
                    currentMove.from = null;
                }
                else if (selectedItem is Unit)
                {
                    Unit selectedUnit = selectedItem as Unit;

                    if (highlightedFriendlyUnit == selectedUnit)
                    {
                        //clicked on the same unit, deselect
                        unhighlightAll();
                        currentMove.from = null;
                    }
                    else if (selectedUnit.getCharacter(battlefield) == this.character)
                    {
                        //Clicked on a friendly unit. Deselect the current one.
                        unhighlightAll();
                        currentMove.from = null;
                    }
                    else
                    {
                        //Clicked on a hostile unit! fight!
                        if (highlightedEnemyUnits.Any(coord => coord.x == tileCoords.x && coord.y == tileCoords.y))
                        {
                            currentMove.to = new Coord(tileCoords.x, tileCoords.y);
                        }
                        else
                        {
                            //Clicked on invalid enemy unit, restart.
                            currentMove.from = null;
                        }
                        unhighlightAll();
                    }
                }
                else
                {
                    Debug.LogWarning("Item of unrecognized type clicked on.");
                }
            }

            //Wait for the mouse down event to un-fire. This avoids an infinite loop in the next condition.
            while (!Input.GetButtonUp("Select"))
            {
                await Task.Delay(1);
            }
        }