I have a turn based game system where after calling the NextTurn function, the current unit is deactivated and the next unit in the initiative order is made active. If there are no more units in the turn order list, StartTurn is called and a new round begun.
I’ve added a timed buff system, and the current spell effects on a unit should tick at the start of the units action, in case damage over time effects etc kill it before it has a chance to act. However this leaves my current function broken when killed by a spell effect and then referenced by the remaining part of the function where it should be taking its action.
I want to include a sanity check to make sure the unit is still active, and if not advance to the next unit in the turn order but I’m not sure where it should go. If I tick spell effects, then test if the active unit is null and then call NextTurn again if so, is this like calling a break on my current iteration through the function, or will it return to the exact same spot after executing and the problem is still there? I thought about encapsulating all the unit selection part in a while selectedUnit != null loop, but not quite sure how to structure this with the else condition that calls StartTurn at the end of the initiative list, since if there’s no other valid unit in the turn order that loop will continue forever? Any idea how i should structure this? Thank you!
edit: I’m also removing the unit from the initiative liston its Death() function but it might be more sensible to just not remove it there, allow that index to be null and rebuild it at the top of the turn? Since if it’s triggering death off a spell effect and removing itself from the list this seems like it might screw with the indices
public void StartTurn(){
//reset the target highlights
foreach (GameObject tile in map.tileArray)
tile.GetComponent<SpriteRenderer> ().color = Color.white;
//reset initiative order and advance round counter
currentInitIndex = 0;
roundCounter += 1;
//reset hero's ability to cast
playerHero.hasCast = false;
playerHero.GetComponent<SpriteRenderer> ().color = Color.white;
map.GetComponent<CombatLog> ().NewMessage ("ROUND " + roundCounter +" BEGINS");
map.selectedUnit = map.initiativeOrder [currentInitIndex];
map.selectedUnit.GetComponent<Unit> ().isActive = true;
foreach (TimedBuff buff in map.selectedUnit.GetComponent<Unit>().currentBuffs.ToArray()) {
buff.Tick (1);
}
if (map.selectedUnit.GetComponent<Enemy> ()) {
map.selectedUnit.GetComponent<Enemy> ().TakeTurn ();
}
}
public void NextTurn(){
//reset the target highlights
foreach (GameObject tile in map.tileArray)
tile.GetComponent<SpriteRenderer> ().color = Color.white;
//null path and reset movement points
map.selectedUnit.GetComponent<Unit> ().currentPath = null;
map.selectedUnit.GetComponent<Unit> ().remainingMovement = map.selectedUnit.GetComponent<Unit> ().moveSpeed;
//remove any expired buffs from the current unit before advancing turn, this is separate from the tick logic which should apply at start of turn
foreach (TimedBuff buff in map.selectedUnit.GetComponent<Unit>().currentBuffs.ToArray()) {
if (buff.IsFinished) {
map.selectedUnit.GetComponent<Unit> ().currentBuffs.Remove (buff);
}
}
//advance the next unit in the initiative order array as the active unit and deactive the previous unit
if (currentInitIndex < map.initiativeOrder.Count-1) {
map.selectedUnit.GetComponent<Unit> ().isActive = false;
currentInitIndex += 1;
map.selectedUnit = map.initiativeOrder [currentInitIndex];
map.selectedUnit.GetComponent<Unit> ().isActive = true;
//advance all times buffs by one tick, we want to advance after selecting the new unit but before it acts, in case it is killed by a spell effect
foreach (TimedBuff buff in map.selectedUnit.GetComponent<Unit>().currentBuffs.ToArray()) {
//all buffs currently decrement by one tick per turn
buff.Tick (1);
}
//TODO sanity check in case a fatal debuff has killed the unit before taking its turn
//if the next unit to act is an enemy, take its turn
if (map.selectedUnit.GetComponent<Enemy> ()) {
map.selectedUnit.GetComponent<Enemy> ().TakeTurn ();
}
} else {
//we have reached the end of the initiative order list, begin a new combat round
map.selectedUnit.GetComponent<Unit>().isActive = false;
map.selectedUnit = null;
StartTurn();
}
}