//-----------------------------------------------------------------------------
// Game_Character
//
// The superclass of Game_Player, Game_Follower, GameVehicle, and Game_Event.
/**
* The superclass of Game_Player, Game_Follower, GameVehicle, and Game_Event.
*
* @class
* @extends Game_CharacterBase
*/
function Game_Character() {
this.initialize(...arguments);
}
Game_Character.prototype = Object.create(Game_CharacterBase.prototype);
Game_Character.prototype.constructor = Game_Character;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_END = 0;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_MOVE_DOWN = 1;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_MOVE_LEFT = 2;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_MOVE_RIGHT = 3;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_MOVE_UP = 4;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_MOVE_LOWER_L = 5;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_MOVE_LOWER_R = 6;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_MOVE_UPPER_L = 7;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_MOVE_UPPER_R = 8;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_MOVE_RANDOM = 9;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_MOVE_TOWARD = 10;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_MOVE_AWAY = 11;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_MOVE_FORWARD = 12;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_MOVE_BACKWARD = 13;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_JUMP = 14;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_WAIT = 15;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_TURN_DOWN = 16;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_TURN_LEFT = 17;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_TURN_RIGHT = 18;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_TURN_UP = 19;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_TURN_90D_R = 20;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_TURN_90D_L = 21;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_TURN_180D = 22;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_TURN_90D_R_L = 23;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_TURN_RANDOM = 24;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_TURN_TOWARD = 25;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_TURN_AWAY = 26;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_SWITCH_ON = 27;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_SWITCH_OFF = 28;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_CHANGE_SPEED = 29;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_CHANGE_FREQ = 30;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_WALK_ANIME_ON = 31;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_WALK_ANIME_OFF = 32;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_STEP_ANIME_ON = 33;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_STEP_ANIME_OFF = 34;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_DIR_FIX_ON = 35;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_DIR_FIX_OFF = 36;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_THROUGH_ON = 37;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_THROUGH_OFF = 38;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_TRANSPARENT_ON = 39;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_TRANSPARENT_OFF = 40;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_CHANGE_IMAGE = 41;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_CHANGE_OPACITY = 42;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_CHANGE_BLEND_MODE = 43;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_PLAY_SE = 44;
/** @constant
@type {number}
@default
*/
Game_Character.ROUTE_SCRIPT = 45;
Game_Character.prototype.initialize = function() {
Game_CharacterBase.prototype.initialize.call(this);
};
Game_Character.prototype.initMembers = function() {
Game_CharacterBase.prototype.initMembers.call(this);
this._moveRouteForcing = false;
this._moveRoute = null;
this._moveRouteIndex = 0;
this._originalMoveRoute = null;
this._originalMoveRouteIndex = 0;
this._waitCount = 0;
};
/**
* Memorizes the character move route
*/
Game_Character.prototype.memorizeMoveRoute = function() {
this._originalMoveRoute = this._moveRoute;
this._originalMoveRouteIndex = this._moveRouteIndex;
};
/**
* Restores a memorized move route
*/
Game_Character.prototype.restoreMoveRoute = function() {
this._moveRoute = this._originalMoveRoute;
this._moveRouteIndex = this._originalMoveRouteIndex;
this._originalMoveRoute = null;
};
/**
* Check if move route is forcing
*
* @return {boolean} True if forcing
*/
Game_Character.prototype.isMoveRouteForcing = function() {
return this._moveRouteForcing;
};
/**
* Sets a move route
*
* @param {Object} moveRoute - The move route to set
*/
Game_Character.prototype.setMoveRoute = function(moveRoute) {
if (this._moveRouteForcing) {
this._originalMoveRoute = moveRoute;
this._originalMoveRouteIndex = 0;
} else {
this._moveRoute = moveRoute;
this._moveRouteIndex = 0;
}
};
/**
* Forces a move route
*
* @param {Object} moveRoute - The move route to force
*/
Game_Character.prototype.forceMoveRoute = function(moveRoute) {
if (!this._originalMoveRoute) {
this.memorizeMoveRoute();
}
this._moveRoute = moveRoute;
this._moveRouteIndex = 0;
this._moveRouteForcing = true;
this._waitCount = 0;
};
Game_Character.prototype.updateStop = function() {
Game_CharacterBase.prototype.updateStop.call(this);
if (this._moveRouteForcing) {
this.updateRoutineMove();
}
};
/**
* Updates move route
*/
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();
}
}
};
/**
* Processes a given move command
*
* @param {Object} command - The move command
*/
Game_Character.prototype.processMoveCommand = function(command) {
const gc = Game_Character;
const params = command.parameters;
switch (command.code) {
case gc.ROUTE_END:
this.processRouteEnd();
break;
case gc.ROUTE_MOVE_DOWN:
this.moveStraight(2);
break;
case gc.ROUTE_MOVE_LEFT:
this.moveStraight(4);
break;
case gc.ROUTE_MOVE_RIGHT:
this.moveStraight(6);
break;
case gc.ROUTE_MOVE_UP:
this.moveStraight(8);
break;
case gc.ROUTE_MOVE_LOWER_L:
this.moveDiagonally(4, 2);
break;
case gc.ROUTE_MOVE_LOWER_R:
this.moveDiagonally(6, 2);
break;
case gc.ROUTE_MOVE_UPPER_L:
this.moveDiagonally(4, 8);
break;
case gc.ROUTE_MOVE_UPPER_R:
this.moveDiagonally(6, 8);
break;
case gc.ROUTE_MOVE_RANDOM:
this.moveRandom();
break;
case gc.ROUTE_MOVE_TOWARD:
this.moveTowardPlayer();
break;
case gc.ROUTE_MOVE_AWAY:
this.moveAwayFromPlayer();
break;
case gc.ROUTE_MOVE_FORWARD:
this.moveForward();
break;
case gc.ROUTE_MOVE_BACKWARD:
this.moveBackward();
break;
case gc.ROUTE_JUMP:
this.jump(params[0], params[1]);
break;
case gc.ROUTE_WAIT:
this._waitCount = params[0] - 1;
break;
case gc.ROUTE_TURN_DOWN:
this.setDirection(2);
break;
case gc.ROUTE_TURN_LEFT:
this.setDirection(4);
break;
case gc.ROUTE_TURN_RIGHT:
this.setDirection(6);
break;
case gc.ROUTE_TURN_UP:
this.setDirection(8);
break;
case gc.ROUTE_TURN_90D_R:
this.turnRight90();
break;
case gc.ROUTE_TURN_90D_L:
this.turnLeft90();
break;
case gc.ROUTE_TURN_180D:
this.turn180();
break;
case gc.ROUTE_TURN_90D_R_L:
this.turnRightOrLeft90();
break;
case gc.ROUTE_TURN_RANDOM:
this.turnRandom();
break;
case gc.ROUTE_TURN_TOWARD:
this.turnTowardPlayer();
break;
case gc.ROUTE_TURN_AWAY:
this.turnAwayFromPlayer();
break;
case gc.ROUTE_SWITCH_ON:
$gameSwitches.setValue(params[0], true);
break;
case gc.ROUTE_SWITCH_OFF:
$gameSwitches.setValue(params[0], false);
break;
case gc.ROUTE_CHANGE_SPEED:
this.setMoveSpeed(params[0]);
break;
case gc.ROUTE_CHANGE_FREQ:
this.setMoveFrequency(params[0]);
break;
case gc.ROUTE_WALK_ANIME_ON:
this.setWalkAnime(true);
break;
case gc.ROUTE_WALK_ANIME_OFF:
this.setWalkAnime(false);
break;
case gc.ROUTE_STEP_ANIME_ON:
this.setStepAnime(true);
break;
case gc.ROUTE_STEP_ANIME_OFF:
this.setStepAnime(false);
break;
case gc.ROUTE_DIR_FIX_ON:
this.setDirectionFix(true);
break;
case gc.ROUTE_DIR_FIX_OFF:
this.setDirectionFix(false);
break;
case gc.ROUTE_THROUGH_ON:
this.setThrough(true);
break;
case gc.ROUTE_THROUGH_OFF:
this.setThrough(false);
break;
case gc.ROUTE_TRANSPARENT_ON:
this.setTransparent(true);
break;
case gc.ROUTE_TRANSPARENT_OFF:
this.setTransparent(false);
break;
case gc.ROUTE_CHANGE_IMAGE:
this.setImage(params[0], params[1]);
break;
case gc.ROUTE_CHANGE_OPACITY:
this.setOpacity(params[0]);
break;
case gc.ROUTE_CHANGE_BLEND_MODE:
this.setBlendMode(params[0]);
break;
case gc.ROUTE_PLAY_SE:
AudioManager.playSe(params[0]);
break;
case gc.ROUTE_SCRIPT:
eval(params[0]);
break;
}
};
/**
* Get the delta x from the given x and the character x
*
* @param {number} x - The given x
* @return {number} The delta x
*/
Game_Character.prototype.deltaXFrom = function(x) {
return $gameMap.deltaX(this.x, x);
};
/**
* Get the delta y from the given y and the character y
*
* @param {number} y - The given y
* @return {number} The delta y
*/
Game_Character.prototype.deltaYFrom = function(y) {
return $gameMap.deltaY(this.y, y);
};
/**
* Random move handling
*/
Game_Character.prototype.moveRandom = function() {
const d = 2 + Math.randomInt(4) * 2;
if (this.canPass(this.x, this.y, d)) {
this.moveStraight(d);
}
};
/**
* Moves toward the given character
*
* @param {Game_Character} character - The character to move toward
*/
Game_Character.prototype.moveTowardCharacter = function(character) {
const sx = this.deltaXFrom(character.x);
const sy = this.deltaYFrom(character.y);
if (Math.abs(sx) > Math.abs(sy)) {
this.moveStraight(sx > 0 ? 4 : 6);
if (!this.isMovementSucceeded() && sy !== 0) {
this.moveStraight(sy > 0 ? 8 : 2);
}
} else if (sy !== 0) {
this.moveStraight(sy > 0 ? 8 : 2);
if (!this.isMovementSucceeded() && sx !== 0) {
this.moveStraight(sx > 0 ? 4 : 6);
}
}
};
/**
* Moves away from the given character
*
* @param {Game_Character} character - The character to move away from
*/
Game_Character.prototype.moveAwayFromCharacter = function(character) {
const sx = this.deltaXFrom(character.x);
const sy = this.deltaYFrom(character.y);
if (Math.abs(sx) > Math.abs(sy)) {
this.moveStraight(sx > 0 ? 6 : 4);
if (!this.isMovementSucceeded() && sy !== 0) {
this.moveStraight(sy > 0 ? 2 : 8);
}
} else if (sy !== 0) {
this.moveStraight(sy > 0 ? 2 : 8);
if (!this.isMovementSucceeded() && sx !== 0) {
this.moveStraight(sx > 0 ? 6 : 4);
}
}
};
/**
* Turns toward the given character
*
* @param {Game_Character} character - The character to turn toward
*/
Game_Character.prototype.turnTowardCharacter = function(character) {
const sx = this.deltaXFrom(character.x);
const sy = this.deltaYFrom(character.y);
if (Math.abs(sx) > Math.abs(sy)) {
this.setDirection(sx > 0 ? 4 : 6);
} else if (sy !== 0) {
this.setDirection(sy > 0 ? 8 : 2);
}
};
/**
* Turns away from the given character
*
* @param {Game_Character} character - The character to turn away from
*/
Game_Character.prototype.turnAwayFromCharacter = function(character) {
const sx = this.deltaXFrom(character.x);
const sy = this.deltaYFrom(character.y);
if (Math.abs(sx) > Math.abs(sy)) {
this.setDirection(sx > 0 ? 6 : 4);
} else if (sy !== 0) {
this.setDirection(sy > 0 ? 2 : 8);
}
};
/**
* Turns toward the player
*/
Game_Character.prototype.turnTowardPlayer = function() {
this.turnTowardCharacter($gamePlayer);
};
/**
* Turns away from the player
*/
Game_Character.prototype.turnAwayFromPlayer = function() {
this.turnAwayFromCharacter($gamePlayer);
};
/**
* Moves toward the player
*/
Game_Character.prototype.moveTowardPlayer = function() {
this.moveTowardCharacter($gamePlayer);
};
/**
* Moves away from the player
*/
Game_Character.prototype.moveAwayFromPlayer = function() {
this.moveAwayFromCharacter($gamePlayer);
};
/**
* Moves forward
*/
Game_Character.prototype.moveForward = function() {
this.moveStraight(this.direction());
};
/**
* Moves backward
*/
Game_Character.prototype.moveBackward = function() {
const lastDirectionFix = this.isDirectionFixed();
this.setDirectionFix(true);
this.moveStraight(this.reverseDir(this.direction()));
this.setDirectionFix(lastDirectionFix);
};
/**
* Processing when move route ends
*/
Game_Character.prototype.processRouteEnd = function() {
if (this._moveRoute.repeat) {
this._moveRouteIndex = -1;
} else if (this._moveRouteForcing) {
this._moveRouteForcing = false;
this.restoreMoveRoute();
this.setMovementSuccess(false);
}
};
/**
* Advances the move route index
*/
Game_Character.prototype.advanceMoveRouteIndex = function() {
const moveRoute = this._moveRoute;
if (moveRoute && (this.isMovementSucceeded() || moveRoute.skippable)) {
let numCommands = moveRoute.list.length - 1;
this._moveRouteIndex++;
if (moveRoute.repeat && this._moveRouteIndex >= numCommands) {
this._moveRouteIndex = 0;
}
}
};
/**
* Turn right 90 degrees
*/
Game_Character.prototype.turnRight90 = function() {
switch (this.direction()) {
case 2:
this.setDirection(4);
break;
case 4:
this.setDirection(8);
break;
case 6:
this.setDirection(2);
break;
case 8:
this.setDirection(6);
break;
}
};
/**
* Turn left 90 degrees
*/
Game_Character.prototype.turnLeft90 = function() {
switch (this.direction()) {
case 2:
this.setDirection(6);
break;
case 4:
this.setDirection(2);
break;
case 6:
this.setDirection(8);
break;
case 8:
this.setDirection(4);
break;
}
};
/**
* Turn 180 degrees (turn around)
*/
Game_Character.prototype.turn180 = function() {
this.setDirection(this.reverseDir(this.direction()));
};
/**
* Randomly turn right or left 90 degrees
*/
Game_Character.prototype.turnRightOrLeft90 = function() {
switch (Math.randomInt(2)) {
case 0:
this.turnRight90();
break;
case 1:
this.turnLeft90();
break;
}
};
/**
* Turn in a random direction
*/
Game_Character.prototype.turnRandom = function() {
this.setDirection(2 + Math.randomInt(4) * 2);
};
/**
* Swap location with the given character
*
* @param {Game_Character} character - The character to swap with
*/
Game_Character.prototype.swap = function(character) {
const newX = character.x;
const newY = character.y;
character.locate(this.x, this.y);
this.locate(newX, newY);
};
/**
* Find the direction to a given x/y coordinate
*
* @param {number} goalX - The goal x coordinate
* @param {number} goalY - The goal y coordinate
* @return {number} The direction to the goal coordinates
*/
Game_Character.prototype.findDirectionTo = function(goalX, goalY) {
const searchLimit = this.searchLimit();
const mapWidth = $gameMap.width();
const nodeList = [];
const openList = [];
const closedList = [];
const start = {};
let best = start;
if (this.x === goalX && this.y === goalY) {
return 0;
}
start.parent = null;
start.x = this.x;
start.y = this.y;
start.g = 0;
start.f = $gameMap.distance(start.x, start.y, goalX, goalY);
nodeList.push(start);
openList.push(start.y * mapWidth + start.x);
while (nodeList.length > 0) {
let bestIndex = 0;
for (let i = 0; i < nodeList.length; i++) {
if (nodeList[i].f < nodeList[bestIndex].f) {
bestIndex = i;
}
}
const current = nodeList[bestIndex];
const x1 = current.x;
const y1 = current.y;
const pos1 = y1 * mapWidth + x1;
const g1 = current.g;
nodeList.splice(bestIndex, 1);
openList.splice(openList.indexOf(pos1), 1);
closedList.push(pos1);
if (current.x === goalX && current.y === goalY) {
best = current;
break;
}
if (g1 >= searchLimit) {
continue;
}
for (let j = 0; j < 4; j++) {
const direction = 2 + j * 2;
const x2 = $gameMap.roundXWithDirection(x1, direction);
const y2 = $gameMap.roundYWithDirection(y1, direction);
const pos2 = y2 * mapWidth + x2;
if (closedList.includes(pos2)) {
continue;
}
if (!this.canPass(x1, y1, direction)) {
continue;
}
const g2 = g1 + 1;
const index2 = openList.indexOf(pos2);
if (index2 < 0 || g2 < nodeList[index2].g) {
let neighbor = {};
if (index2 >= 0) {
neighbor = nodeList[index2];
} else {
nodeList.push(neighbor);
openList.push(pos2);
}
neighbor.parent = current;
neighbor.x = x2;
neighbor.y = y2;
neighbor.g = g2;
neighbor.f = g2 + $gameMap.distance(x2, y2, goalX, goalY);
if (!best || neighbor.f - neighbor.g < best.f - best.g) {
best = neighbor;
}
}
}
}
let node = best;
while (node.parent && node.parent !== start) {
node = node.parent;
}
const deltaX1 = $gameMap.deltaX(node.x, start.x);
const deltaY1 = $gameMap.deltaY(node.y, start.y);
if (deltaY1 > 0) {
return 2;
} else if (deltaX1 < 0) {
return 4;
} else if (deltaX1 > 0) {
return 6;
} else if (deltaY1 < 0) {
return 8;
}
const deltaX2 = this.deltaXFrom(goalX);
const deltaY2 = this.deltaYFrom(goalY);
if (Math.abs(deltaX2) > Math.abs(deltaY2)) {
return deltaX2 > 0 ? 4 : 6;
} else if (deltaY2 !== 0) {
return deltaY2 > 0 ? 8 : 2;
}
return 0;
};
/**
* The maximum amount of tiles to search for finding direction
*
* @return {number} The search limit
*/
Game_Character.prototype.searchLimit = function() {
return 12;
};