Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Messages - DoubleX

1
Advertising / DoubleX Music Room
May 07, 2023, 10:04:00 am
I never thought even I could make some music, but I don't know if mine would be too unpleasant to hear, so it takes me some courage to share them here :)

DoubleX - Everyone Turning Against You
"Description": ShowHide

Current version: 3rd(30 Apr 2023)

I just had a rather special dream in my sleep, although I already can't remember every last bit of its details precisely.

During this dream, I was watching a short movie, with its male protagonist suddenly being betrayed by just about everyone around him, including his beloved wife.
Even though it's clear to him that she was forced to do so, he still had to kill her personally to protect his sons and daughters, just as a slightly tragic melody started playing, with him recalling all the good memories with them within his family before this.
The situation ended up with total chaos and he was driven into total madness. Then I just woke up from the dream before I could watch the rest of the movie(that's why the melody's so short), but this doesn't feel like a nightmare to me, despite the fact that I slept quite poorly that night.

Because I want to remember that short melody, I composed this easy, simple and small song based on it, and it's done via 1BITGRADON within 8 hours.
I hope that this song, being my 1st published one, won't be too much of an earsore for too many of you :)
2
DoubleX_RMMV_RMMZ_Event_Text_Extractor
Authors: DoubleX
Version: v1.00a
Type: Event Text Add-on
Key Term: Game Utility



Note
This plugin works for both RMMV and RMMZ

Purpose
Lets you extract texts in events/common events/battle events to txt file

Video


Games using this plugin
None so far

"Parameters": ShowHide

 * @param fileName
 * @type string
 * @desc Sets the name of the txt file having those extracted texts
 * @default Extracted Event Texts
 *
 * @param filePath
 * @type string
 * @desc Sets the path of the txt file having those extracted texts
 * Leaving it empty means placing the file at project root directory
 * @default


"Prerequisites": ShowHide

Abilities:
1. Nothing special


"Terms Of Use": ShowHide

*      1. Commercial use's always allowed and crediting me's always optional.
*      2. You shall keep this plugin's Plugin Info part's contents intact.
*      3. You shalln't claim that this plugin's written by anyone other than
*        DoubleX or my aliases. I always reserve the right to deny you from
*        using any of my plugins anymore if you've violated this.
*      4. If you repost this plugin directly(rather than just linking back),
*        you shall inform me of these direct repostings. I always reserve
*        the right to request you to edit those direct repostings.
*      5. CC BY 4.0, except those conflicting with any of the above, applies
*        to this plugin, unless you've my permissions not needing follow so.
*      6. I always reserve the right to deny you from using this plugin
*        anymore if you've violated any of the above.


"Contributors": ShowHide

*      Authors:
*      1. DoubleX
*      Plugin Development Collaborators:
*      - None So Far
*      Bug Reporters:
*      - None So Far
*      Compatibility Issue Raisers:
*      - None So Far
*      Feature Requesters:
*      - None So Far


"Changelog": ShowHide

 *      { codebase: "1.4.4", plugin: "v1.00a" }(2022 Apr 15 GMT 1300):
 *      1. 1st version of this plugin finished


Download Link
Demo Link
3
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)

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": ShowHide

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": ShowHide

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": ShowHide

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": ShowHide

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": ShowHide

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": ShowHide

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": ShowHide

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


