// maybe it should be up to the battle manager to store good guys and bad guys? // Use this for initialization void Start() { // if we have a gameboy game, delete this object if (Toolbox.Instance.battleScene != null && Toolbox.Instance.battleScene != "") { Destroy(this); } // The battle manager contains a list of scripts as attached to objects // INIT will get the list of objects and do some setup // DECIDE ON TURN will call the queue and toggle at this point // DECIDE ATTACK will simply call the units attack // PERFORM COMMANDS will perform the attack's commands // Check conditions will just determine if we are done with the round // WIN will fire the winning conditions off // LOSE will fire the losing conditions off // Battle Manager // - START / INIT // - DECIDE WHOSE TURN IT IS (speed and turn queue? - for now we'll just swap off in a simple turn based queue) // - DECIDE ATTACK (random if enemy) // - PERFORM COMMANDS // - CHECK CONDITIONS // - WIN // - LOSE currentState = BATTLE_STATES.START; sceneInit = GameObject.Find("LoadScene").GetComponent <LoadBattleScene> (); Camera.main.orthographicSize = 2; Camera.main.transform.position = new Vector3(-4.30f, -1.50f, -10); }
/// <summary> /// Displays the attack in the text panel /// </summary> /// <returns>The attack.</returns> private IEnumerator displayAttack() { // wait for a couple of seconds and then we'll change the state attackTextPanel.SetActive(true); displayAttackText.text = currentPlayerTurn.playerName + " " + attackDone; yield return(new WaitForSeconds(2)); currentState = BATTLE_STATES.CHECK_CONDITIONS; attackTextPanel.SetActive(false); Toolbox.Instance.isLocked = false; }
/// <summary> /// Initializes the battle by passing the battle data received from the server, /// and a callback function to notify the caller when it ends. /// /// </summary> /// <param name="battleData">A battle data</param> /// <param name="OnBattleEnds">A callback</param> public void Init(BattleData battleData, Action <bool> OnBattleEnds) { this._onBattleEnds = OnBattleEnds; this._battleData = battleData; _referenceService = ReferenceService.GetInstance(); _playerService = PlayerService.GetInstance(); _uiManager = GameObject.FindGameObjectWithTag("UIManager").GetComponent <UIManager>(); Feedback.gameObject.SetActive(false); Feedback.text = ""; InitNPC(); InitAvatar(); _npcCurrentState = BATTLE_STATES.READY_SET_GO; _isBattleOn = true; }
/// <summary> /// Update this instance. Controls our state machine. Uses ToolBox /// </summary> // Update is called once per frame void Update() { // if we are locked, can't go forward if (Toolbox.Instance.isLocked) { return; } // lock our toolbox Toolbox.Instance.isLocked = true; Toolbox toolboxInstance = Toolbox.Instance; // switch over our battle state switch (currentState) { // load our scene and move our battle forward case BATTLE_STATES.START: Debug.Log("We are in start here" + turnsLoaded); if (!turnsLoaded) { turnsLoaded = true; sceneInit.LoadTurns(); Toolbox.Instance.isLocked = false; } else { sceneInit.LoadBattleSceneItems(); currentState = BATTLE_STATES.DECIDE_TURN; battleTurnOrder = sceneInit.turnOrder; Toolbox.Instance.isLocked = false; } break; // decide whose turn it is case BATTLE_STATES.DECIDE_TURN: Debug.Log("We are deciding turn : "); currentState = BATTLE_STATES.DECIDE_ATTACK; // pick the turn person currentPlayerTurn = battleTurnOrder [currentTurn]; // update our current turn to the next player in the queue // and cycle if we are at the end. currentTurn++; if (currentTurn >= battleTurnOrder.Count) { currentTurn = 0; } turnFinished = false; waitingForTurn = false; Toolbox.Instance.isLocked = false; break; // decide which attack we are using on whoever's turn it is case BATTLE_STATES.DECIDE_ATTACK: // skip this turn if our player has no health if (currentPlayerTurn.isPlayerCharacter && currentPlayerTurn.GetComponent <PlayerHealth> ().currentHealth <= 0) { waitingForTurn = true; currentState = BATTLE_STATES.CHECK_CONDITIONS; Toolbox.Instance.isLocked = false; } else if (!currentPlayerTurn.isPlayerCharacter && currentPlayerTurn.GetComponent <EnemyHealth> ().currentHealth <= 0) { waitingForTurn = true; currentState = BATTLE_STATES.CHECK_CONDITIONS; Toolbox.Instance.isLocked = false; } // get our battle manager if we are a good guy. // Otherwise, perform an attack if we are a bad guy if (!waitingForTurn) { waitingForTurn = true; turnFinished = false; Debug.Log("Whose turn is it? : " + currentPlayerTurn.name + " " + currentPlayerTurn.isPlayerCharacter); if (currentPlayerTurn.isPlayerCharacter) { // get their battle mode and start gaming currentPlayerTurn.gameObject.GetComponent <BattleMenu> ().isMyTurn = true; } // otherwise, if it is not my turn, enemy attack! else { StartCoroutine(currentPlayerTurn.gameObject.GetComponent <EnemyAttack> ().Attack()); } } if (turnFinished) { currentState = BATTLE_STATES.PERFORM_COMMANDS; Toolbox.Instance.isLocked = false; } break; // perform commands of the attack case BATTLE_STATES.PERFORM_COMMANDS: // let's do a little enum in here StartCoroutine(displayAttack()); break; // check the conditions of the battle - has someone won? is any unit // to be destroyed? case BATTLE_STATES.CHECK_CONDITIONS: bool playerStillAlive = false; bool enemyStillAlive = false; // if we have all of the enemies killed // if we have the player characters all dead.. Debug.Log("ALLIES LENGTH : " + teammates.Count + " ENEMIES LENGTH : " + enemies.Count); // check if any of our players are still alive // if all are dead, we've lost this battle foreach (var player in teammates) { if (player.playerHealth.currentHealth > 0) { playerStillAlive = true; } } if (!playerStillAlive) { currentState = BATTLE_STATES.LOSE; Toolbox.Instance.isLocked = false; break; } // check if any of our enemies are still alive - if all are dead // then we are done with this battle foreach (var player in enemies) { if (player.enemyHealth.currentHealth > 0) { enemyStillAlive = true; } } if (!enemyStillAlive) { currentState = BATTLE_STATES.WIN; Toolbox.Instance.isLocked = false; break; } // if we have all of the enemies killed // if we have the player characters all dead.. Debug.Log("ALLIES LENGTH : " + teammates.Count + " ENEMIES LENGTH : " + enemies.Count); // first check if the player characters are all dead // then check if the enemy characters are all dead Debug.Log("we are here in check condition"); // for each of the enemies in play - are we all dead? // for each of the players in play, are we all dead? currentState = BATTLE_STATES.DECIDE_TURN; Toolbox.Instance.isLocked = false; break; // if the player side has won, hooray! victory conditions and experience case BATTLE_STATES.WIN: toolboxInstance.sceneAlreadyLoaded = false; changeCharacterStates(); // load previous scene toolboxInstance.positionInLastScene = toolboxInstance.battlePosition; // enemy defeated GameObject enemyDefeated = GameObject.FindGameObjectWithTag("Enemy"); toolboxInstance.enemyDefeated = enemyDefeated.name; Destroy(enemyDefeated); // return to enemy position from last scene. SceneManager.LoadScene("OpeningScene"); break; // if the good side has lost, sad day. Penalties and teleport case BATTLE_STATES.LOSE: Debug.Log("we have lost"); toolboxInstance.sceneAlreadyLoaded = false; changeCharacterStates(); // spawn at least location? // what if the grue is still there? // we'll get this in a moment. SceneManager.LoadScene("OpeningScene"); break; // if we hit a non-existent case default: break; } }
/// <summary> /// Update this instance. Controls our state machine. Uses ToolBox /// </summary> // Update is called once per frame void Update() { // if we are locked, can't go forward if (Toolbox.Instance.isLocked) { return; } // lock our toolbox Toolbox.Instance.isLocked = true; Toolbox toolboxInstance = Toolbox.Instance; // switch over our battle state switch (currentState) { // load our scene and move our battle forward case BATTLE_STATES.START: playAgainChoiceMade = false; currentTurn = 0; // if we don't have turns loaded, load the turns if (!turnsLoaded) { sceneInit.LoadGameBoyTurns(); turnsLoaded = true; Toolbox.Instance.isLocked = false; } // if we have turns loaded, load the battle scene and move into deciding // whose turn it is else { sceneInit.LoadBattleSceneItems(); currentState = BATTLE_STATES.DECIDE_TURN; battleTurnOrder = sceneInit.turnOrder; Toolbox.Instance.isLocked = false; } break; // decide whose turn it is case BATTLE_STATES.DECIDE_TURN: Debug.Log("We are deciding turn " + currentTurn); currentState = BATTLE_STATES.DECIDE_ATTACK; // pick the turn person currentPlayerTurn = battleTurnOrder [currentTurn]; // update our current turn to the next player in the queue // and cycle if we are at the end. currentTurn++; if (currentTurn >= battleTurnOrder.Count) { currentTurn = 0; } turnFinished = false; waitingForTurn = false; Toolbox.Instance.isLocked = false; break; // decide which attack we are using on whoever's turn it is case BATTLE_STATES.DECIDE_ATTACK: // skip this turn if our player has no health if (currentPlayerTurn.isPlayerCharacter && currentPlayerTurn.GetComponent <GameBoyUnit> ().currentHealth <= 0) { waitingForTurn = true; currentState = BATTLE_STATES.LOSE; Toolbox.Instance.isLocked = false; } // if the current player is an enemy and is dead, victory! (for now - later on we'll just skip this turn // and add in a "CHECK" phase else if (!currentPlayerTurn.isPlayerCharacter && currentPlayerTurn.GetComponent <GameBoyUnit> ().currentHealth <= 0) { waitingForTurn = true; currentState = BATTLE_STATES.WIN; Toolbox.Instance.isLocked = false; } // get our battle manager if we are a good guy. // Otherwise, perform an attack if we are a bad guy if (!waitingForTurn) { waitingForTurn = true; turnFinished = false; if (currentPlayerTurn.isPlayerCharacter) { // get their battle mode and start gaming //currentPlayerTurn.gameObject.GetComponent<BattleMenu> ().isMyTurn = true; StartCoroutine(currentPlayerTurn.Attack()); } // otherwise, if it is not my turn, enemy attack! else { StartCoroutine(currentPlayerTurn.Attack()); } } // if the turn is finished, perform our commands if (turnFinished) { currentState = BATTLE_STATES.PERFORM_COMMANDS; Toolbox.Instance.isLocked = false; } break; // perform commands of the attack case BATTLE_STATES.PERFORM_COMMANDS: // let's do a little enum in here StartCoroutine(displayAttack()); break; // check the conditions of the battle - has someone won? is any unit // to be destroyed? case BATTLE_STATES.CHECK_CONDITIONS: bool playerStillAlive = true; bool enemyStillAlive = true; // if our player is dead, we have lost if (!playerStillAlive) { currentState = BATTLE_STATES.LOSE; Toolbox.Instance.isLocked = false; break; } // if our enemy is dead, we have won if (!enemyStillAlive) { currentState = BATTLE_STATES.WIN; Toolbox.Instance.isLocked = false; break; } // first check if the player characters are all dead // then check if the enemy characters are all dead Debug.Log("we are here in check condition"); // for each of the enemies in play - are we all dead? // for each of the players in play, are we all dead? currentState = BATTLE_STATES.DECIDE_TURN; Toolbox.Instance.isLocked = false; break; // if the player side has won, hooray! victory conditions and experience case BATTLE_STATES.WIN: // let's add that experience to our tally // enemy defeated GameObject enemyDefeated = GameObject.FindGameObjectWithTag("Enemy"); gainedExperience += enemyDefeated.GetComponent <GameBoyUnit> ().experience; // if we have received a choice - we can choose to play again if (playAgainChoiceMade) { // check if we are gambling or continuing on. if (gambling) { currentState = BATTLE_STATES.START; Toolbox.Instance.isLocked = false; } // we have decided we are done gambling on experience else if (!gambling) { currentState = BATTLE_STATES.END; Toolbox.Instance.isLocked = false; } } // display character selection panel else { displayCharacterSelectionPanel(); } break; // if the good side has lost, sad day. Penalties and teleport case BATTLE_STATES.LOSE: currentState = BATTLE_STATES.END; Toolbox.Instance.isLocked = false; break; case BATTLE_STATES.CHARACTER_SELECTION: break; case BATTLE_STATES.END: // load previous scene toolboxInstance.positionInLastScene = toolboxInstance.battlePosition; toolboxInstance.sceneAlreadyLoaded = false; GameObject.FindGameObjectWithTag("PlayerCharacter").GetComponent <PlayerUnit> ().playerExperience += gainedExperience; // spawn at least location? // what if the grue is still there? // we'll get this in a moment. SceneManager.LoadScene("OpeningScene"); break; // if we hit a non-existent case default: break; } }
/// <summary> /// Responsible for moving the state machine forward, updating UI elements, /// and displaying animations when needed. /// </summary> private void Update() { if (_isBattleOn) { if (_playerService.GetMaxEnergyLevel() != 0) { Lives.size = (float)_playerService.GetEnergyLevel() / _playerService.GetMaxEnergyLevel(); } if (_maximumNPCEnergyLevel != 0) { float fill = _currentNPCEnergyLevel / _maximumNPCEnergyLevel; NPCHealthSlider.maxValue = _maximumNPCEnergyLevel; NPCHealthSlider.value = _currentNPCEnergyLevel; Color c = Color.Lerp(Color.red, Color.green, fill); NPCHealthSliderFillImage.color = c; } if (_showFeedback) { _feedbackTimeCounter += Time.deltaTime; Feedback.gameObject.SetActive(true); if (_feedbackTimeCounter >= SHOW_FEEDBACK_TIMEOUT) { _showFeedback = false; Feedback.gameObject.SetActive(false); _feedbackTimeCounter = 0f; } } // Check NPC and Player healths if ((_currentNPCEnergyLevel <= 0 || _playerService.GetEnergyLevel() <= 0) && _isBattleOn) { // Battle is over // Go to resolution StartCoroutine(BattleEnds()); } else { // Handle NPC State machine switch (_npcCurrentState) { case BATTLE_STATES.READY_SET_GO: Feedback.gameObject.SetActive(true); Feedback.text = _battleStartCountDown.ToString(); Feedback.color = Color.blue; _battleStartCounter += Time.deltaTime; if (_battleStartCounter >= 1) { _battleStartCountDown--; _battleStartCounter = 0f; if (_battleStartCountDown < 0) { Feedback.text = ""; // Who starts first? _playerCurrentState = BATTLE_STATES.WAITING_FOR_PLAYER; _npcCurrentState = _battleData.playerStarts ? BATTLE_STATES.NPC_COOLDOWN : BATTLE_STATES.NPC_ATTACKING; } else if (_battleStartCountDown == 0) { Feedback.text = "GO!"; } } break; case BATTLE_STATES.NPC_COOLDOWN: _npcTimeCounter += Time.deltaTime; if (_npcTimeCounter >= _npcCooldown.TotalSeconds) { _npcTimeCounter = 0f; _npcCurrentState = BATTLE_STATES.NPC_ATTACKING; } break; case BATTLE_STATES.NPC_ATTACKING: // Compute battle int att = _npcAttackScore + Random.Range(0, _battleData.maxAttackScoreBonus); int def = _playerBaseDefenseScore; int dmg = ComputeDamage(att, def); if (dmg > 0) { _playerService.DecreaseEnergyLevel(dmg); PlayNPCAttackAnimation(); PlayPlayerIsHitAnimation(dmg); } else { PlayNPCMissAnimation(); } _npcCurrentState = BATTLE_STATES.NPC_COOLDOWN; break; } // Handle Player State machine switch (_playerCurrentState) { case BATTLE_STATES.WAITING_FOR_PLAYER: // Do nothing AttackButton.interactable = true; break; case BATTLE_STATES.PLAYER_ATTACKING: // Compute battle int att = _playerBaseAttackScore + Random.Range(0, _battleData.maxAttackScoreBonus); int def = _npcDefenseScore + Random.Range(0, _battleData.maxAttackScoreBonus); int dmg = ComputeDamage(att, _npcDefenseScore); if (dmg > 0) { _currentNPCEnergyLevel -= dmg; PlayNPCIsHitAnimation(dmg); PlayPlayerAttackAnimation(); } else { PlayPlayerMissAnimation(); } AttackButton.interactable = false; _avatarCooldownCounter = 0f; PlayerCooldownSlider.gameObject.SetActive(true); PlayerCooldownSlider.maxValue = (float)_playerCooldownDuration.TotalSeconds; _playerCurrentState = BATTLE_STATES.PLAYER_COOLDOWN; break; case BATTLE_STATES.PLAYER_COOLDOWN: PlayerCooldownSlider.value = PlayerCooldownSlider.maxValue - _avatarCooldownCounter; _avatarCooldownCounter += Time.deltaTime; if (_avatarCooldownCounter >= _playerCooldownDuration.TotalSeconds) { _avatarCooldownCounter = 0f; PlayerCooldownSlider.gameObject.SetActive(false); _playerCurrentState = BATTLE_STATES.WAITING_FOR_PLAYER; } break; } } } }
/// <summary> /// Triggered when the player touches the attack button. /// </summary> public void OnPlayerAttack() { _playerCurrentState = BATTLE_STATES.PLAYER_ATTACKING; }