Basic knowledge to the default RMMZ TPBS battle flow implementations

This topic aims to share the basic knowledge on what the default RMMZ TPBS battle flow implementations do in general, but you’re still assumed to have at least:
1. Some plugin development proficiency(having written several easy, simple and small battle-related plugins up to 1k LoC scale)
2. Basic knowledge on what the default RMMZ turn based battle flow implementations do in general
3. Basic knowledge on what the default RMMZ TPBS battle flow does in general on the user level(At least you need to know what’s going on on the surface when playing it as a player)

Simplified Flowchart

Please note that this flowchart only includes the most important elements of the battle flow, to avoid making it too complicated and convoluted for the intended targeting audience 😉

Battle Start
It’s almost exactly the same as that in the turn based counterpart, so the phase will change to “start” after finished starting the battle.

Input Action Slots
It’s actually quite similar to that in the turn based counterpart, except that:
1. As nothing other than inputting action slots can happen during the “input” phase in the turn based counterpart, the exact input sequence is always fixed there, whereas in the TPBS some party members can become inputable or uninputable at anytime, especially when it comes to active TPBS.
2. At any given frame in TPBS, players are still supposed to start from inputting the 1st action slot of the 1st inputable party member to inputting the last action slot of the last party member.
3. If players are inputting the action slots of a party member, and then they cancel inputting all those action slots of of that party member, among all the other inputable party members, those whose party member indices are greater rather than less than the previously inputting one will be selected first, and the party command window will be setup in case no other inputable party member exists.
This is because BattleManager.selectPreviousCommand will call BattleManager.selectPreviousActor, which will still call BattleManager.changeCurrentActor with argument forward as true, which is the same as what BattleManager.selectNextActor, which is called by BattleManager.selectNextCommand, does:

BattleManager.selectPreviousCommand = function() {
    if (this._currentActor) {
        if (this._currentActor.selectPreviousCommand()) {
            return;
        }
        this.cancelActorInput();
    }
    this.selectPreviousActor();
};

4. Also, unlike the turn based counterpart, if another inputable party member is selected for inputting actions due to cancelling inputs of another inputable party member, the newly selected one will still input his/her/its 1st action slot first, then proceed the same sequence until the last action slot is inputted.
5. As a corollary, once an inputable party member has inputted all his/her/its action slots, there’s no way to cancel those input because he/she/it’ll proceed to casting and then executing those actions, and this is unlike the turn based counterpart, where players can cancel party members who’ve inputted all their action slots, as long as the phase is still “input”.
6. In the turn based counterpart, the only way to activate or deactivate any input window is by the ok and cancel commands issued by players, whereas in TPBS this can also be affected by whether the currently inputting party member becomes not inputable, due to Scene_Battle.prototype.changeInputWindow, which will only be called if some input windows need to be activated/deactivated:

Scene_Battle.prototype.changeInputWindow = function() {
    this.hideSubInputWindows();
    if (BattleManager.isInputting()) {
        if (BattleManager.actor()) {
            this.startActorCommandSelection();
        } else {
            this.startPartyCommandSelection();
        }
    } else {
        this.endCommandSelection();
    }
};

In short, other than hiding the skill, item, actor and enemy windows:
– If there are inputable party members and 1 of them becomes selected to input action slots, the actor command window will be setup with the status window selecting that actor
– If there are inputable party members and all of them become not selected to input action slots, the party command window will be setup with the status window deselected
– If there are no more inputable party members, all the input windows will be closed and the status window will be deselected
Bear in mind that how the above points work in details are too advanced to be covered here.

Thinking In Frames
Unlike the default turn based battle system, thinking in frames are vital even in just trying to have a basic knowledge on what the default RMMZ TPBS battle flow implementations do in general, especially when it comes to active TPBS, so the flowchart is drawn quite differently from the turn based counterpart.
To be able to think in frames, one first need to know the starting point of a frame and all the possible ending points of that frame, then one can sequentially grasp the summary of each path, until a vague impression of a frame can be formed.
To make the task even easier, simpler and smaller, one can first try to briefly read the codes without thinking about active TPBS, which is more complicated and convoluted, especially when it comes to edge cases that are hard but still possible to reach.
When one becomes familiar with thinking in frames, he/she should be able to at least partially simulate what a frame does in general in his/her mind, and eventually roughly visualize the TPBS battle flow implementations mentally.

Frame Start
A frame starts from Scene_Battle.prototype.update, which is a vital part of the scene life cycle(too advanced to be covered here):