"Turn End Phase": ShowHide

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": ShowHide

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": ShowHide

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": ShowHide

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
4
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 ;)
5
Updates
 *      { codebase: "1.1.1", plugin: "v1.02a" }(2021 Feb 7 GMT 1300):
 *      1. Added skillItemCooldownGaugeColor1 and skillItemCooldownGaugeColor2
 *         to let you show the TPB battler cooldown bar inside battles with
 *         configurable colors
 *      2. Added cancelBattlerCooldownHotkeys and
 *         cancelSkillItemCooldownHotkeys to let you set some hotkeys to
 *         cancel the battler/skill item cooldown of the corresponding actors
 *         respectively
 *      3. Added the following parameters:
 *         - canCancelBattlerCooldown
 *         - canCancelSkillItemCooldown
 *         - cancelBattlerCooldownFail
 *         - cancelSkillItemCooldownFail
 *         - cancelBattlerCooldownSuc
 *         - cancelSkillItemCooldownSuc
 *         - canCancelBattlerCooldownNotetagDataTypePriorities
 *         - canCancelSkillItemCooldownNotetagDataTypePriorities
 *         - cancelBattlerCooldownFailNotetagDataTypePriorities
 *         - cancelSkillItemCooldownFailNotetagDataTypePriorities
 *         - cancelBattlerCooldownSucNotetagDataTypePriorities
 *         - cancelSkillItemCooldownSucNotetagDataTypePriorities
 *      4. Added the following plugin commands:
 *         - canCancelBattlerCooldown
 *         - canCancelSkillItemCooldown
 *         - cancelBattlerCooldown
 *         - cancelSkillItemCooldown
 *      5. Added the following notetags:
 *         - canCancelBattler
 *         - canCancelSkillItem
 *         - cancelBattlerFail
 *         - cancelSkillItemFail
 *         - cancelBattlerSuc
 *         - cancelSkillItemSuc
6
I just received an email like this:
Title: Notification Case #(Some random numbers)
Sender: (Non-Paypal logo)service@paypal.com.(My PayPal account location) <(Non-PayPal email used by the real scammers)>
Recipients: (My email), (The email of an innocent straw man used by the real scammers)
Contents(With UI styles copying those in real PayPal emails):
Someone has logged into your account
We noticed a new login with your PayPal account associated with (The email of an innocent straw man used by the real scammers) from a device we don't recognize. Because of that we've temporarily limited your account until you renew and verify your identity.
Please click the button below to login into your account for verify your account.
(Login button copying that in real Paypal emails)
If this was you, please disregard this email.
(Footers copying those in real PayPal emails)

I admit that I'm incredibly stupid, because I almost believed that it's a real PayPal email, and I only realized that it's a scam right after I've clicked the login button, because it links to a URL that's completely different from the login page of the real PayPal(so fortunately I didn't input anything there).
While I've faced many old-schooled phishing emails and can figure them all out right from the start, I've never seen phishing emails like this, and what makes me feel even more dumb is that I already have 2FA applied to my PayPal account before receiving this scam email, meaning that my phone would've a PayPal verification SMS out of nowhere if there was really an unauthorized login to my account.

Of course, that straw man email owner is completely innocent, and I believe that owner already received the same scam email with me being the straw man, so that owner might think that I really performed unauthorized login into his/her PayPal account, if he/she didn't realize that the whole email's just a scam.
Before I realized that it's just a scam, I thought he/she really done what the email claims as well, so I just focused on logging into my PayPal accounts to assess the damages done and evaluate countermeasures to be taken, and if I didn't realize that it's just a scam, I'd already have given the password of my PayPal account to the scammers in their fake PayPal login page.

I suspect that many more PayPal users might have already received/are going to receive such scam emails, and I think this way of phishing can work for many other online payment gateways as well, so I think I can do some good by sharing my case, to hope that only I'll be this dumb(even though I didn't give the scammers my Paypal password at the end).
7
Mathematics / Using Abel-Ruffini theorem on encryptions
January 25, 2021, 07:54:12 am
The complete microsoft word file can be downloaded here(as a raw file)
 
Summary
 
