- Home /
rpg turn based attack enemy is not attacking
going mad with this, i habe decided to make my first rpg so i am using 3 states machines, one for the player, one for the enemy and one for the battle state thing is my enemy will never debug an attack or do damage, no idea why but it looks like hes always waiting
here is my battle state machine:
using UnityEngine; using System.Collections; using System.Collections.Generic; using UnityEngine.UI;
public class BattleState : MonoBehaviour {
public enum performAction
{
WAIT,
TAKEACTION,
PERFORMACTION
}
public performAction battleStates;
public List<HandleTurn> PerformList = new List<HandleTurn>();//lista de actores
public List<GameObject> HeroInGame = new List<GameObject>();//heroes en la escena
public List<GameObject> EnemiesInBattle = new List<GameObject>();//enemigos en la escena
public enum HeroGUi//acciones posibles del heroe
{
ACTIVATE,
WAITING,
INPUT1,
INPUT2,
DONE
}
public HeroGUi HeroInput;
public List<GameObject> HeroesToManage = new List<GameObject>();
private HandleTurn HeroChoice;
public GameObject enemyButton;
public Transform Spacer;
public GameObject AttackPanel;
public GameObject EnemySelectPanel;
public GameObject StatusPanel;
// Use this for initialization
void Start ()
{
battleStates = performAction.WAIT;
EnemiesInBattle.AddRange(GameObject.FindGameObjectsWithTag("Enemy"));
HeroInGame.AddRange(GameObject.FindGameObjectsWithTag("Hero"));
HeroInput = HeroGUi.ACTIVATE;
AttackPanel.SetActive(false);
EnemySelectPanel.SetActive(false);
StatusPanel.SetActive(false);
CreateEnemyButtons();
}
// Update is called once per frame
void Update ()
{
if (HeroSM.inBattle == true)
{
StatusPanel.SetActive(true);
switch (battleStates)
{
case (performAction.WAIT):
if (PerformList.Count > 0)//revisa la lista
{
battleStates = performAction.TAKEACTION;
}
break;
case (performAction.TAKEACTION):
GameObject performer = GameObject.Find(PerformList[0].Attacker);
if (PerformList[0].Side == "Enemy")
{
EnemySM ESM = performer.GetComponent<EnemySM>();
ESM.HeroToAttack = PerformList[0].TargetGO;
EnemySM.currentEnemyTurn = EnemySM.enemyTurn.ACTION;
HeroSM.currentHeroTurn = HeroSM.heroTurn.WAITING;
}
if (PerformList[0].Side == "Hero")
{
HeroSM HSM = performer.GetComponent<HeroSM>();
HSM.EnemyToAttack = PerformList[0].TargetGO;
HeroSM.currentHeroTurn = HeroSM.heroTurn.ACTION;
EnemySM.currentEnemyTurn = EnemySM.enemyTurn.WAITING;
}
battleStates = performAction.PERFORMACTION;
break;
case (performAction.PERFORMACTION):
//iddle
break;
}
//switch para el estado del heroe
switch (HeroInput)
{
case (HeroGUi.ACTIVATE):
if (HeroesToManage.Count > 0)
{
print("im active yo!");
HeroesToManage[0].transform.FindChild("Selector").gameObject.SetActive(true);//tomamos al primer heroe de la lista, hallamos el padre, pasamos al hijo llamado selector y seteamos el booleano
HeroChoice = new HandleTurn();
AttackPanel.SetActive(true);
HeroInput = HeroGUi.WAITING;
}
break;
case (HeroGUi.WAITING):
//iddle
break;
case (HeroGUi.DONE):
HeroInputDone();
break;
}
}
}
public void CollectActions(HandleTurn handleInput)
{
PerformList.Add(handleInput);
}
void CreateEnemyButtons ()
{
foreach(GameObject Enemy in EnemiesInBattle)
{
GameObject newButton = Instantiate(enemyButton) as GameObject;
EnemySelectButton button = newButton.GetComponent<EnemySelectButton>();
EnemySM curEnemy = Enemy.GetComponent<EnemySM>();
Text buttonText = newButton.transform.FindChild("Text").gameObject.GetComponent<Text>();
buttonText.text = curEnemy.Enemy.baseName;
button.EnemyPrefab = Enemy;
newButton.transform.SetParent(Spacer, false);
}
}
public void Input1()//attack button
{
HeroChoice.Attacker = HeroesToManage[0].name;
HeroChoice.AttackerGO = HeroesToManage[0]; // ya es un gameobject asi que no lo especificamos
HeroChoice.Side = "Hero";
AttackPanel.SetActive(false);
EnemySelectPanel.SetActive(true);
}
public void InputEnemySelection(GameObject choosenEnemy)//enemy selection
{
HeroChoice.TargetGO = choosenEnemy;
HeroInput = HeroGUi.DONE;
}
void HeroInputDone()
{
PerformList.Add(HeroChoice);
EnemySelectPanel.SetActive(false);
AttackPanel.SetActive(true);
HeroesToManage[0].transform.FindChild("Selector").gameObject.SetActive(false);
HeroesToManage.RemoveAt(0);
HeroInput = HeroGUi.ACTIVATE;
}
}
this is my enemy state machine:
using UnityEngine; using System.Collections; using UnityEngine.UI;
public class EnemySM : MonoBehaviour {
public EnemyStats Enemy;//creamos a enemigo desde la plantilla
private BattleState BS;
public bool actionStarted = false;
public GameObject Description;
public enum enemyTurn
{
PROCESSING,
CHOOSEACTION,
WAITING,
ACTION,
DEAD
}
public static enemyTurn currentEnemyTurn;
//para cambiar las barras
private float curHealth;
public GameObject HeroToAttack;
// Use this for initialization
void Start()
{
currentEnemyTurn = enemyTurn.WAITING;
BS = GameObject.Find("BM").GetComponent<BattleState>();
}
// Update is called once per frame
void Update()
{
/* if (HeroSM.currentHeroTurn != HeroSM.heroTurn.WAITING)
{
currentEnemyTurn = enemyTurn.WAITING;
}*/
if (GMScript.InBattle == true)
{
curHealth = Enemy.CurrentHp;
switch (currentEnemyTurn)
{
case (enemyTurn.PROCESSING):
print("enemy processing");
currentEnemyTurn = enemyTurn.CHOOSEACTION;
break;
case (enemyTurn.CHOOSEACTION):
print("enemy chooseaction");
ChooseAction();
currentEnemyTurn = enemyTurn.WAITING;
break;
case (enemyTurn.WAITING):
//idle state
/*if (HeroSM.currentHeroTurn == HeroSM.heroTurn.WAITING)
{
currentEnemyTurn = enemyTurn.PROCESSING;
}*/
break;
case (enemyTurn.ACTION):
print("enemy action");
StartCoroutine(TimeForAction());
break;
case (enemyTurn.DEAD):
break;
}
}
}
void ChooseAction()
{
HandleTurn myAttack = new HandleTurn();
myAttack.Attacker = Enemy.baseName;
myAttack.Side = "Enemy";
myAttack.AttackerGO = this.gameObject;
myAttack.TargetGO = BS.HeroInGame[Random.Range(0, BS.HeroInGame.Count)];
int num = Random.Range(0,Enemy.Attacks.Count);//se genra un numero aleatorio entre 0 y la cantidad de ataques
myAttack.chooseAttack = Enemy.Attacks[num];//usamos el numero para escoger el ataque
Debug.Log(this.gameObject.name + " has choosen " + myAttack.chooseAttack.attackName + " and did " +myAttack.chooseAttack.attackDamage + " damage!!!");
BS.CollectActions(myAttack);
}
private IEnumerator TimeForAction ()//controla variables atraves del tiempo
{
if(actionStarted == true)
{
yield break;
}
actionStarted = true;
//wait
//do damage
DoDamage();
//remove from bs list
BS.PerformList.RemoveAt(0);//remueve al objeto en 0, el siguiente sube transformando el 1 en 0
//continua removiendo hasta desaparecer todo
//reset bs to wait
BS.battleStates = BattleState.performAction.WAIT;
//al pasar a wait y saltar a takeaction los objetos vuelven a crearse repitiendo el ciclo
//end coroutine
actionStarted = false;
currentEnemyTurn = enemyTurn.PROCESSING;
}
void DoDamage()
{
float calcDamage = Enemy.Fue * BS.PerformList[0].chooseAttack.attackDamage;
HeroToAttack.GetComponent<HeroSM>().TakeDamage(calcDamage);
}
}
this is my hero state machine:
using UnityEngine; using System.Collections; using UnityEngine.UI;
public class HeroSM : MonoBehaviour {
private BattleState BS;
public static bool inBattle;
public partyStat hero;//creamos a hero desde la plantilla
public enum heroTurn
{
START,
PROCESSING,
ADDTOLIST,
WAITING,
SELECTING,
ACTION,
DEAD
}
public static heroTurn currentHeroTurn;
//para cambiar las barras
private float curHealth;
public Image healthB;
public Image chamaB;
public GameObject selector;
public GameObject EnemyToAttack;
//ienumerator
private bool actionStarted;
// Use this for initialization
void Start ()
{
selector.SetActive(false);
BS = GameObject.Find("BM").GetComponent<BattleState>();
currentHeroTurn = heroTurn.START;
}
// Update is called once per frame
void Update ()
{
/*if (EnemySM.currentEnemyTurn != EnemySM.enemyTurn.WAITING)
{
currentHeroTurn = heroTurn.WAITING;
}*/
//creamos el movimiento de las barras de hp y chama
chamaB.transform.localScale = new Vector3(hero.CurrentChama / 100, this.transform.localScale.y, this.transform.localScale.z);
healthB.transform.localScale = new Vector3(hero.CurrentHp / 100, this.transform.localScale.y, this.transform.localScale.z);
curHealth = hero.CurrentHp;
if (GMScript.InBattle == true)
{
switch (currentHeroTurn)
{
case (heroTurn.START):
currentHeroTurn = heroTurn.PROCESSING;
break;
case (heroTurn.PROCESSING):
//inBattle = true;
//print("hero processing");
UpgradeBar();
break;
case (heroTurn.ADDTOLIST):
//print("hero addtolist");
BS.HeroesToManage.Add(this.gameObject);
currentHeroTurn = heroTurn.WAITING;
break;
case (heroTurn.WAITING):
//print("hero waiting");
/* if (EnemySM.currentEnemyTurn == EnemySM.enemyTurn.WAITING)
{
currentHeroTurn = heroTurn.START;
}*/
//idle
break;
case (heroTurn.ACTION):
//print("hero action");
StartCoroutine(TimeForAction());
break;
case (heroTurn.DEAD):
break;
}
}
}
void UpgradeBar()
{
currentHeroTurn = heroTurn.ADDTOLIST;
}
private IEnumerator TimeForAction()//controla variables atraves del tiempo
{
if (actionStarted == true)
{
yield break;
}
actionStarted = true;
//wait
//do damage
//remove from bs list
BS.PerformList.RemoveAt(0);//remueve al objeto en 0, el siguiente sube transformando el 1 en 0
//continua removiendo hasta desaparecer todo
//reset bs to wait
BS.battleStates = BattleState.performAction.WAIT;
//al pasar a wait y saltar a takeaction los objetos vuelven a crearse repitiendo el ciclo
//end coroutine
actionStarted = false;
currentHeroTurn = heroTurn.PROCESSING;
}
public void TakeDamage(float getDamageAmount)
{
hero.CurrentHp -= getDamageAmount;
if (hero.CurrentHp <= 0)
{
currentHeroTurn = heroTurn.DEAD;
}
}
}
habe been with this for 2 days now, would love any help
Honestly... that's a lot of code to go through and it seems you know how to code decently well. I read a little of the code and just stopped. Too much to process.
By a quick glance, your enemy while in wait mode will continue waiting forever as you have no code in the wait switch statement. (the code that changes the state is commented out).
During my quick glance I couldn't quickly see what PerformList does or how it gets changed. (Didn't put much time into reading the scripts).
To debug this, put print statements everywhere where variables change and make sure they are actually changing. Put a print statement before the change and after. Ensure the values are correct. Then where the actual variable resides, make sure it changes. Put print statements in the update loop. This should allow you to see what is happening after you read through all the logs. $$anonymous$$ake the print statements well too that let you know exactly what print statement is being printed as in what file it is in, what method it is, and on what condition/criteria.
I would exa$$anonymous$$e:
if (PerformList[0].Side == "Enemy") if (PerformList[0].Side == "Hero")
to see what those are giving you or if those are actually working as those are making the turns/moves happen.
Answer by zolutr · Sep 23, 2016 at 11:40 AM
it looks like it was a design problem, i decdided to create a cooldown system and looks like its working for now so, question closed i guess?
Your answer
Follow this Question
Related Questions
Best way to implement a turn system? Co-Routines or State-Machine? 1 Answer
Multiplayer battles on iOS 0 Answers
How can I pause one object's Update() until another class has performed its task? 2 Answers
Creating an Interactable Grid for Tactics Game (C#) 1 Answer
How to handle undefined targets in a composition based ability system? 2 Answers