Source: Game_Player.js

Game_Player.js

//-----------------------------------------------------------------------------
// Game_Player
//
// The game object class for the player. It contains event starting
// determinants and map scrolling functions.
/**
 * The game object class for the player. It contains event starting determinants and map scrolling functions.
 *
 * @class
 * @extends Game_Character
 */
function Game_Player() {
    this.initialize(...arguments);
}

Game_Player.prototype = Object.create(Game_Character.prototype);
Game_Player.prototype.constructor = Game_Player;

Game_Player.prototype.initialize = function() {
    Game_Character.prototype.initialize.call(this);
    this.setTransparent($dataSystem.optTransparent);
};

Game_Player.prototype.initMembers = function() {
    Game_Character.prototype.initMembers.call(this);
    this._vehicleType = "walk";
    this._vehicleGettingOn = false;
    this._vehicleGettingOff = false;
    this._dashing = false;
    this._needsMapReload = false;
    this._transferring = false;
    this._newMapId = 0;
    this._newX = 0;
    this._newY = 0;
    this._newDirection = 0;
    this._fadeType = 0;
    this._followers = new Game_Followers();
    this._encounterCount = 0;
};

/**
 * Clear player transfer data
 */
Game_Player.prototype.clearTransferInfo = function() {
    this._transferring = false;
    this._newMapId = 0;
    this._newX = 0;
    this._newY = 0;
    this._newDirection = 0;
};

/**
 * Get the player's followers
 *
 * @return {Game_Followers} The game followers object
 */
Game_Player.prototype.followers = function() {
    return this._followers;
};

/**
 * Refresh the player
 */
Game_Player.prototype.refresh = function() {
    const actor = $gameParty.leader();
    const characterName = actor ? actor.characterName() : "";
    const characterIndex = actor ? actor.characterIndex() : 0;
    this.setImage(characterName, characterIndex);
    this._followers.refresh();
};

Game_Player.prototype.isStopping = function() {
    if (this._vehicleGettingOn || this._vehicleGettingOff) {
        return false;
    }
    return Game_Character.prototype.isStopping.call(this);
};

/**
 * Reserve a transfer
 *
 * @param {number} mapId - The map id to transfer to
 * @param {number} x - The x coordinate to transfer to
 * @param {number} y - The y coordinate to transfer to
 * @param {number} d - The direction to face after transfer
 * @param {number} fadeType - The type of fade for the transfer
 */
Game_Player.prototype.reserveTransfer = function(mapId, x, y, d, fadeType) {
    this._transferring = true;
    this._newMapId = mapId;
    this._newX = x;
    this._newY = y;
    this._newDirection = d;
    this._fadeType = fadeType;
};

/**
 * Set up when a new game is started
 */
Game_Player.prototype.setupForNewGame = function() {
    const mapId = $dataSystem.startMapId;
    const x = $dataSystem.startX;
    const y = $dataSystem.startY;
    this.reserveTransfer(mapId, x, y, 2, 0);
};

/**
 * Request the map to reload
 */
Game_Player.prototype.requestMapReload = function() {
    this._needsMapReload = true;
};

/**
 * Check if the player is transferring
 *
 * @return {boolean} True if transferring
 */
Game_Player.prototype.isTransferring = function() {
    return this._transferring;
};

/**
 * Get the new map id of a transfer
 *
 * @return {number} The new map id
 */
Game_Player.prototype.newMapId = function() {
    return this._newMapId;
};

/**
 * Get the fade type of a transfer
 *
 * @return {number} The fade type
 */
Game_Player.prototype.fadeType = function() {
    return this._fadeType;
};

/**
 * Processing when the transfer occurs
 */
Game_Player.prototype.performTransfer = function() {
    if (this.isTransferring()) {
        this.setDirection(this._newDirection);
        if (this._newMapId !== $gameMap.mapId() || this._needsMapReload) {
            $gameMap.setup(this._newMapId);
            this._needsMapReload = false;
        }
        this.locate(this._newX, this._newY);
        this.refresh();
        this.clearTransferInfo();
    }
};

Game_Player.prototype.isMapPassable = function(x, y, d) {
    const vehicle = this.vehicle();
    if (vehicle) {
        return vehicle.isMapPassable(x, y, d);
    } else {
        return Game_Character.prototype.isMapPassable.call(this, x, y, d);
    }
};

