Exemplo n.º 1
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;
            }
        }
Exemplo n.º 2
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;
            }
        }
Exemplo n.º 3
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;
            }
        }