Scene_Battle.prototype.update = function() {
    const active = this.isActive();
    $gameTimer.update(active);
    $gameScreen.update();
    this.updateVisibility();
    if (active && !this.isBusy()) {
        this.updateBattleProcess();
    }
    Scene_Message.prototype.update.call(this);
};

Then Scene_Battle.prototype.updateBattleProcess will be called to use the result of Scene_Battle.prototype.isTimeActive as the argument of BattleManager.update, which is being called immediately afterwards:

Scene_Battle.prototype.updateBattleProcess = function() {
    BattleManager.update(this.isTimeActive());
};
Scene_Battle.prototype.isTimeActive = function() {
    if (BattleManager.isActiveTpb()) {
        return !this._skillWindow.active && !this._itemWindow.active;
    } else {
        return !this.isAnyInputWindowActive();
    }
};
BattleManager.update = function(timeActive) {
    if (!this.isBusy() && !this.updateEvent()) {
        this.updatePhase(timeActive);
    }
    if (this.isTpb()) {
        this.updateTpbInput();
    }
};

Because of Scene_Battle.prototype.isTimeActive, the active TPBS will keep the TPB running unless the skill or item window’s active, while the non-active TPBS will only keep the TPB running when there are no active input windows(party or actor command, or skill, item, actor or enemy window), meaning that there are no inputable party members.
(On a side note: Strictly speaking, the way the TPBS battle flow’s implemented won’t let plugin developers change the active TPBS to keep the TPB running even when battlers are executing actions, unless those plugin developers rewrite the whole TPBS from scratch, but these details are way, way too advanced and complex to be elaborated here)
BattleManager.isBusy and BattleManager.updateEvent will be called to only call BattleManager.updatePhase when the TPB can technically keep running(the details of these underlying technical limitations are way, way too advanced and complex to be elaborated here):

BattleManager.isBusy = function() {
    return (
        $gameMessage.isBusy() ||
        this._spriteset.isBusy() ||
        this._logWindow.isBusy()
    );
};
BattleManager.updateEvent = function() {
    switch (this._phase) {
        case "start":
        case "turn":
        case "turnEnd":
            if (this.isActionForced()) {
                this.processForcedAction();
                return true;
            } else {
                return this.updateEventMain();
            }
    }
    return this.checkAbort();
};
BattleManager.updatePhase = function(timeActive) {
    switch (this._phase) {
        case "start":
            this.updateStart();
            break;
        case "turn":
            this.updateTurn(timeActive);
            break;
        case "action":
            this.updateAction();
            break;
        case "turnEnd":
            this.updateTurnEnd();
            break;
        case "battleEnd":
            this.updateBattleEnd();
            break;
    }
};

While Game_Message.prototype.isBusy and Spriteset_Battle.prototype.isBusy are self-explanatory enough, Window_BattleLog.prototype.isBusy is a lot more complicated and convoluted(too advanced to be covered here), but it’s still about whether the TPB needs to stop to let the visual coordination running, like the battle log, animations, battler sprites, etc.
The main function of interest inside BattleManager.updateEvent is BattleManager.updateEventMain(too advanced to be covered here), and what makes it interesting here is that it’ll check whether the battle needs to end by checking whether it’s aborted, victorious or defeated, and will change the phase to “battleEnd” if any of those conditions are met.
As for BattleManager.updatePhase, it’s mainly about picking the function to call according to the current phase of the battle, while the argument timeActive is the result of Scene_Battle.prototype.isTimeActive.

Start Phase
There’s not much in this phase, as all BattleManager.updateStart does in TPBS is to change to phase to “turn”:

BattleManager.updateStart = function() {
    if (this.isTpb()) {
        this._phase = "turn";
    } else {
        this.startInput();
    }
};

Turn Phase
The “turn” phase is the majority of the difference between the TPBS battle flow and the turn based counterpart.
First, BattleManager.updateTurn will be called to use the argument timeActive as the result of Scene_Battle.prototype.isTimeActive to determine if BattleManager.updateTpb should be called as well:

BattleManager.updateTurn = function(timeActive) {
    $gameParty.requestMotionRefresh();
    if (this.isTpb() && timeActive) {
        this.updateTpb();
    }
    if (!this._subject) {
        this._subject = this.getNextSubject();
    }
    if (this._subject) {
        this.processTurn();
    } else if (!this.isTpb()) {
        this.endTurn();
    }
};
BattleManager.updateTpb = function() {
    $gameParty.updateTpb();
    $gameTroop.updateTpb();
    this.updateAllTpbBattlers();
    this.checkTpbTurnEnd();
};

Assuming that timeActive is true –
Now, Game_Unit.prototype.updateTpb will be called to call Game_Battler.prototype.updateTpb for all battlers:

Game_Battler.prototype.updateTpb = function() {
    if (this.canMove()) {
        this.updateTpbChargeTime();
        this.updateTpbCastTime();
        this.updateTpbAutoBattle();
    }
    if (this.isAlive()) {
        this.updateTpbIdleTime();
    }
};

So, if a battler can move, he/she/it’ll update the TPB and action casting bars, as well as start casting all the autobattle actions that are just made in case he/she/it’s in Auto Battle.
If he/she/it’s alive, he/she/it’ll update the idle TPB bar as well.
If his/her/its TPB becomes fully charged, he/she/it’ll become available for inputting action slots.
If his/her/its action casting bar becomes full, he/she/it’ll become available for executing valid actions.
BattleManager.updateAllTpbBattlers will call BattleManager.updateTpbBattler for all battle members:

BattleManager.updateTpbBattler = function(battler) {
    if (battler.isTpbTurnEnd()) {
        battler.onTurnEnd();
        battler.startTpbTurn();
        this.displayBattlerStatus(battler, false);
    } else if (battler.isTpbReady()) {
        battler.startTpbAction();
        this._actionBattlers.push(battler);
    } else if (battler.isTpbTimeout()) {
        battler.onTpbTimeout();
        this.displayBattlerStatus(battler, true);
    }
};

First, if the turn of the battler involved becomes ended, the old turn will be ended and the new one will be started here, with the latest battler status displayed on the battle log window.
Second, if the battler involved becomes available for executing actions, that battler will be pushed into the back of the action execution subject queue, so later BattleManager.updateTurn can call BattleManager.getNextSubject to pickup that battler to be the action execution subject.
Third, if the battler involved has become idled for so long that a turn has passed, that battler will be in the new battler turn, with the latest battler status displayed on the battle log window.
BattleManager.checkTpbTurnEnd will be covered in “Turn End Phase”.
Regardless of whether BattleManager.updateTpb is called, the rest of BattleManager.updateTurn is exactly the same as the turn based counterpart.

Action Phase
It’s almost the same as the turn based counterpart, as least when only the battle flow is concerned.

Turn End Phase
It’s quite similar to the “turn” phase in TPBS, except that, after calling BattleManager.checkTpbTurnEnd, if Game_Troop.prototype.isTpbTurnEnd returns true, BattleManager.endTurn will be called to change the phase to “turnEnd” as well:

BattleManager.checkTpbTurnEnd = function() {
    if ($gameTroop.isTpbTurnEnd()) {
        this.endTurn();
    }
};
Game_Troop.prototype.isTpbTurnEnd = function() {
    const members = this.members();
    const turnMax = Math.max(...members.map(member => member.turnCount()));
    return turnMax > this._turnCount;
};
BattleManager.endTurn = function() {
    this._phase = "turnEnd";
    this._preemptive = false;
    this._surprise = false;
};

Note that this doesn’t always mean that the phase at the next frame will be “turnEnd”, because as shown in the flowchart, it’s still possible that BattleManager.startAction will be called to change the phase to “action” before proceeding to the next frame(the proof of this possibility is too advanced to be covered here), meaning that the battle turn count can trigger later than expected, and thus potentially surprising effects on the subsequent action executions before all the queued action execution subjects have executed all their valid actions.

Battle End Phase
It’s exactly the same as the turn based counterpart as well, since BattleManager.updateBattleEnd is the absolute last stop of both of the battle flows:

BattleManager.updateBattleEnd = function() {
    if (this.isBattleTest()) {
        AudioManager.stopBgm();
        SceneManager.exit();
    } else if (!this._escaped && $gameParty.isAllDead()) {
        if (this._canLose) {
            $gameParty.reviveBattleMembers();
            SceneManager.pop();
        } else {
            SceneManager.goto(Scene_Gameover);
        }
    } else {
        SceneManager.pop();
    }
    this._phase = "";
};

Note that SceneManager here is to change the scene from Scene_Battle to something else:
1. Exits the game in the case of battle test
2. Goes to the last scene(the one before this battle) if it’s not a game over
3. Goes to the game over scene(Scene_GameOver)

Update TPB Input
It’s always run at the end of a frame in TPBS, regardless of what the current phase of the battle is.
Basically, if there’s at least 1 inputable party members, BattleManager.updateTpbInput will call BattleManager.checkTpbInputClose, otherwise it’ll call BattleManager.checkTpbInputOpen:

BattleManager.updateTpbInput = function() {
    if (this._inputting) {
        this.checkTpbInputClose();
    } else {
        this.checkTpbInputOpen();
    }
};
BattleManager.checkTpbInputClose = function() {
    if (!this.isPartyTpbInputtable() || this.needsActorInputCancel()) {
        this.cancelActorInput();
        this._currentActor = null;
        this._inputting = false;
    }
};
BattleManager.checkTpbInputOpen = function() {
    if (this.isPartyTpbInputtable()) {
        if (this._tpbNeedsPartyCommand) {
            this._inputting = true;
            this._tpbNeedsPartyCommand = false;
        } else {
            this.selectNextCommand();
        }
    }
};

In the case of running BattleManager.checkTpbInputClose, it’s to void the currently inputting party member(the one whose action slots are being inputted by players) and the party inputability flag if the currently inputting party member becomes not inputable(BattleManager.isPartyTpbInputtable is mainly for handling edge cases here).
In the case of BattleManager.checkTpbInputOpen, the gist is that(the details are too advanced to be covered here), when at least 1 of the party members become inputable, the party inputability flag will be raised if it’s the 1st time the party becomes inputable(to show the party command window instead of the actor command window), otherwise BattleManager.selectNextCommand will be called:

BattleManager.selectNextCommand = function() {
    if (this._currentActor) {
        if (this._currentActor.selectNextCommand()) {
            return;
        }
        this.finishActorInput();
    }
    this.selectNextActor();
};

While the exact mechanism of raising the inputability flag and setting up the actor command window are too advanced to be covered here, the point is that BattleManager.selectNextActor will call BattleManager.changeCurrentActor, which will call BattleManager.startActorInput, and thus raise the inputability flag if the players are already inputting the action slots of an inputable party member.

Summary
First, the battle will start, and the phase will change to “start” upon fully starting the battle, with the catch that this phase will only trigger once, which is at the start of the battle.
Then, the phase will quickly change to “turn”.
After that, all battlers will charge their TPB, and will become inputable when theirs become full.
In the case of actors, the party command window will be setup for the 1st time such event triggers in this battle, otherwise the actor command window corresponding to the inputable party member with the smallest party index at that frame will be setup.
Whenever a battler becomes restricted, his/her/its TPB and cast bars will be cleared.
Players will input from the 1st action slot of the 1st inputable party member to the last action slot of the last inputable party member at any given frame.
Whenever the party becomes to have at least 1 inputable party member, the actor command window will be setup if an actor’s selected for inputting action slots, otherwise the party command window will be setup.
Whenever the party becomes to have no inputable party members, all the input windows will be closed.
When battlers finish inputting all their action slots, they’ll start casting those actions, until they’re fully cast, and this will cause those battlers to be pushed at the back of the action execution subject queue.
As long as no actions are already executing, the most up front battler in that queue will be picked up as the action execution subject to execute will be cast valid actions, and the phase will be changed to “action”.
When that action execution subject has executed all those cast valid actions, that battler will have the TPB and cast bars emptied, and the above process of picking up new action execution subject will be repeated, until there are no more battlers available as action execution subjects, in which the phase will be changed to “turn”.
If a battle turn’s supposed to be ended, the phase will be changed to “turnEnd”, but it’ll be immediately changed to “action” at the same frame if there are still action execution subjects to execute actions.
If a battle’s supposed to be ended, the phase will be changed to “battleEnd”, and the scene will be changed from the battle scene to something else, followed by changing the phase to empty.

That’s all for now. I hope this can help you grasp these basic knowledge. For those thoroughly comprehending the essence of the default RMMZ TPBS battle flow implementations, feel free to correct me if there’s anything wrong 🙂
For those wanting to have a solid understanding to the default RMMZ TPBS battle flow implementations, I might open a more advanced topic for that later 😀

Basic knowledge to the default RMMZ turn based battle flow implementations

This topic aims to share the basic knowledge on what the default RMMZ turn based battle flow implementations do in general, but you’re still assumed to have at least:
1. Little javascript coding proficiency(barely okay with writing rudimentary Javascript codes up to 300 LoC scale)
2. Basic knowledge on what the default RMMZ turn based battle flow does on the user level(At least you need to know what’s going on on the surface when playing it as a player)

Simplified Flowchart

Please note that this flowchart only includes the most important elements of the battle flow, to avoid making it too complicated and convoluted for the intended targeting audience :)

Start Battle
This is the phase handling the start of the battle(with the empty phase only being run once), until BattleManager.startInput will be called to change the phase to “input”.
To keep things simple here, only the parts that are common to all the 3 different ways(battle tests, normal encounters and event encounters) of starting battles will be covered.
The common parts start from BattleManager.setup, which initializes the battle phase as empty in BattleManager.initMembers:

BattleManager.initMembers = function() {
    this._phase = "";
    this._inputting = false;
    this._canEscape = false;
    this._canLose = false;
    this._battleTest = false;
    this._eventCallback = null;
    this._preemptive = false;
    this._surprise = false;
    this._currentActor = null;
    this._actionForcedBattler = null;
    this._mapBgm = null;
    this._mapBgs = null;
    this._actionBattlers = [];
    this._subject = null;
    this._action = null;
    this._targets = [];
    this._logWindow = null;
    this._spriteset = null;
    this._escapeRatio = 0;
    this._escaped = false;
    this._rewards = {};
    this._tpbNeedsPartyCommand = true;
};

Then, regardless of how the battles are started, either of the following will be called to start the battle scene:

SceneManager.goto(Scene_Battle);
SceneManager.push(Scene_Battle);

At the beginning of the scene life cycle(too advanced to be covered here), Scene_Battle.prototype.create will be called to call Scene_Battle.prototype.createDisplayObjects as well, which calls Scene_Battle.prototype.createAllWindows:

Scene_Battle.prototype.createAllWindows = function() {
    this.createLogWindow();
    this.createStatusWindow();
    this.createPartyCommandWindow();
    this.createActorCommandWindow();
    this.createHelpWindow();
    this.createSkillWindow();
    this.createItemWindow();
    this.createActorWindow();
    this.createEnemyWindow();
    Scene_Message.prototype.createAllWindows.call(this);
};

Here, Scene_Battle.prototype.createPartyCommandWindow and Scene_Battle.prototype.createActorCommandWindow are methods creating the party and actor command windows respectively, and these 2 are the windows that are parts of the battle flow.
As the scene life cycle reaches Scene_Battle.prototype.start, BattleManager.startBattle will be called to change the phase to “start”:

BattleManager.startBattle = function() {
    this._phase = "start";
    $gameSystem.onBattleStart();
    $gameParty.onBattleStart(this._preemptive);
    $gameTroop.onBattleStart(this._surprise);
    this.displayStartMessages();
};

When the events that are supposed to be run upon battle start are finished(how this is exactly done is too advanced to be covered here), Scene_Battle.prototype.update will call Scene_Battle.prototype.updateBattleProcess, which will call BattleManager.update, causing BattleManager.updatePhase to be called as well(frame updates in battle flow are too advanced to be covered here), and so BattleManager.updateStart will be called to call BattleManager.startInput, in order to change the phase to “input”, meaning that the battle is finally fully started:

BattleManager.startInput = function() {
    this._phase = "input";
    this._inputting = true;
    $gameParty.makeActions();
    $gameTroop.makeActions();
    this._currentActor = null;
    if (this._surprise || !$gameParty.canInput()) {
        this.startTurn();
    }
};

Input Actions
This phase starts from BattleManager.startInput and ends with BattleManager.startTurn, and it’s the phase where players can either try to escape the battle, or input all actions for all inputable party members, until BattleManager.startTurn is called to change the phase to “turn”, or BattleManager.processAbort is called to abort the battle.
First, Game_Unit.prototype.makeActions will be called, causing Game_Battler.prototype.makeActions to be called to make all battlers have their respective number of action slots determined by their respective Action Times+ at that moment:

Game_Battler.prototype.makeActions = function() {
    this.clearActions();
    if (this.canMove()) {
        const actionTimes = this.makeActionTimes();
        this._actions = [];
        for (let i = 0; i < actionTimes; i++) {
            this._actions.push(new Game_Action(this));
        }
    }
};

Note that Auto Battle and/or confused actors will automatically input all their action slots without player inputs because of Game_Actor.prototype.makeActions:

Game_Actor.prototype.makeActions = function() {
    Game_Battler.prototype.makeActions.call(this);
    if (this.numActions() > 0) {
        this.setActionState("undecided");
    } else {
        this.setActionState("waiting");
    }
    if (this.isAutoBattle()) {
        this.makeAutoBattleActions();
    } else if (this.isConfused()) {
        this.makeConfusionActions();
    }
};

Whereas all enemies will always automatically input all their action slots:

Game_Enemy.prototype.makeActions = function() {
    Game_Battler.prototype.makeActions.call(this);
    if (this.numActions() > 0) {
        const actionList = this.enemy().actions.filter(a =>
            this.isActionValid(a)
        );
        if (actionList.length > 0) {
            this.selectAllActions(actionList);
        }
    }
    this.setActionState("waiting");
};

