[Tutorial Series] Hime ATB #3: Implementing Turn Count

This tutorial is part of a tutorial series on Active Time Battle (ATB) System development. In this series, you will learn how to build your own ATB system from scratch, and add new functionality to create a unique battle system based on ATB.

At the end of this tutorial, you will be able to trigger battle events based on the current turn count in the battle as well handle basic state durations.

Preparation

In this tutorial, we continue to build on the results from the first part, which lays out the foundations for an ATB system. If you haven’t read the first tutorial, I would highly recommend doing so in order to understand how it was designed.

You may also be interested in the second tutorial, where we customize our battlers’ ATB fill rates so that the faster the battler is, the more actions they can perform over a fixed period of time. It is not necessary to complete that section since turn count and fill rates are two distinct concepts and can be implemented independent of each other.

For this tutorial, I will be building on the code from the second tutorial, which you can find here.

Re-Cap

In our first tutorial, I mentioned that “time” is what we will use to determine whether a battler can perform an action or not.

By default, the game performs one update per frame, and  60 updates are performed per second, which means there are 60 frames per second.
We assumed that each battler has an AT bar that ranges from 0 to 100 frames, with a fill rate of 1 frame per second. This means that after 100 frames, a battler will be able to perform an action.

Frames, as a Measure of Time

Now, because frames are used as a measure of time, we can use frames to measure the “duration” of the battle.

When the battle begins, time begins at frame 0.
As the battle progresses, the frame count will increase.

This is very similar to turn counts in the default battle system.

When the battle begins, we are at turn 0.
At the battle progresses, the turn count will increase.

You can see that there may be some relationship between frames and turns. The question is, how can we define what that relationship is?

Determining “Frames Per Turn”

Let us suppose that ON AVERAGE, a battler can perform one action per turn. This means that for someone with an AVERAGE ATB fill rate, they will perform approximately one action every turn.

So for example, going with the assumptions from the first tutorial, we will assume that the average ATB fill rate is 1 per frame. With a max ATB of 100 and an initial ATB of 0, this means that the battler will be able to perform an action at frame 100.

After they have performed the action, assuming their ATB is completely depleted, they must wait another 100 frames before they can perform their next action.

Here is a summary of their actions:

  • Frame 0: nothing
  • Frame 100: first action
  • Frame 200: second action
  • Frame 300: third action

And so on.

Now, if we wanted to say that on average, battlers can perform one action per turn, we could define a concept called “Frames Per Turn” which is equal to

   100 Frames = 1 Turn

Using this expression, we can re-write our summary as follows:

  • Turn 0: nothing
  • Turn 1: first action
  • Turn 2: second action
  • Turn 3: third action

Which is approximately one action per turn.

Does the math work? Let’s say someone is a bit faster and has a fill rate of 2 per frame. If they are “twice” as fast as the average battler, then we can expected them to perform twice as many actions per turn, on average. The summary for a battler with a fill rate of 2 per frame would look something like this:

  • Frame 0: nothing
  • Frame 50: first action
  • Frame 100: second action — Turn 1
  • Frame 150: third action
  • Frame 200: fourth action — Turn 2

We can see that for every turn that passes, two actions can be performed.

Remember that “Frames Per Turn” is not some magic number. It is completely dependent on the scale of time. I came up with the number 100 because I assumed that the max ATB is 100, with a fill rate of 1 as the average fill rate, and one action per turn on average.

If your average fill rate was 2, with a max ATB of 100, and one action per turn, then you would need to use something like 50 for your Frames Per Turn value.

Battle Turn vs Action Turn

The term “turn” could be used very loosely. For example, how might you describe our “fast” battler with a fill rate of 2 could perform 2 actions every turn. You might say that the battler has “two turns” every 100 frames, or that the battler waits for “her turn” that comes up every 50 frames.

It is therefore important to distinguish between different kinds of “turns”.

When I say “turn”, I am referring to a “Battle Turn”. So if a battler performs two actions per turn, it means that for every 100 frames, the battler can perform two actions.

This will be important when we discuss “States” in a later tutorial.

Battle Events and Turns

One of the core features of RPG Maker is the ability to define “battle events”. These are events that occur during battle, when a certain condition is met. In particular, there are two important conditions related to time:

  • Start of Turn – event runs when the turn begins
  • End of Turn – event runs when the turn ends

In our system, we have defined one turn to be equal to 100 frames. Therefore, we can say the following

  • Turn 0 begins at frame 0
  • Turn 1 begins at frame 100
  • Turn 2 begins at frame 200

Consequently, because we have defined what the “start” of a turn is, we can say that the “end” of a turn is the frame right before the start of the next turn!

  • Turn 0 ends at frame 99
  • Turn 1 ends at frame 199
  • Turn 2 ends at frame 299