The whole password setup/change process is as follows:
1. The client inputs the user ID and its password in plaintext
2. A salt for hashing the password in plaintexts will be randomly generated
3. The password will be combined with a fixed pepper in the client software source code and the aforementioned salt, to be hashed in the client terminal by SHA3-512 afterwards
4. The hashed password as a hexadecimal number with 128 digits will be converted to a base 256 number with 64 digits, which will be repeated 8 times in a special manner, and then broken down into a list of 512 literals, each being either numeric literals 1 to 100 or any of the 156 named constants
5. Each of those 512 numeric literals or named constants will be attached with existing numeric literals and named constants via different ways and combinations of additions, subtractions, multiplications and divisions, and the whole attachment process is determined by the fixed pepper in the client software source code
6. The same attachment process will be repeated, except that this time it's determined by a randomly generated salt in the client terminal
7. That list of 512 distinct roots, with the ordering among all roots and all their literal expressions preserved, will produce the resultant polynomial equation of degree 512
8. The resultant polynomial equation will be encoded into numbers and number separators in the client terminal
9. The encoded version will be encrypted by RSA-4096 on the client terminal with a public key there before being sent to the server, which has the private key
10. The server decrypts the encrypted polynomial equation from the client with its RSA-4096 private key, then decode the decrypted version in the server to recover the original polynomial equation, which will finally be stored there
11. The 2 aforementioned different salts will be encrypted by 2 different AES-256 keys in the client software source code, and their encrypted versions will be sent to the server to be stored there
12. The time complexity of the whole process, except the SHA3-512, RSA-4096 and AES-256, should be controlled to quadratic time
 
The whole login process is as follows:
1. The client inputs the user ID and its password in plaintext
2. The client terminal will send the user ID to the server, which will send its corresponding salts for hashing the password in plaintexts and forming distinct roots respectively, already encrypted in AES-256 back to the client terminal, assuming that the user ID from the client does exist in the server(otherwise the login fails and nothing will be sent back from the server)
3. The password will be combined with a fixed pepper in the client software source code, and the aforementioned salt that is decrypted in the client terminal using the AES-256 key in the client software source code, to be hashed in the client terminal by SHA3-512 afterwards
4. The hashed password as a hexadecimal number with 128 digits will be converted to a base 256 number with 64 digits, which will be repeated 8 times in a special manner, and then broken down into a list of 512 literals, each being either numeric literals 1 to 100 or any of the 156 named constants
5. Each of those 512 numeric literals or named constants will be attached with existing numeric literals and named constants via different ways and combinations of additions, subtractions, multiplications and divisions, and the whole attachment process is determined by the fixed pepper in the client software source code
6. The same attachment process will be repeated, except that this time it's determined by the corresponding salt sent from the server that is decrypted in the client terminal using a different AES-256 key in the client software source code
7. That list of 512 distinct roots, with the ordering among all roots and all their literal expressions preserved, will produce the resultant polynomial equation of degree 512
8. The resultant polynomial equation will be encoded into numbers and number separators in the client terminal
9. The encoded version will be encrypted by RSA-4096 on the client terminal with a public key there before being sent to the server, which has the private key
10. The server decrypts the encrypted polynomial equation from the client with its RSA-4096 private key, then decode the decrypted version in the server to recover the original polynomial equation
11. Whether the login will succeed depends on if the literal expression of the polynomial equation from the client exactly matches the expected counterpart already stored in the server
12. The time complexity of the whole process, except the SHA3-512, RSA-4096 and AES-256, should be controlled to quadratic time
 