As for inputability, an actor’s inputable if he/she/it’s alive, in battle and has no Restrictions enforced by states and no special flag Auto Battle.
As long as the party can input actions in the current turn(determined by whether it’s the 1st turn with a surprise battle start and whether any party member can input actions), this phase will proceed as follows:
1. Scene_Battle.prototype.changeInputWindow will call Scene_Battle.prototype.startPartyCommandSelection(its reasons are too advanced to be covered here), which setups the party command window:

Scene_Battle.prototype.changeInputWindow = function() {
    this.hideSubInputWindows();
    if (BattleManager.isInputting()) {
        if (BattleManager.actor()) {
            this.startActorCommandSelection();
        } else {
            this.startPartyCommandSelection();
        }
    } else {
        this.endCommandSelection();
    }
};
Scene_Battle.prototype.startPartyCommandSelection = function() {
    this._statusWindow.deselect();
    this._statusWindow.show();
    this._statusWindow.open();
    this._actorCommandWindow.setup(null);
    this._actorCommandWindow.close();
    this._partyCommandWindow.setup();
};

2a. If those players choose to escape, then Scene_Battle.prototype.commandEscape as the corresponding handler of the party command window(handlers are too advanced to be covered here) will be called to call BattleManager.processEscape.
The escape attempt will always succeed upon the 1st turn if the battle starts with preemptive, otherwise its probability of success is determined by the escape ratio at that moment, which is initially set as 0.5 * the average of agi of all party members in battle / the average of agi of all enemies in battle, and will increase by 0.1 per failed attempt.
2a(i). If the escape attempt succeeded, then BattleManager.onEscapeSucces will be called to call BattleManager.processAbort, which calls BattleManager.endBattle which the result argument as 1 to abort the battle(how battles are ended are too advanced to be covered here):

BattleManager.processAbort = function() {
    $gameParty.removeBattleStates();
    this._logWindow.clear();
    this.replayBgmAndBgs();
    this.endBattle(1);
};

2a(ii). If the escape attempt failed, then BattleManager.onEscapeFailure will be called to call BattleManager.startTurn, which starts the current turn and will be covered in the later parts of this post:

BattleManager.onEscapeFailure = function() {
    $gameParty.onEscapeFailure();
    this.displayEscapeFailureMessage();
    this._escapeRatio += 0.1;
    if (!this.isTpb()) {
        this.startTurn();
    }
};

Note that Game_Party.prototype.onEscapeFailure will call Game_Actor.prototype.onEscapeFailure for all party members, and so Game_Actor.prototype.clearActions will be called to void all action slots:

Game_Actor.prototype.onEscapeFailure = function() {
    if (BattleManager.isTpb()) {
        this.applyTpbPenalty();
    }
    this.clearActions();
    this.requestMotionRefresh();
};
Game_Actor.prototype.clearActions = function() {
    Game_Battler.prototype.clearActions.call(this);
    this._actionInputIndex = 0;
};

2b. If those players choose to fight, then Scene_Battle.prototype.commandFight use select next command(covered in the later parts of this post) to let those players input all actions of all inputable party members sequentially.
3. Those players will first input the 1st action slot of the 1st inputable party member, then the 2nd, 3rd, and finally the last action slot of that member, and those players will proceed with the same sequence for the 2nd inputable party member, finally those players will repeat this sequence until the last action slot of the last inputable party member is inputted, with the restriction that those players can never break nor escape this sequence without inputting all action slots of all inputable party members.
4. When inputting actions for inputable party members, players can use the ok command to proceed to the next action slot of the current member, or from the last action slot of that member to the 1st action slot of the next member(or start the current turn upon finish inputting the last action slot of the last member).
The ok command is handled by the actor command window(how it’s setup is too advanced to be covered here) using the handler Scene_Battle.prototype.selectNextCommand, which calls BattleManager.selectNextCommand to call Game_Actor.prototype.selectNextCommand:

Scene_Battle.prototype.selectNextCommand = function() {
    BattleManager.selectNextCommand();
    this.changeInputWindow();
};
BattleManager.selectNextCommand = function() {
    if (this._currentActor) {
        if (this._currentActor.selectNextCommand()) {
            return;
        }
        this.finishActorInput();
    }
    this.selectNextActor();
};
Game_Actor.prototype.selectNextCommand = function() {
    if (this._actionInputIndex < this.numActions() - 1) {
        this._actionInputIndex++;
        return true;
    } else {
        return false;
    }
};

