I've learned a lot of things during my time at Champlain. Unfortunately, Unreal Engine 4 was not one of them, despite how prevalent it is these days in games. I'm going to be chronicling my journey to create the skeleton of an Active Time Battle system (similar to FF7/Chrono Trigger).
The first thing I did when jumping into Unreal was creating a base blueprint that I could use for all party and enemy units, called BattleActor. This blueprint is responsible for storing data on stats, attacks, and also its progress on filling its ATB bar.
Because RPGs rely heavily on their UI for most player feedback, I prioritized completing a basic progress bar that fills over a unit's head based on a speed statistic to use as the ATB bar. After some research on how to create UI widgets that appears in world space, it resulted in this, which while seeming small was quite a victory for me.
Next up was getting a proper command menu working. Keeping things basic for now, I created two attack buttons and an image. When provided with a BattleActor, the image gets updated to the BattleActor's portrait image. Eventually I got the main scene looking like this:
The easy parts were over however, as now I had to actually create attacks. This is where the Turn Queue system comes in. In RPGs that use ATB, the player can input commands to their party members even while other attacks are playing out on screen, and as soon as the current attack finishes, the next one in line starts automatically. So what I needed to do was to not only create an attack, but also have every attack go through a queue system where each unit's turn would play out in the order they were inputted. So I set out to create an attack where a party controlled BattleActor lerps towards an enemy BattleActor and then back to its home position.
Here's the blueprint for my basic attack animation:
This code works, but it needs the actual Turn Queue to govern it. I started by creating a Struct called TurnStruct that contains basic data about a turn, namely who is executing the turn, how long the animation will last, who is the target, etc. Every time the attack button is pressed on a BattleActor's command menu, a new TurnStruct gets created and added to the TurnQueue blueprint's array. Every frame, TurnQueue checks to see if there are any turns in the queue, and if so, sets the owner of that turn's ATB progress to 0 and initiates the attack.
Additionally, to simulate how Limit Break attacks in Final Fantasy 7 skip to the front of the line, I added a completely separate queue called Priority Queue that always takes priority over the normal queue if any turns are stored in it at a given time.
And while a turn is being executed, TurnQueue is constantly checking the status of the current turn's owner to see if the turn has been completed yet.
Here's a gif of it in action. The Skip Queue button being pressed on the third unit allows it to cut in line in front of the second unit even though its turn was inputted beforehand.
Comments