For an attacker trying to get the raw password in plaintext:
1. If the attacker can only sniff the transmission from the client to the server to get the encoded then encrypted version(which is then encrypted by RSA-4096) of the polynomial equation, the salt of its roots, and the counterpart for the password in plaintext, the attacker first have to break RSA-4096, then the attacker has to figure out the highly secret and obfuscated algorithm to decode those numbers and number separators into the resultant polynomial equation and the way its roots are attached by existing numeric literals and named constants
2. If the attacker has the resultant polynomial equation of degree 512, its roots must be found, but there's no direct formula to do so analytically due to Abel-Ruffini theorem, and factoring such a polynomial with 156 different named constants efficiently is very, very complicated and convoluted
3. If the attacker has direct access to the server, the expected polynomial equation can be retrieved, but the attacker still has to solve that polynomial equation of degree 512 to find all its roots with the right ordering among them and all their correct literal expressions
4. If the attacker has direct access to the client software source codes, the pepper for hashing the password in plaintext, the pepper used on the polynomial equation roots, and the highly secret and obfuscated algorithm for using them with the salt counterparts can be retrieved, but it's still far from being able to find all the roots of the expected polynomial equation of degree 512
5. If the attacker has all those roots, the right ordering among them and all their correct literal expressions still have to be figured out, and the salts and peppers for those roots has to be properly removed as well
6. If the attacker has all those roots with the right ordering among them, all their correct literal expressions, and salts and peppers on them removed, the attacker has effectively recovered the hashed password, which is mixed with salts and peppers in plaintext
7. The attacker then has to figure out the password in plaintext even with the hashing function, salt, pepper, and the highly secret and obfuscated algorithm that combines them known
8. Unless there are really efficient algorithms for every step involved, the time complexity of the whole process can be as high as factorial time
9. As users are still inputting passwords in plaintexts, dictionary attacks still work to some extent, but if the users are careless with their password strengths, then no amount of cryptography will be safe enough
10. Using numerical methods to find all the roots won't work in most cases, because such methods are unlikely to find those roots analytically, let alone with the right ordering among them and all their right literal expressions, which are needed to produce the resultant polynomial equation with literal expressions exactly matching the expected one
11. Using rainbow tables won't work well either, because such table would be way too large to be used in practice, due to the number of polynomial equations with degree 512 being unlimited in theory
12. Strictly speaking, the whole password encryption scheme isn't a one-way function, but the time complexity needed for encryption compared to that for decryption is so trivial that this scheme can act like such a function
 
Areas demanding further researches:
1. The time complexity for factoring a polynomial of degree n with named constants into n factors analytically
2. Possibilities of collisions from the ordering among all roots and all their different literal expressions
3. Existence of efficient algorithms on finding the right ordering among all roots and all their right literal expressions
4. Strategies on setting up the fixed peppers and generating random salts to form roots with maximum encryption strength
 
Essentially, the whole approach on using polynomial equations for encryptions is to exploit equations that are easily formed by their analytical solution sets but very hard to solve analytically, especially when exact literal matches, rather than just mathematical identity, are needed to match the expected equations.
So it's not strictly restricted to polynomial equations with a very high degree, but maybe very high order partial differential equations with many variables, complex coefficients and functions accepting complex numbers can also work, because there are no known analytical algorithm on solving such equations yet, but analytical solutions are demanded to reproduce the same partial differential equations with exact literal matches, as long as performing partial differentiations analytically can be efficient enough.
8
Updates
 *      { codebase: "1.1.1", plugin: "v1.01a" }(2020 Dec 26 GMT 1300):
 *      1. Added the following notetag types:
 *         subjectMiss
 *         subjectEva
 *         subjectCnt
 *         subjectMrf
 *         subjectCri
 *         subjectNorm
 *         subjectSubstitute
 *      2. Added the following parameters:
 *         subjectMissNotetagDataTypePriorities
 *         subjectEvaNotetagDataTypePriorities
 *         subjectCntNotetagDataTypePriorities
 *         subjectMrfNotetagDataTypePriorities
 *         subjectCriNotetagDataTypePriorities
 *         subjectNormNotetagDataTypePriorities
 *         subjectSubstituteNotetagDataTypePriorities
 *      3. Fixed the eventEntry of all notetags not correctly accepting all
 *         intended suffixes and rejecting the unintended ones
You'll need the latest version of DoubleX RMMZ Enhanced Codebase as well :)
9
Updates
*      - v0.15c(GMT 0700 11-Dec-2020):
*        1. Fixed the following wrong documentations:
*          Battler manipulations -
*          i. setDelaySecCounter should be setSATBDelaySecCounter
*          ii. addDelaySecCounter should be addSATBDelaySecCounter
*          iii. multiplyDelaySecCounter should be
*                multiplySATBDelaySecCounter
*          iv. delaySecCounter should be satbDelaySecCounter
*        2. Added the action sequence for the Delay Module in
*          Yanfly Engine Plugins - Battle Engine Core
*        3. Lets players cancels actor cooldown by clicking the actor sprite
*        4. Lets players cancels actor charge by clicking the actor sprite