5. Similarly, players can use the cancel command to proceed to the previous action slot of the current member, or from the 1st action slot of that member to the last action slot of the previous member(or setup the party command window upon cancelling the input of the 1st action slot of the 1st member).
The cancel command is handled by the actor command window using the handler Scene_Battle.prototype.selectPreviousCommand, which calls BattleManager.selectPreviousCommand to call Game_Actor.prototype.selectPreviousCommand:

Scene_Battle.prototype.selectPreviousCommand = function() {
    BattleManager.selectPreviousCommand();
    this.changeInputWindow();
};
BattleManager.selectPreviousCommand = function() {
    if (this._currentActor) {
        if (this._currentActor.selectPreviousCommand()) {
            return;
        }
        this.cancelActorInput();
    }
    this.selectPreviousActor();
};
Game_Actor.prototype.selectPreviousCommand = function() {
    if (this._actionInputIndex > 0) {
        this._actionInputIndex--;
        return true;
    } else {
        return false;
    }
};

6. While the exact traversals of this doubly linked list are too advanced to be covered here, the party command window(head sentinel node) and the turn start(tail sentinel node) are the start and end of this sequence respectively, while the ok and cancel commands are single steps for moving forward(next pointer) and backward(previous pointer) respectively.

Process Turns
To be precise, there are 2 phases in this part, which are “turn” and “turnEnd”.
The “turn” phase starts from having BattleManager.startTurn called upon inputting the last action slot of the last inputable party member, and ends with calling BattleManager.startAction to change the phase to “action”, or BattleManager.endTurn to change the phase to “turnEnd”:

BattleManager.startTurn = function() {
    this._phase = "turn";
    $gameTroop.increaseTurn();
    $gameParty.requestMotionRefresh();
    if (!this.isTpb()) {
        this.makeActionOrders();
        this._logWindow.startTurn();
        this._inputting = false;
    }
};

This changes the phase to “turn” and increases the battle turn count by 1.
Then, by calling BattleManager.makeActionOrders, the action order queue descendingly sorted by the speed of all battlers(the faster the battlers are the more up front they’re on this queue) at this moment will have all the inputted actions of all those battlers, with the ordering of all actions among the same battler unchanged from his/her/its action slot input sequence:

BattleManager.makeActionOrders = function() {
    const battlers = [];
    if (!this._surprise) {
        battlers.push(...$gameParty.battleMembers());
    }
    if (!this._preemptive) {
        battlers.push(...$gameTroop.members());
    }
    for (const battler of battlers) {
        battler.makeSpeed();
    }
    battlers.sort((a, b) => b.speed() - a.speed());
    this._actionBattlers = battlers;
};

Note that the speed of a battler is determined by the fastest action slot inputted by that battler(the skill/item with the lowest Speed).
After that, all battle events which should be run upon turn start will be run(how this is exactly done is too advanced to be covered here), and then BattleManager.updatePhase will call BattleManager.updateTurn:

BattleManager.updateTurn = function(timeActive) {
    $gameParty.requestMotionRefresh();
    if (this.isTpb() && timeActive) {
        this.updateTpb();
    }
    if (!this._subject) {
        this._subject = this.getNextSubject();
    }
    if (this._subject) {
        this.processTurn();
    } else if (!this.isTpb()) {
        this.endTurn();
    }
};

If there’s no action execution subject, BattleManager.getNextSubject will be used as a try to find the most up front alive battler in the action order queue at that moment, with all the dead ones removed from the queue before an alive one is found, and having found such a battler means that battler will be removed from the queue as well:

BattleManager.getNextSubject = function() {
    for (;;) {
        const battler = this._actionBattlers.shift();
        if (!battler) {
            return null;
        }
        if (battler.isBattleMember() && battler.isAlive()) {
            return battler;
        }
    }
};

If no such battler’s found, then the phase will change to “turnEnd” by calling BattleManager.endTurn(which will be covered in the later parts of this post).
If such a battler’s found, he/she/it’ll be the new action subject, and BattleManager.processTurn will be called to try to execute inputted actions of that battler:

BattleManager.processTurn = function() {
    const subject = this._subject;
    const action = subject.currentAction();
    if (action) {
        action.prepare();
        if (action.isValid()) {
            this.startAction();
        }
        subject.removeCurrentAction();
    } else {
        this.endAction();
        this._subject = null;
    }
};

An action is said to be valid upon execution if it’s forced or its user meets all the conditions of the corresponding skill/item upon execution.
If the action execution subject has no valid actions to execute, then BattleManager.endAction will be called(this will be covered in the later parts of this post), which will cause BattleManager.updateTurn to be called again later, meaning that another action execution subject has to be found, or the turn will just end.
If the action execution subject has valid actions to execute, then all the invalid ones will be discarded and the valid ones will be executed sequentially, by calling BattleManager.startAction, which makes the target queue of the current action to be executed and changes the phase to “action”:

BattleManager.startAction = function() {
    const subject = this._subject;
    const action = subject.currentAction();
    const targets = action.makeTargets();
    this._phase = "action";
    this._action = action;
    this._targets = targets;
    subject.cancelMotionRefresh();
    subject.useItem(action.item());
    this._action.applyGlobal();
    this._logWindow.startAction(subject, action, targets);
};

The “turnEnd” phase starts from having BattleManager.endTurn called upon having no more action execution subject to be found nor execute valid actions not yet executed, and ends with later calling BattleManager.updatePhase, which calls BattleManager.updateTurnEnd to change the phase to “start”:

BattleManager.endTurn = function() {
    this._phase = "turnEnd";
    this._preemptive = false;
    this._surprise = false;
};
BattleManager.updateTurnEnd = function() {
    if (this.isTpb()) {
        this.startTurn();
    } else {
        this.endAllBattlersTurn();
        this._phase = "start";
    }
};

Execute Actions
It basically starts from BattleManager.startAction and ends with BattleManager.endAction to change the phase to “turn”.
It’s the phase where the current action execution subject will, after discarding all the invalid actions, execute all the valid ones sequentially, which the ordering unchanged from the action slot input sequence of that subject.
As far as only the current action execution subject is concerned, this phase will proceed as follows:
1. The 1st valid action that aren’t executed yet will be executed after showing its start using the battle log window(how Window_BattleLog works is too advanced to be covered here).
2. Upon the start of the execution, BattleManager.updatePhase will call BattleManager.updateAction, which tries to find the 1st target in the target queue of the action to be executed:

BattleManager.updateAction = function() {
    const target = this._targets.shift();
    if (target) {
        this.invokeAction(this._subject, target);
    } else {
        this.endAction();
    }
};

If such target’s found, that target will be removed from the queue and BattleManager.invokeAction will be called:

BattleManager.invokeAction = function(subject, target) {
    this._logWindow.push("pushBaseLine");
    if (Math.random() < this._action.itemCnt(target)) {
        this.invokeCounterAttack(subject, target);
    } else if (Math.random() < this._action.itemMrf(target)) {
        this.invokeMagicReflection(subject, target);
    } else {
        this.invokeNormalAction(subject, target);
    }
    subject.setLastTarget(target);
    this._logWindow.push("popBaseLine");
};

For now, you just need to know that Window_BattleLog is way more than just a battle log window, as it actually coordinates all the visual display sequences in the battle flow(also too advanced to be covered here).
If no such target’s found, then BattleManager.endAction will be called to change the phase to “turn”:

BattleManager.endAction = function() {
    this._logWindow.endAction(this._subject);
    this._phase = "turn";
    if (this._subject.numActions() === 0) {
        this.endBattlerActions(this._subject);
        this._subject = null;
    }
};

Summary
The battle first starts with the empty phase.
The empty phase will always change to “start” after finished preparing to start the battle.
The “start” phase will always change to “input” after finished starting the battle to try to let players input actions for all inputable party members.
All battlers will use their respective Action Times+ at that moment to determine their respectively number of action slots they can have in the current turn.
If there’s no such member or the battle starts with surprise, the battle phase will immediately change to “turn”.
Otherwise players will either try to escape the battle, or sequentially input from the 1st action slot of the 1st inputable party member to the last one of the last such member.
A sucess escape attempt will abort the battle while a failed one will change the phase to “turn” without inputting any action slot of any inputable party member.
The battle phase will change to “turn” when all actions slots of all inputable party members are inputted.
The “turn” phase will try to sequentially execute actions from the 1st inputted valid ones of the fastest alive battler at that moment to the last inputted valid ones of the slowest alive battler at that moment.
Whenever the 1st inputted valid action not executed yet by the current action execution subject is to be executed now, the phase will change to “action”.
When there are no more alive battlers left to execute valid actions that aren’t executed yet, the phase will change to “turnEnd”, which will soon change to “start”.
The “action” phase will try to sequentially invoke the currently valid action to be executed into each of its targets and remove that target from the action target queue.
When that action target queue has no more targets, the phase will change to “turn”.

That’s all for now. I hope this can help you grasp these basic knowledge. For those thoroughly comprehending the essence of the default RMMZ turn based battle flow implementations, feel free to correct me if there’s anything wrong :D
For those wanting to have a solid understanding to the default RMMZ turn based battle flow implementations, I might open a more advanced topic for that later