/**
 * Get the vehicle the player is in
 *
 * @return {Game_Vehicle} The vehicle the player is in
 */
Game_Player.prototype.vehicle = function() {
    return $gameMap.vehicle(this._vehicleType);
};

/**
 * Check if the player is in the boat
 *
 * @return {boolean} True if in boat
 */
Game_Player.prototype.isInBoat = function() {
    return this._vehicleType === "boat";
};

/**
 * Check if the player is in the ship
 *
 * @return {boolean} True if in ship
 */
Game_Player.prototype.isInShip = function() {
    return this._vehicleType === "ship";
};

/**
 * Check if the player is in the airship
 *
 * @return {boolean} True if in airship
 */
Game_Player.prototype.isInAirship = function() {
    return this._vehicleType === "airship";
};

/**
 * Check if the player is in any vehicle
 *
 * @return {boolean} True if in vehicle
 */
Game_Player.prototype.isInVehicle = function() {
    return this.isInBoat() || this.isInShip() || this.isInAirship();
};

/**
 * Check if the player is normal
 *
 * @return {boolean} True if normal
 */
Game_Player.prototype.isNormal = function() {
    return this._vehicleType === "walk" && !this.isMoveRouteForcing();
};

/**
 * Check if the player is dashing
 *
 * @return {boolean} True if dashing
 */
Game_Player.prototype.isDashing = function() {
    return this._dashing;
};

/**
 * Check if the player is through as a result of debug inputs
 *
 * @return {boolean} True if in debug through mode
 */
Game_Player.prototype.isDebugThrough = function() {
    return Input.isPressed("control") && $gameTemp.isPlaytest();
};

/**
 * Check if the player is collided with
 *
 * @param {number} x - The x coordinate to check for collision
 * @param {number} y - The y coordinate to check for collision
 * @return {boolean} True if collided
 */
Game_Player.prototype.isCollided = function(x, y) {
    if (this.isThrough()) {
        return false;
    } else {
        return this.pos(x, y) || this._followers.isSomeoneCollided(x, y);
    }
};

/**
 * Get the center x coordinate
 *
 * @return {number} Center x coordinate
 */
Game_Player.prototype.centerX = function() {
    return ($gameMap.screenTileX() - 1) / 2;
};

/**
 * Get the center y coordinate
 *
 * @return {number} Center y coordinate
 */
Game_Player.prototype.centerY = function() {
    return ($gameMap.screenTileY() - 1) / 2;
};

/**
 * Center on the given position
 *
 * @param {number} x - The x position to center on
 * @param {number} y - The y position to center on
 * @return {undefined} Undefined is returned
 */
Game_Player.prototype.center = function(x, y) {
    return $gameMap.setDisplayPos(x - this.centerX(), y - this.centerY());
};

Game_Player.prototype.locate = function(x, y) {
    Game_Character.prototype.locate.call(this, x, y);
    this.center(x, y);
    this.makeEncounterCount();
    if (this.isInVehicle()) {
        this.vehicle().refresh();
    }
    this._followers.synchronize(x, y, this.direction());
};

Game_Player.prototype.increaseSteps = function() {
    Game_Character.prototype.increaseSteps.call(this);
    if (this.isNormal()) {
        $gameParty.increaseSteps();
    }
};

/**
 * Make the encounter count for the player
 */
Game_Player.prototype.makeEncounterCount = function() {
    const n = $gameMap.encounterStep();
    this._encounterCount = Math.randomInt(n) + Math.randomInt(n) + 1;
};

/**
 * Get a troop id to encounter
 *
 * @return {number} The troop id to encounter
 */
Game_Player.prototype.makeEncounterTroopId = function() {
    const encounterList = [];
    let weightSum = 0;
    for (const encounter of $gameMap.encounterList()) {
        if (this.meetsEncounterConditions(encounter)) {
            encounterList.push(encounter);
            weightSum += encounter.weight;
        }
    }
    if (weightSum > 0) {
        let value = Math.randomInt(weightSum);
        for (const encounter of encounterList) {
            value -= encounter.weight;
            if (value < 0) {
                return encounter.troopId;
            }
        }
    }
    return 0;
};

