all repos — RPG @ 050a361fce88c2c846faa8a0d153163277574da6

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