10
Updates
*      { codebase: "1.1.0", plugin: "v1.00b" }(2020 Dec 11 GMT 0400):
*      1. Adding the plugin command and query counterpart of the
*        isTPBSCountdownState battler manipulation
*      2. Documented the isTPBSCountdownState battler manipulation
*      3. Fixed the bug of not removing countdown states nor triggering
*        effects from plugin DoubleX RMMZ State Triggers
11
Updates
*      - v0.15b(GMT 0400 7-Dec-2020):
 *        1. You no longer have to edit the value of
 *           DoubleX_RMMZ.Superlative_ATB_Parameters_File when changing the
 *           parameter plugin file name
 *        2. Fixed the wrong this of the following Array prototype methods:
 *           i. fastFilter
 *           ii. fastMap
 *           iii. filterMap
 *           iv. mapFilter
 *           v. mapReduce
 *           vi. mapSome
 *        3. Fixed the x and y positions and opacity update bugs for discrete
 *           order battler sprites
 *        4. Fixed wrong unit test check conditions for the x and y positions
 *           and opacity for discrete order battler sprites
12
RMMZ Script Database / Re: [MZ] DoubleX RMMZ TPBS CTB
December 02, 2020, 05:14:48 am
Updates
*      { codebase: "1.1.0", plugin: "v1.00b" }(2020 Dec 2 GMT 1000):
 *      1. You no longer have to edit the value of
 *         DoubleX_RMMZ.TPBS_CTB.PLUGIN_NAME when changing this plugin file
 *         name
13
Updates
*      { codebase: "1.1.0", plugin: "v1.00b" }(2020 Dec 2 GMT 1000):
 *      1. You no longer have to edit the value of
 *         DoubleX_RMMZ.TPBS_Battle_Turns.PLUGIN_NAME when changing this
 *         plugin file name
14
Updates
*      { codebase: "1.1.0", plugin: "v1.00b" }(2020 Dec 2 GMT 1000):
 *      1. You no longer have to edit the value of
 *         DoubleX_RMMZ.TPBS_Actor_Hotkeys.PLUGIN_NAME when changing this
 *         plugin file name
15
Updates
*      { codebase: "1.1.0", plugin: "v1.00b" }(2020 Dec 2 GMT 0900):
 *      1. You no longer have to edit the value of
 *         DoubleX_RMMZ.Targeting_Hotkeys.PLUGIN_NAME when changing this
 *         plugin file name
16
Updates
*      { codebase: "1.1.0", plugin: "v1.00b" }(2020 Dec 2 GMT 0800):
 *      1. You no longer have to edit the value of
 *         DoubleX_RMMZ.Script_Call_Hotkeys.PLUGIN_NAME when changing this
 *         plugin file name
17
RMMZ Script Database / Re: [MZ] DoubleX RMMZ Plugin Query
December 02, 2020, 02:02:13 am
Updates
*      { codebase: "1.1.0", plugin: "v1.00b" }(2020 Dec 2 GMT 0700):
 *      1. You no longer have to edit the value of
 *         DoubleX_RMMZ.Plugin_Query.PLUGIN_NAME when changing this plugin
 *         file name
18
Updates
*      { codebase: "1.1.0", plugin: "v1.00b" }(2020 Dec 2 GMT 0700):
 *      1. You no longer have to edit the value of
 *         DoubleX_RMMZ.Custom_Script_Calls.PLUGIN_NAME when changing this
 *         plugin file name
19
Updates
*      { codebase: "1.1.0", plugin: "v1.00b" }(2020 Dec 2 GMT 0600):
 *      1. You no longer have to edit the value of
 *         DoubleX_RMMZ.Custom_Key_Maps.PLUGIN_NAME when changing this plugin
 *         file name
20
Updates
*      { codebase: "1.1.0", plugin: "v1.00b" }(2020 Dec 2 GMT 0400):
 *      1. You no longer have to edit the value of
 *         DoubleX_RMMZ.Auto_Battle_Command.PLUGIN_NAME when changing this
 *         plugin file name