/**
 * Check if an encounter meets conditions
 *
 * @param {Object} encounter - The encounter object to check
 * @return {boolean} True if conditions are met
 */
Game_Player.prototype.meetsEncounterConditions = function(encounter) {
    return (
        encounter.regionSet.length === 0 ||
        encounter.regionSet.includes(this.regionId())
    );
};

/**
 * Start an encounter
 *
 * @return {boolean} True if encounter succeeded
 */
Game_Player.prototype.executeEncounter = function() {
    if (!$gameMap.isEventRunning() && this._encounterCount <= 0) {
        this.makeEncounterCount();
        const troopId = this.makeEncounterTroopId();
        if ($dataTroops[troopId]) {
            BattleManager.setup(troopId, true, false);
            BattleManager.onEncounter();
            return true;
        } else {
            return false;
        }
    } else {
        return false;
    }
};

/**
 * Start an event on the map
 *
 * @param {number} x - The x coordinate of the event
 * @param {number} y - The y coordinate of the event
 * @param {number[]} triggers - The event's triggers
 * @param {boolean} normal - If the priority should be normal or not
 */
Game_Player.prototype.startMapEvent = function(x, y, triggers, normal) {
    if (!$gameMap.isEventRunning()) {
        for (const event of $gameMap.eventsXy(x, y)) {
            if (
                event.isTriggerIn(triggers) &&
                event.isNormalPriority() === normal
            ) {
                event.start();
            }
        }
    }
};

/**
 * Move the player with input
 */
Game_Player.prototype.moveByInput = function() {
    if (!this.isMoving() && this.canMove()) {
        let direction = this.getInputDirection();
        if (direction > 0) {
            $gameTemp.clearDestination();
        } else if ($gameTemp.isDestinationValid()) {
            const x = $gameTemp.destinationX();
            const y = $gameTemp.destinationY();
            direction = this.findDirectionTo(x, y);
        }
        if (direction > 0) {
            this.executeMove(direction);
        }
    }
};

/**
 * Check if the player can move
 *
 * @return {boolean} True if the player can move
 */
Game_Player.prototype.canMove = function() {
    if ($gameMap.isEventRunning() || $gameMessage.isBusy()) {
        return false;
    }
    if (this.isMoveRouteForcing() || this.areFollowersGathering()) {
        return false;
    }
    if (this._vehicleGettingOn || this._vehicleGettingOff) {
        return false;
    }
    if (this.isInVehicle() && !this.vehicle().canMove()) {
        return false;
    }
    return true;
};

/**
 * Get the direction of input
 *
 * @return {number} The direction of input
 */
Game_Player.prototype.getInputDirection = function() {
    return Input.dir4;
};

/**
 * Move the player
 *
 * @param {number} direction - The direction to move
 */
Game_Player.prototype.executeMove = function(direction) {
    this.moveStraight(direction);
};

/**
 * Update the player
 *
 * @param {boolean} sceneActive - If the scene is active
 */
Game_Player.prototype.update = function(sceneActive) {
    const lastScrolledX = this.scrolledX();
    const lastScrolledY = this.scrolledY();
    const wasMoving = this.isMoving();
    this.updateDashing();
    if (sceneActive) {
        this.moveByInput();
    }
    Game_Character.prototype.update.call(this);
    this.updateScroll(lastScrolledX, lastScrolledY);
    this.updateVehicle();
    if (!this.isMoving()) {
        this.updateNonmoving(wasMoving, sceneActive);
    }
    this._followers.update();
};

/**
 * Update dash
 */
Game_Player.prototype.updateDashing = function() {
    if (this.isMoving()) {
        return;
    }
    if (this.canMove() && !this.isInVehicle() && !$gameMap.isDashDisabled()) {
        this._dashing =
            this.isDashButtonPressed() || $gameTemp.isDestinationValid();
    } else {
        this._dashing = false;
    }
};

/**
 * Check if dash button is being pressed
 *
 * @return {boolean} True if dash button is pressed
 */
Game_Player.prototype.isDashButtonPressed = function() {
    const shift = Input.isPressed("shift");
    if (ConfigManager.alwaysDash) {
        return !shift;
    } else {
        return shift;
    }
};

/**
 * Update scroll
 *
 * @param {number} lastScrolledX - The last scroll x position
 * @param {number} lastScrolledY - The last scroll y position
 */
