Bug - Restore move route - index skip

● ARCHIVED · READ-ONLY
Started by caethyril 1 posts View original ↗
  1. Edit: this bug is fixed in v1.2.1 of the core scripts.​


    Seen in RMMZ core scripts up to the current version (v1.2.0).

    Description​

    Events can have an auto move route assigned. If given an "active" route, e.g. via the Set Movement Route command, the auto route will be restored when the active one completes. On restore, the auto route's index skips one command. This can cause unintentional offsets in event movements.​

    Steps to reproduce​

    1. Create an event with an auto move route that makes it walk in a loop.
    2. Give the event any active route (e.g. wait 60 frames) using the Set Movement Route event command.
    3. When the active route ends, the event's auto route will resume 1 command after where it was interrupted.
    Demo (v1.1.1): bug-MoveRestore.zip (Google Drive) [2.3 MB].
    • Interact with the NPC to give her an empty active route: she will skip one step in her auto walk loop.

    Technical explanation​

    When a character updates their move route, the route index is always advanced. This occurs even when the route has just ended and an autonomous route has been restored. In that case, the auto route's index advances once after being restored, before it can process a command. Supporting code excerpts (rmmz_objects.js v1.2.0):
    Spoiler
    JavaScript:
    Game_Character.prototype.updateRoutineMove = function() {
        if (this._waitCount > 0) {
            this._waitCount--;
        } else {
            this.setMovementSuccess(true);
            const command = this._moveRoute.list[this._moveRouteIndex];
            if (command) {
                this.processMoveCommand(command);
                this.advanceMoveRouteIndex();
            }
        }
    };
    
    Game_Character.prototype.processMoveCommand = function(command) {
        const gc = Game_Character;
        const params = command.parameters;
        switch (command.code) {
            case gc.ROUTE_END:
                this.processRouteEnd();
                break;
    // ... //
    }};
    
    Game_Character.prototype.processRouteEnd = function() {
        if (this._moveRoute.repeat) {
            this._moveRouteIndex = -1;
        } else if (this._moveRouteForcing) {
            this._moveRouteForcing = false;
            this.restoreMoveRoute();
        }
    };
    
    Game_Character.prototype.restoreMoveRoute = function() {
        this._moveRoute = this._originalMoveRoute;
        this._moveRouteIndex = this._originalMoveRouteIndex;
        this._originalMoveRoute = null;
    };

    Suggested fix!​

    Restore the autonomous move route to "memorized index - 1" on line 7555:
    JavaScript:
        this._moveRouteIndex = this._originalMoveRouteIndex - 1;
    This should counter the advanceMoveRouteIndex call immediately afterwards.​

    Temporary fix​

    Hook into the restoreMoveRoute method and adjust the index that way:
    JavaScript:
    (alias => {
        Game_Character.prototype.restoreMoveRoute = function() {
            alias.apply(this, arguments);
            this._moveRouteIndex--;  // not so fast!
        };
    })(Game_Character.prototype.restoreMoveRoute);
    This is not ideal: if the fix is applied twice, a new bug will appear.​

    [Edit: updated to clarify that the bug still exists in v1.2.0.]