all repos — RPG @ master

Fully functional 3D turn based role playing game coded in C# and base Unity.

Assets/Scripts/Battle/BattleManager.cs (view raw)

  1using System;
  2using System.Collections;
  3using System.Collections.Generic;
  4using UnityEngine;
  5using UnityEngine.SceneManagement;
  6using UnityEngine.UI;
  7
  8public class BattleManager : MonoBehaviour
  9{
 10    #region Private
 11    private int currentTurn = 0;
 12    private Fighter currentTarget;
 13    private Action currentAction;
 14    private float lerpStart;
 15    private GameObject player;
 16    public BattleUIManager ui;
 17    private BadGuy tmpbad;
 18    private bool action_output = true;
 19    #endregion
 20
 21    public Fighter turn;
 22    public BadGuy enemy;
 23    public int enemyGold;
 24    public Inventory enemyItems;
 25
 26    public Camera main_camera;
 27    public GameMaster gm;
 28    
 29    enum Status
 30    {
 31        StartTurn = 0,
 32        EnableIO = 1,
 33        DisableIO = 3,
 34        NextTurn = 5,
 35        Wait = 69
 36    }
 37    private Status status = Status.Wait;
 38    
 39
 40    [Header("Fighter Prefabs")]
 41    public GameObject p_paladin;
 42    public GameObject p_archer;
 43    public GameObject p_boxer;
 44    public GameObject p_mage;
 45
 46    [Header("Enemy Prefabs")]
 47    public GameObject p_orc;
 48    public GameObject p_mutant;
 49    public GameObject p_brady;
 50    public GameObject p_ganfaul;
 51    //public GameObject p_enemy1;
 52
 53    [Header("Current fighters")]
 54    public List<Fighter> fighters;
 55
 56    // Start is called before the first frame update
 57    void Start()
 58    {
 59        //inizia la battaglia
 60        gm = GameMaster.Instance;
 61        ui = GetComponent<BattleUIManager>();
 62
 63        fighters = new List<Fighter>();
 64        Fighter tmpfighter;
 65        foreach(Stats s in gm.Party)
 66        {
 67            //instantiate good guy
 68            tmpfighter = instantiateFighter(s.Name, s.Name + "Spawn").GetComponent<Fighter>();
 69
 70            //set current HP and MP
 71            tmpfighter.stats = new Stats(s);
 72
 73            //check if fighter's already dead
 74            if (tmpfighter.stats.HP == 0)
 75            {
 76                tmpfighter.animator.SetTrigger("Corpse");
 77                tmpfighter.dead = true;
 78            }
 79
 80            fighters.Add(tmpfighter);
 81        }
 82        enemy = (BadGuy)instantiateFighter(gm.GetEnemyType(), "EnemySpawn").GetComponent<Fighter>();
 83        fighters.Add(enemy);
 84
 85        enemyGold = enemy.goldDrop;
 86        enemyItems = enemy.itemsDrop;
 87        
 88        fighters.Sort(Fighter.SortByAgl);
 89
 90        //aspetto che finisca l'animazione e poi vado
 91        UI.changeText(ui.status, enemy.stats.Name + " approaches!");
 92        StartCoroutine(waitThenStatus(UI.BattleSpeed, Status.StartTurn));
 93
 94    }
 95
 96    private void Update()
 97    {
 98        #region State Machine
 99        switch (status)
100        {
101            case Status.StartTurn:
102                turn = fighters[currentTurn];
103                //reset defence
104                if (turn.defending)
105                {
106                    turn.defending = false;
107                    turn.stats.DEF = turn.stats.MaxDEF;
108                }
109
110                if (turn.dead)
111                {
112                    status = Status.NextTurn;
113                } else
114                {
115                    //step forward
116                    if (action_output)
117                    {
118                        turnEffect(turn, true);
119                    }
120                    UI.changeText(ui.status, "It's " + turn + "'s turn.");
121
122                    if (turn is BadGuy) //load AI
123                    {
124                        //execute AI
125                        tmpbad = (BadGuy)turn;
126                        UI.changeText(ui.status, tmpbad.Combat_AI());
127
128                        //wait for animation
129                        StartCoroutine(waitThenStatus(UI.BattleSpeed * 2, Status.NextTurn));
130                    }
131                    else 
132                    {
133                        //show input UI
134                        ui.showAbilities(true);
135                    }
136                    status = Status.Wait;
137                }
138                break;
139            case Status.DisableIO:
140                UI.changeText(ui.status, AbilityDB.Process(turn, currentAction, currentTarget, true, out action_output));
141
142                if (action_output)
143                {
144                    StartCoroutine(waitThenStatus(UI.BattleSpeed * 2, Status.NextTurn));
145                } else
146                {
147                    StartCoroutine(waitThenStatus(UI.BattleSpeed * 2, Status.StartTurn));
148                }
149                status = Status.Wait;
150                break;
151            case Status.NextTurn:
152                if (!turn.dead)
153                {
154                    turnEffect(turn, false);
155                }
156                //kill'em
157                foreach (Fighter f in fighters)
158                {
159                    if(f.stats.HP == 0 && f.dead == false)
160                    {
161                        f.animator.SetTrigger("Dead");
162                        f.dead = true;
163                    }
164                }
165                
166                //did i lose?
167                if (countGuys(false) == 0)
168                {
169                    StartCoroutine(endBattle(UI.BattleSpeed * 5, false));
170                    status = Status.Wait; //wait until scene has changed
171                }
172                else //did i win?
173                if (countGuys(true) == 0)
174                {
175                    //start victory animations
176                    foreach(Fighter f in getGuys(false))
177                    {
178                        f.animator.SetTrigger("Victory");
179                    }
180                    StartCoroutine(endBattle(UI.BattleSpeed * 3, true));
181                    status = Status.Wait;
182                } else
183                {
184                    //next turn
185                    currentTurn++;
186                    if (currentTurn == fighters.Count)
187                    {
188                        currentTurn = 0;
189                    }
190                    status = Status.StartTurn;
191                }
192                break;
193        }
194        #endregion
195    }
196
197    public void getInput(Action Action, Fighter Target)
198    {
199        if (status == Status.Wait)
200        {
201            currentAction = Action;
202            currentTarget = Target;
203            status = Status.DisableIO;
204        }
205    }
206
207    public Fighter[] getGuys(bool bad)
208    {
209        List<Fighter> tmp = new List<Fighter>();
210        foreach (Fighter figh in fighters)
211        {
212            if ((figh is BadGuy) == bad && !figh.dead)
213            {
214                tmp.Add(figh);
215            }
216        }
217        return tmp.ToArray();
218    }
219
220    public int countGuys(bool bad)
221    {
222        int i = 0;
223        foreach (Fighter figh in fighters)
224        {
225            if ((figh is BadGuy) == bad && !figh.dead)
226            {
227                i++;
228            }
229        }
230        return i;
231    }
232
233    private GameObject instantiateFighter(string type, string spawnPoint)
234    {
235        Transform spot = GameObject.Find(spawnPoint).transform;
236        switch (type)
237        {
238            case "Paladin":
239                if (p_paladin)
240                {
241                    return Instantiate(p_paladin, spot.position, spot.rotation);
242                }
243                break;
244            case "Archer":
245                if (p_archer)
246                {
247                    return Instantiate(p_archer, spot.position, spot.rotation);
248                }
249                break;
250            case "Boxer":
251                if (p_boxer)
252                {
253                    return Instantiate(p_boxer, spot.position, spot.rotation);
254                }
255                break;
256            case "Mage":
257                if (p_mage)
258                {
259                    return Instantiate(p_mage, spot.position, spot.rotation);
260                }
261                break;
262
263            case "Orc":
264                return Instantiate(p_orc, spot.position, spot.rotation);
265            case "Mutant":
266                return Instantiate(p_mutant, spot.position, spot.rotation);
267            case "Brady":
268                return Instantiate(p_brady, spot.position, spot.rotation);
269            case "Ganfaul":
270                return Instantiate(p_ganfaul, spot.position, spot.rotation);
271            default:
272                Debug.Log("Wrong name!");
273                return null;
274        }
275        return null;
276    }
277
278    private IEnumerator endBattle(float offset, bool didYouWin)
279    {
280        yield return new WaitForSeconds(offset);
281        if (didYouWin)
282        {
283            ui.showResults(enemy.goldDrop, enemyItems);
284            yield return new WaitForSeconds(offset + 1);
285            gm.EndBattle(true);
286        } else
287        {
288            gm.EndBattle(false);
289        }
290    }
291
292    private IEnumerator waitThenStatus(float seconds, Status nextStatus)
293    {
294        yield return new WaitForSeconds(seconds);
295        status = nextStatus;
296    }
297
298    private IEnumerator MoveFromTo(Transform objectToMove, Vector3 a, Vector3 b, float speed)
299    {
300        float step = (speed / (a - b).magnitude) * Time.fixedDeltaTime;
301        float t = 0;
302        while (t <= 1.0f)
303        {
304            t += step; // Goes from 0 to 1, incrementing by step each time
305            objectToMove.position = Vector3.Lerp(a, b, t); // Move objectToMove closer to b
306            yield return new WaitForFixedUpdate();         // Leave the routine and return here in the next frame
307        }
308        objectToMove.position = b;
309    }
310
311    public void turnEffect(Fighter f, bool onOff)
312    {
313        int distance = 4;
314
315        if(f is BadGuy)
316        {
317            distance *= -1;
318        }
319        if (!onOff)
320        {
321            distance *= -1;
322        }
323
324        StartCoroutine(MoveFromTo(f.transform, f.transform.position, f.transform.position + new Vector3(0, 0, distance), 20));
325    }
326}