Implementing Attacks in Battle System
BattleSystem
cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum BattleState { Start, PlayerAction, PlayerMove, EnemyMove, Busy }
public class BattleSystem : MonoBehaviour
{
[SerializeField] BattleUnit playerUnit;
[SerializeField] BattleUnit enemyUnit;
[SerializeField] BattleHub playerHub;
[SerializeField] BattleHub enemyHub;
[SerializeField] BattleDialogBox dialogBox;
BattleState state;
int currentAction;
int currentMove;
private void Start()
{
StartCoroutine(SetupBattle());
}
public IEnumerator SetupBattle()
{
playerUnit.Setup();
playerHub.SetData(playerUnit.Pokemon);
enemyUnit.Setup();
enemyHub.SetData(enemyUnit.Pokemon);
dialogBox.SetMovenames(playerUnit.Pokemon.Moves);
yield return dialogBox.TypeDialog($"A wild {enemyUnit.Pokemon.Base.Name} appeard.");
yield return new WaitForSeconds(1f);
PlayerAction();
}
void PlayerAction()
{
state = BattleState.PlayerAction;
StartCoroutine(dialogBox.TypeDialog("Choose an aciton"));
dialogBox.EnableActionSelector(true);
}
void playerMove()
{
state = BattleState.PlayerMove;
dialogBox.EnableActionSelector(false);
dialogBox.EnableDialogText(false);
dialogBox.EnableMoveSelector(true);
}
IEnumerator PerformPlayerMove()
{
state = BattleState.Busy;
var move = playerUnit.Pokemon.Moves[currentMove];
yield return dialogBox.TypeDialog($"{playerUnit.Pokemon.Base.name} used {move.Base.Name}");
yield return new WaitForSeconds(1f);
bool isFainted = enemyUnit.Pokemon.TakeDamage(move,playerUnit.Pokemon);
yield return enemyHub.UpdateHP();
if (isFainted)
{
yield return dialogBox.TypeDialog($"{enemyUnit.Pokemon.Base.name} Fainted");
}
else
{
StartCoroutine(EnemyMove());
}
}
IEnumerator EnemyMove()
{
state = BattleState.EnemyMove;
var move = enemyUnit.Pokemon.GetRandomMove();
yield return dialogBox.TypeDialog($"{enemyUnit.Pokemon.Base.name} used {move.Base.Name}");
yield return new WaitForSeconds(1f);
bool isFainted = playerUnit.Pokemon.TakeDamage(move, playerUnit.Pokemon);
yield return playerHub.UpdateHP();
if (isFainted)
{
yield return dialogBox.TypeDialog($"{playerUnit.Pokemon.Base.name} Fainted");
}
else
{
PlayerAction();
}
}
private void Update()
{
if (state == BattleState.PlayerAction)
{
HandleActionSelection();
}
else if (state == BattleState.PlayerMove)
{
HandleMoveSelection();
}
}
void HandleActionSelection()
{
if (Input.GetKeyDown(KeyCode.DownArrow))
{
if (currentAction < 1)
++currentAction;
}
else if (Input.GetKeyDown(KeyCode.UpArrow))
{
if (currentAction > 0)
--currentAction;
}
dialogBox.UpdateActionSelection(currentAction);
if (Input.GetKeyDown(KeyCode.Z))
{
if (currentAction == 0)
{
playerMove();
}
else if (currentAction == 1)
{
}
}
}
void HandleMoveSelection()
{
if (Input.GetKeyDown(KeyCode.RightArrow))
{
if (currentMove < playerUnit.Pokemon.Moves.Count - 1)
++currentMove;
}
else if (Input.GetKeyDown(KeyCode.LeftArrow))
{
if (currentMove > 0)
--currentMove;
}
if (Input.GetKeyDown(KeyCode.DownArrow))
{
if (currentMove < playerUnit.Pokemon.Moves.Count - 2)
currentMove += 2;
}
else if (Input.GetKeyDown(KeyCode.UpArrow))
{
if (currentMove > 1)
currentMove -= 2;
}
dialogBox.UpdateMoveSelection(currentMove,playerUnit.Pokemon.Moves[currentMove]);
if (Input.GetKeyDown(KeyCode.Z))
{
dialogBox.EnableMoveSelector(false);
dialogBox.EnableDialogText(true);
StartCoroutine(PerformPlayerMove());
}
}
}
BattleUnit
cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class BattleUnit : MonoBehaviour
{
[SerializeField] PokemonBase _base;
[SerializeField] int level;
[SerializeField] bool isPlayerUnit;
public Pokemon Pokemon { get; set; }
public void Setup()
{
Pokemon = new Pokemon(_base, level);
if(isPlayerUnit)
GetComponent<Image>().sprite = Pokemon.Base.BackSprite;
else
GetComponent<Image>().sprite = Pokemon.Base.FrontSprite;
}
}
BattleHub
cs
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class BattleHub : MonoBehaviour
{
[SerializeField] TMP_Text nameText;
[SerializeField] TMP_Text levelText;
[SerializeField] HPBar hpBar;
Pokemon _pokemon;
public void SetData(Pokemon pokemon)
{
_pokemon = pokemon;
nameText.text = pokemon.Base.name;
levelText.text = "Lvl " + pokemon.Level;
hpBar.SetHP((float) pokemon.HP / pokemon.MaxHp);
}
public IEnumerator UpdateHP()
{
yield return hpBar.SetHPSmooth((float)_pokemon.HP / _pokemon.MaxHp);
}
}
HPBar
cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HPBar : MonoBehaviour
{
[SerializeField] GameObject health;
private void Start()
{
health.transform.localScale = new Vector3(1f, 1f);
}
public void SetHP(float hpNormalized)
{
health.transform.localScale = new Vector3(hpNormalized, 1f);
}
public IEnumerator SetHPSmooth(float newHp)
{
float curHp = health.transform.localScale.x;
float changeAmt = curHp - newHp;
while (curHp - newHp > Mathf.Epsilon)
{
curHp -= changeAmt * Time.deltaTime;
health.transform.localScale = new Vector3(curHp, 1f);
yield return null;
}
health.transform.localScale = new Vector3(newHp, 1f);
}
}
Move
cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Move
{
public MoveBase Base { get; set; }
public int PP { get; set; }
public Move(MoveBase pBase)
{
Base = pBase;
PP = pBase.PP;
}
}
MoveBase
cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "Move", menuName = "Pokemon/Create new move")]
public class MoveBase : ScriptableObject
{
[SerializeField] string name;
[TextArea]
[SerializeField] string description;
[SerializeField] PokemonType type;
[SerializeField] int power;
[SerializeField] int accuracy;
[SerializeField] int pp;
public string Name { get { return name; } }
public PokemonType Type { get { return type; } }
public int Power { get { return power; } }
public int Accuracy { get { return accuracy; } }
public int PP { get { return pp; } }
}
cs
using JetBrains.Annotations;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Pokemon
{
public PokemonBase Base { get; set; }
public int Level { get; set; }
public int HP { get; set; }
public List<Move> Moves { get; set; }
public Pokemon(PokemonBase pBase, int plevel)
{
Base = pBase;
Level = plevel;
HP = MaxHp;
// Generate Moves
Moves = new List<Move>();
foreach (var move in Base.LearnableMoves)
{
if (move.Level <= Level)
Moves.Add(new Move(move.Base));
if (Moves.Count >= 4)
break;
}
}
public int Attack
{
get { return Mathf.FloorToInt((Base.Attack * Level) / 100f) + 5;}
}
public int Defense
{
get { return Mathf.FloorToInt((Base.Defense * Level) / 100f) + 5; }
}
public int SpAttack
{
get { return Mathf.FloorToInt((Base.SpAttack * Level) / 100f) + 5; }
}
public int SpDefense
{
get { return Mathf.FloorToInt((Base.SpDefense * Level) / 100f) + 5; }
}
public int Speed
{
get { return Mathf.FloorToInt((Base.Speed * Level) / 100f) + 5; }
}
public int MaxHp
{
get { return Mathf.FloorToInt((Base.MaxHp * Level) / 100f) + 10; }
}
public bool TakeDamage(Move move, Pokemon attacker)
{
float modifiers = Random.Range(0.85f, 1f);
float a = (2 * attacker.Level + 10) / 250f;
float d = a * move.Base.Power * ((float)attacker.Attack / Defense) + 2;
int damage = Mathf.FloorToInt(d * modifiers);
HP -= damage;
if (HP <= 0)
{
HP = 0;
return true;
}
return false;
}
public Move GetRandomMove()
{
int r = Random.Range(0, Moves.Count);
return Moves[r];
}
}