Game_Player.prototype.updateScroll = function(lastScrolledX, lastScrolledY) {
    const x1 = lastScrolledX;
    const y1 = lastScrolledY;
    const x2 = this.scrolledX();
    const y2 = this.scrolledY();
    if (y2 > y1 && y2 > this.centerY()) {
        $gameMap.scrollDown(y2 - y1);
    }
    if (x2 < x1 && x2 < this.centerX()) {
        $gameMap.scrollLeft(x1 - x2);
    }
    if (x2 > x1 && x2 > this.centerX()) {
        $gameMap.scrollRight(x2 - x1);
    }
    if (y2 < y1 && y2 < this.centerY()) {
        $gameMap.scrollUp(y1 - y2);
    }
};

/**
 * Update player vehicle
 */
Game_Player.prototype.updateVehicle = function() {
    if (this.isInVehicle() && !this.areFollowersGathering()) {
        if (this._vehicleGettingOn) {
            this.updateVehicleGetOn();
        } else if (this._vehicleGettingOff) {
            this.updateVehicleGetOff();
        } else {
            this.vehicle().syncWithPlayer();
        }
    }
};

/**
 * Update getting on a vehicle
 */
Game_Player.prototype.updateVehicleGetOn = function() {
    if (!this.areFollowersGathering() && !this.isMoving()) {
        this.setDirection(this.vehicle().direction());
        this.setMoveSpeed(this.vehicle().moveSpeed());
        this._vehicleGettingOn = false;
        this.setTransparent(true);
        if (this.isInAirship()) {
            this.setThrough(true);
        }
        this.vehicle().getOn();
    }
};

/**
 * Update getting off a vehicle
 */
Game_Player.prototype.updateVehicleGetOff = function() {
    if (!this.areFollowersGathering() && this.vehicle().isLowest()) {
        this._vehicleGettingOff = false;
        this._vehicleType = "walk";
        this.setTransparent(false);
    }
};

/**
 * Update when not moving
 *
 * @param {boolean} wasMoving - If the player just stopped moving
 * @param {boolean} sceneActive - If scene is active
 */
Game_Player.prototype.updateNonmoving = function(wasMoving, sceneActive) {
    if (!$gameMap.isEventRunning()) {
        if (wasMoving) {
            $gameParty.onPlayerWalk();
            this.checkEventTriggerHere([1, 2]);
            if ($gameMap.setupStartingEvent()) {
                return;
            }
        }
        if (sceneActive && this.triggerAction()) {
            return;
        }
        if (wasMoving) {
            this.updateEncounterCount();
        } else {
            $gameTemp.clearDestination();
        }
    }
};

/**
 * Check if action is triggered
 *
 * @return {boolean} True if action is triggered
 */
Game_Player.prototype.triggerAction = function() {
    if (this.canMove()) {
        if (this.triggerButtonAction()) {
            return true;
        }
        if (this.triggerTouchAction()) {
            return true;
        }
    }
    return false;
};

/**
 * Check if button input triggered action
 *
 * @return {boolean} True if action is triggered
 */
Game_Player.prototype.triggerButtonAction = function() {
    if (Input.isTriggered("ok")) {
        if (this.getOnOffVehicle()) {
            return true;
        }
        this.checkEventTriggerHere([0]);
        if ($gameMap.setupStartingEvent()) {
            return true;
        }
        this.checkEventTriggerThere([0, 1, 2]);
        if ($gameMap.setupStartingEvent()) {
            return true;
        }
    }
    return false;
};

/**
 * Check if touch triggered action
 *
 * @return {boolean} True if action is triggered
 */
Game_Player.prototype.triggerTouchAction = function() {
    if ($gameTemp.isDestinationValid()) {
        const direction = this.direction();
        const x1 = this.x;
        const y1 = this.y;
        const x2 = $gameMap.roundXWithDirection(x1, direction);
        const y2 = $gameMap.roundYWithDirection(y1, direction);
        const x3 = $gameMap.roundXWithDirection(x2, direction);
        const y3 = $gameMap.roundYWithDirection(y2, direction);
        const destX = $gameTemp.destinationX();
        const destY = $gameTemp.destinationY();
        if (destX === x1 && destY === y1) {
            return this.triggerTouchActionD1(x1, y1);
        } else if (destX === x2 && destY === y2) {
            return this.triggerTouchActionD2(x2, y2);
        } else if (destX === x3 && destY === y3) {
            return this.triggerTouchActionD3(x2, y2);
        }
    }
    return false;
};

/**
 * Check if touch action should trigger on the given coordinates
 *
 * @param {number} x1 - The x coordinate to check for trigger
 * @param {number} y1 - The y coordinate to check for trigger
 * @return {boolean} True if action is triggered
 */
Game_Player.prototype.triggerTouchActionD1 = function(x1, y1) {
    if ($gameMap.airship().pos(x1, y1)) {
        if (TouchInput.isTriggered() && this.getOnOffVehicle()) {
            return true;
        }
    }
    this.checkEventTriggerHere([0]);
    return $gameMap.setupStartingEvent();
};

/**
 * Check if touch action should trigger on the given coordinates
 *
 * @param {number} x2 - The x coordinate to check for trigger
 * @param {number} y2 - The y coordinate to check for trigger
 * @return {boolean} True if action is triggered
 */
Game_Player.prototype.triggerTouchActionD2 = function(x2, y2) {
    if ($gameMap.boat().pos(x2, y2) || $gameMap.ship().pos(x2, y2)) {
        if (TouchInput.isTriggered() && this.getOnVehicle()) {
            return true;
        }
    }
    if (this.isInBoat() || this.isInShip()) {
        if (TouchInput.isTriggered() && this.getOffVehicle()) {
            return true;
        }
    }
    this.checkEventTriggerThere([0, 1, 2]);
    return $gameMap.setupStartingEvent();
};

/**
 * Check if touch action should trigger on the given coordinates
 *
 * @param {number} x2 - The x coordinate to check for trigger
 * @param {number} y2 - The y coordinate to check for trigger
 * @return {boolean} True if action is triggered
 */
Game_Player.prototype.triggerTouchActionD3 = function(x2, y2) {
    if ($gameMap.isCounter(x2, y2)) {
        this.checkEventTriggerThere([0, 1, 2]);
    }
    return $gameMap.setupStartingEvent();
};

/**
 * Update the encounter count
 */
Game_Player.prototype.updateEncounterCount = function() {
    if (this.canEncounter()) {
        this._encounterCount -= this.encounterProgressValue();
    }
};

/**
 * Check if the player can encounter enemies
 *
 * @return {boolean} True if can encounter
 */
Game_Player.prototype.canEncounter = function() {
    return (
        !$gameParty.hasEncounterNone() &&
        $gameSystem.isEncounterEnabled() &&
        !this.isInAirship() &&
        !this.isMoveRouteForcing() &&
        !this.isDebugThrough()
    );
};

/**
 * Get the encounter progress value
 *
 * @return {number} The encounter progress amount
 */
Game_Player.prototype.encounterProgressValue = function() {
    let value = $gameMap.isBush(this.x, this.y) ? 2 : 1;
    if ($gameParty.hasEncounterHalf()) {
        value *= 0.5;
    }
    if (this.isInShip()) {
        value *= 0.5;
    }
    return value;
};

/**
 * Check event triggers on the player's location
 *
 * @param {number[]} triggers - The triggers to check for
 */
Game_Player.prototype.checkEventTriggerHere = function(triggers) {
    if (this.canStartLocalEvents()) {
        this.startMapEvent(this.x, this.y, triggers, false);
    }
};

/**
 * Check event triggers one tile in front of the player
 *
 * @param {number[]} triggers - The triggers to check for
 */
Game_Player.prototype.checkEventTriggerThere = function(triggers) {
    if (this.canStartLocalEvents()) {
        const direction = this.direction();
        const x1 = this.x;
        const y1 = this.y;
        const x2 = $gameMap.roundXWithDirection(x1, direction);
        const y2 = $gameMap.roundYWithDirection(y1, direction);
        this.startMapEvent(x2, y2, triggers, true);
        if (!$gameMap.isAnyEventStarting() && $gameMap.isCounter(x2, y2)) {
            const x3 = $gameMap.roundXWithDirection(x2, direction);
            const y3 = $gameMap.roundYWithDirection(y2, direction);
            this.startMapEvent(x3, y3, triggers, true);
        }
    }
};

/**
 * Check event triggers for touch
 *
 * @param {number} x - The x coordinate to check
 * @param {number} y - The y coordinate to check
 */
Game_Player.prototype.checkEventTriggerTouch = function(x, y) {
    if (this.canStartLocalEvents()) {
        this.startMapEvent(x, y, [1, 2], true);
    }
};

/**
 * Check if local events can start
 *
 * @return {boolean} True if local events can start
 */
Game_Player.prototype.canStartLocalEvents = function() {
    return !this.isInAirship();
};

/**
 * Processing for getting on or off a vehicle
 *
 * @param {boolean} True if get on/off started
 */
Game_Player.prototype.getOnOffVehicle = function() {
    if (this.isInVehicle()) {
        return this.getOffVehicle();
    } else {
        return this.getOnVehicle();
    }
};

/**
 * Processing for getting on a vehicle
 *
 * @param {boolean} True if get on started
 */
Game_Player.prototype.getOnVehicle = function() {
    const direction = this.direction();
    const x1 = this.x;
    const y1 = this.y;
    const x2 = $gameMap.roundXWithDirection(x1, direction);
    const y2 = $gameMap.roundYWithDirection(y1, direction);
    if ($gameMap.airship().pos(x1, y1)) {
        this._vehicleType = "airship";
    } else if ($gameMap.ship().pos(x2, y2)) {
        this._vehicleType = "ship";
    } else if ($gameMap.boat().pos(x2, y2)) {
        this._vehicleType = "boat";
    }
    if (this.isInVehicle()) {
        this._vehicleGettingOn = true;
        if (!this.isInAirship()) {
            this.forceMoveForward();
        }
        this.gatherFollowers();
    }
    return this._vehicleGettingOn;
};

/**
 * Processing for getting off a vehicle
 *
 * @param {boolean} True if get off started
 */
Game_Player.prototype.getOffVehicle = function() {
    if (this.vehicle().isLandOk(this.x, this.y, this.direction())) {
        if (this.isInAirship()) {
            this.setDirection(2);
        }
        this._followers.synchronize(this.x, this.y, this.direction());
        this.vehicle().getOff();
        if (!this.isInAirship()) {
            this.forceMoveForward();
            this.setTransparent(false);
        }
        this._vehicleGettingOff = true;
        this.setMoveSpeed(4);
        this.setThrough(false);
        this.makeEncounterCount();
        this.gatherFollowers();
    }
    return this._vehicleGettingOff;
};

/**
 * Force the player to move forward
 */
Game_Player.prototype.forceMoveForward = function() {
    this.setThrough(true);
    this.moveForward();
    this.setThrough(false);
};

/**
 * Check if the player is on a damage floor
 *
 * @param {boolean} True if on damage floor
 */
Game_Player.prototype.isOnDamageFloor = function() {
    return $gameMap.isDamageFloor(this.x, this.y) && !this.isInAirship();
};

Game_Player.prototype.moveStraight = function(d) {
    if (this.canPass(this.x, this.y, d)) {
        this._followers.updateMove();
    }
    Game_Character.prototype.moveStraight.call(this, d);
};

Game_Player.prototype.moveDiagonally = function(horz, vert) {
    if (this.canPassDiagonally(this.x, this.y, horz, vert)) {
        this._followers.updateMove();
    }
    Game_Character.prototype.moveDiagonally.call(this, horz, vert);
};

Game_Player.prototype.jump = function(xPlus, yPlus) {
    Game_Character.prototype.jump.call(this, xPlus, yPlus);
    this._followers.jumpAll();
};

/**
 * Show player followers
 */
Game_Player.prototype.showFollowers = function() {
    this._followers.show();
};

/**
 * Hide player followers
 */
Game_Player.prototype.hideFollowers = function() {
    this._followers.hide();
};

/**
 * Gather player followers
 */
Game_Player.prototype.gatherFollowers = function() {
    this._followers.gather();
};

/**
 * Check if player followers are gathering
 *
 * @param {boolean} True if gathering
 */
Game_Player.prototype.areFollowersGathering = function() {
    return this._followers.areGathering();
};

/**
 * Check if followers are gathered
 *
 * @param {boolean} True if gathered
 */
Game_Player.prototype.areFollowersGathered = function() {
    return this._followers.areGathered();
};