In math terms, for some turn N we can define turn start and turn end in terms of frames as follows:

  • Frame Count at Start of Turn N = N * FramePerTurn
  • Frame Count at End of Turn N = (N + 1) * FramesPerTurn – 1

So for example:

  • Start of Turn 1 = 1 * 100 = Frame 100
  • End of Turn 1 = (1 + 1) * 100 – 1 = 2 * 100 – 1 = Frame 199

Of course, since we only have frames to work with, we need to phrase our formulas in terms of frames. As a trick, we can check the remainder of the frame count. For example,

  • 100 Frames / 100 Frames Per Turn = 1 Turn and 0 Frames
  • 150 Frames / 100 Frames Per Turn = 1 Turn and 50 Frames
  • 199 Frames / 100 Frames Per Turn = 1 Turn and 99 Frames

We can see that the result of the division is the turn count, and depending on the remainer, we can determine whether it’s the start of the turn or the end of the turn.

  • If remainder = 0, then it is the start of that turn
  • If remainder = 99, then it is the end of that turn

We have now created a relationship between Frames and Turns, and now we can use this to implement battle turns. We’ve done some planning, so let’s implement it and see how it works out.

Keeping track of Frame Count

 

In the first tutorial, we did not keep track of frame count. This is because whenever an update was performed, each battlers’ ATB would be updated, and that was all we needed. Now, our battles actually need to keep track of time.

Let’s initialize a few things when the battle begins

var TH_BattleManager_initMembers = BattleManager.initMembers;
  BattleManager.initMembers = function() {
    TH_BattleManager_initMembers.call(this);
    this._framesPerTurn = 100;
    this._frames = 0;
  }

Next, we want to update this value on every frame update. In addition to updating the frame, we also want to check our turn count

BattleManager.updateFrame = function() {
  var members = this.allBattleMembers();
  for (var i = 0; i < members.length; i++) {        
    if (members[i].canInput()) {
      this._subject = members[i];
      this.startInput();
      break;
    }
  }
  if (!this._subject) {
    this._frames++;   // new
    $gameParty.updateFrame();
    $gameTroop.updateFrame();    
    this.updateTurnCount(); // new
  }
}

So on every frame update, we increment frame count by 1. Then we update all of our battlers’ frames once as usual, and finally we check the turn count using the rules we put together earlier.

BattleManager.updateTurnCount = function() {
  var rem = this._frames % this._framesPerTurn
  if (rem === 0) {
    this.startTurn();
  }
  else if (rem === this._framesPerTurn - 1) {
    this.endTurn();
  }
}

Because startTurn and endTurn already exist, I will just overwrite them for now:

/* Overwrite for now */
BattleManager.startTurn = function() {
  this._phase = 'turn';
  $gameTroop.increaseTurn();
  $gameParty.requestMotionRefresh();
};

/* Overwrite for now */
BattleManager.endTurn = function() {
  this._phase = 'turnEnd'
  var battlers = this.allBattleMembers();
  for (var i = 0; i < battlers.length; i++) {
    battlers[i].onTurnEnd();
    this._logWindow.displayAutoAffectedStatus(battlers[i]);
    this._logWindow.displayRegeneration(battlers[i]);
  }    
};

The “turnEnd” phase is important because the troops use that to determine whether it is currently the end of the turn, and thus whether a page that is conditioned on the end of the turn should execute.

There is actually a method called “updateTurnEnd” which is executed while the battle manager is in the turn end phase, but all that does is execute startInput, which would simply change the phase to “turn” in our system, so we don’t need to change it. However, in the future we might need to re-visit it.

Now, at this point, you should be able to create a troop, add some pages with conditions on turn count, and they will run at the correct times!

Summary

While the default battle system was based on turns and our active time battle system is based on frames, we can still use all of the turn-based features in our battle system be defining a rule that connects turns to frames.

In our system, we simply defined a Frames Per Turn constant and used that to check for the start and end of a turn.
With the addition of turns, game developers can now take advantage of enemy actions and battle events that are conditioned on the turn count without having to change the way they are specified in the database.

Feedback

Do you have any questions or comments? Perhaps there is something that is unclear, or could be implemented in a better way? Let me know in the comments!

Share the Tutorial

If you know anyone that is interested in writing battle systems for RPG Maker, share this with them!
You can also follow me on TwitterFacebook, or Youtube  for the latest posts and videos.

Support HimeWorks

If you would like to support me in writing these tutorials, you can put in a monthly pledge on Patreon! Every little bit helps, and becoming a supporter allows you to gain access to some exclusive content like development logs/rants, closed beta tests, and other things that I offer.

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *