//-----------------------------------------------------------------------------
// Game_Map
//
// The game object class for a map. It contains scrolling and passage
// determination functions.
/**
* The game object class for a map. It contains scrolling and passage determination functions.
*
* @class
*/
function Game_Map() {
this.initialize(...arguments);
}
/**
* Initialize the map class
*/
Game_Map.prototype.initialize = function() {
this._interpreter = new Game_Interpreter();
this._mapId = 0;
this._tilesetId = 0;
this._events = [];
this._commonEvents = [];
this._vehicles = [];
this._displayX = 0;
this._displayY = 0;
this._nameDisplay = true;
this._scrollDirection = 2;
this._scrollRest = 0;
this._scrollSpeed = 4;
this._parallaxName = "";
this._parallaxZero = false;
this._parallaxLoopX = false;
this._parallaxLoopY = false;
this._parallaxSx = 0;
this._parallaxSy = 0;
this._parallaxX = 0;
this._parallaxY = 0;
this._battleback1Name = null;
this._battleback2Name = null;
this.createVehicles();
};
/**
* Sets up the map for the given map id
*
* @param {number} mapId - The map id to setup
* @throws Error if map data object is not available
*/
Game_Map.prototype.setup = function(mapId) {
if (!$dataMap) {
throw new Error("The map data is not available");
}
this._mapId = mapId;
this._tilesetId = $dataMap.tilesetId;
this._displayX = 0;
this._displayY = 0;
this.refereshVehicles();
this.setupEvents();
this.setupScroll();
this.setupParallax();
this.setupBattleback();
this._needsRefresh = false;
};
/**
* Check if events are running
*
* @return {boolean} True if event is running
*/
Game_Map.prototype.isEventRunning = function() {
return this._interpreter.isRunning() || this.isAnyEventStarting();
};
/**
* Get the width of a map tile in pixels
*
* @return {number} The width of one tile
*/
Game_Map.prototype.tileWidth = function() {
if ("tileSize" in $dataSystem) {
return $dataSystem.tileSize;
} else {
return 48;
}
};
/**
* Get the height of a map tile in pixels
*
* @return {number} The height of one tile
*/
Game_Map.prototype.tileHeight = function() {
return this.tileWidth();
};
/**
* Get the bush depth
*
* @return {number} The bush depth
* @since Version 1.5.0
*/
Game_Map.prototype.bushDepth = function() {
return this.tileHeight() / 4;
};
/**
* Get the map id
*
* @return {number} The map id
*/
Game_Map.prototype.mapId = function() {
return this._mapId;
};
/**
* Get the tileset id
*
* @return {number} The tileset id
*/
Game_Map.prototype.tilesetId = function() {
return this._tilesetId;
};
/**
* Get the display x
*
* @return {number} The display x
*/
Game_Map.prototype.displayX = function() {
return this._displayX;
};
/**
* Get the display y
*
* @return {number} The display y
*/
Game_Map.prototype.displayY = function() {
return this._displayY;
};
/**
* Get the parallax image file name
*
* @return {string} The parallax name
*/
Game_Map.prototype.parallaxName = function() {
return this._parallaxName;
};
/**
* Get the battleback 1 image file name
*
* @return {string} The battleback 1 name
*/
Game_Map.prototype.battleback1Name = function() {
return this._battleback1Name;
};
/**
* Get the battleback 2 image file name
*
* @return {string} The battleback 2 name
*/
Game_Map.prototype.battleback2Name = function() {
return this._battleback2Name;
};
/**
* Request a map refresh
*/
Game_Map.prototype.requestRefresh = function() {
this._needsRefresh = true;
};
/**
* Check if the map has an enabled display name
*
* @return {boolean} True if name display is enabled
*/
Game_Map.prototype.isNameDisplayEnabled = function() {
return this._nameDisplay;
};
/**
* Disables name display
*/
Game_Map.prototype.disableNameDisplay = function() {
this._nameDisplay = false;
};
/**
* Enables name display
*/
Game_Map.prototype.enableNameDisplay = function() {
this._nameDisplay = true;
};
/**
* Creates the vehicles
*/
Game_Map.prototype.createVehicles = function() {
this._vehicles = [];
this._vehicles[0] = new Game_Vehicle("boat");
this._vehicles[1] = new Game_Vehicle("ship");
this._vehicles[2] = new Game_Vehicle("airship");
};
/**
* Refreshes the vehicles
*/
Game_Map.prototype.refereshVehicles = function() {
for (const vehicle of this._vehicles) {
vehicle.refresh();
}
};
/**
* Get the vehicle array
*
* @return {Game_Vehicle[]} Array of game vehicles
*/
Game_Map.prototype.vehicles = function() {
return this._vehicles;
};
/**
* Get a vehicle by type
*
* @param {string|number} type - Either string or number type of the vehicle (0/1/2 or boat/ship/airship)
* @return {Game_Vehicle|null} The game vehicle object, or null if invalid type
*/
Game_Map.prototype.vehicle = function(type) {
if (type === 0 || type === "boat") {
return this.boat();
} else if (type === 1 || type === "ship") {
return this.ship();
} else if (type === 2 || type === "airship") {
return this.airship();
} else {
return null;
}
};
/**
* Get the boat vehicle
*
* @return {Game_Vehicle} The boat object
*/
Game_Map.prototype.boat = function() {
return this._vehicles[0];
};
/**
* Get the ship vehicle
*
* @return {Game_Vehicle} The ship object
*/
Game_Map.prototype.ship = function() {
return this._vehicles[1];
};
/**
* Get the airship vehicle
*
* @return {Game_Vehicle} The airship object
*/
Game_Map.prototype.airship = function() {
return this._vehicles[2];
};
/**
* Set up events on the map
*/
Game_Map.prototype.setupEvents = function() {
this._events = [];
this._commonEvents = [];
for (const event of $dataMap.events.filter(event => !!event)) {
this._events[event.id] = new Game_Event(this._mapId, event.id);
}
for (const commonEvent of this.parallelCommonEvents()) {
this._commonEvents.push(new Game_CommonEvent(commonEvent.id));
}
this.refreshTileEvents();
};
/**
* Get the events
*
* @return {Game_Event[]} The array of map events
*/
Game_Map.prototype.events = function() {
return this._events.filter(event => !!event);
};
/**
* Get an event by id
*
* @param {number} eventId - The id of the event to get
* @return {Game_Event} The event object
*/
Game_Map.prototype.event = function(eventId) {
return this._events[eventId];
};
/**
* Erase an event by id
*
* @param {number} eventId - The id of the event to erase
*/
Game_Map.prototype.eraseEvent = function(eventId) {
this._events[eventId].erase();
};
/**
* Get autorun common events
*
* @return {Array} Array of autorunning common events
*/
Game_Map.prototype.autorunCommonEvents = function() {
return $dataCommonEvents.filter(
commonEvent => commonEvent && commonEvent.trigger === 1
);
};
/**
* Get parallel common events
*
* @return {Array} Array of parallel common events
*/
Game_Map.prototype.parallelCommonEvents = function() {
return $dataCommonEvents.filter(
commonEvent => commonEvent && commonEvent.trigger === 2
);
};
/**
* Set up the map scroll
*/
Game_Map.prototype.setupScroll = function() {
this._scrollDirection = 2;
this._scrollRest = 0;
this._scrollSpeed = 4;
};
/**
* Set up the map parallax
*/
Game_Map.prototype.setupParallax = function() {
this._parallaxName = $dataMap.parallaxName || "";
this._parallaxZero = ImageManager.isZeroParallax(this._parallaxName);
this._parallaxLoopX = $dataMap.parallaxLoopX;
this._parallaxLoopY = $dataMap.parallaxLoopY;
this._parallaxSx = $dataMap.parallaxSx;
this._parallaxSy = $dataMap.parallaxSy;
this._parallaxX = 0;
this._parallaxY = 0;
};
/**
* Set up the map battlebacks
*/
Game_Map.prototype.setupBattleback = function() {
if ($dataMap.specifyBattleback) {
this._battleback1Name = $dataMap.battleback1Name;
this._battleback2Name = $dataMap.battleback2Name;
} else {
this._battleback1Name = null;
this._battleback2Name = null;
}
};
/**
* Set up the display position
*
* @param {number} x - The x coordinate
* @param {number} y - The y coordinate
*/
Game_Map.prototype.setDisplayPos = function(x, y) {
if (this.isLoopHorizontal()) {
this._displayX = x.mod(this.width());
this._parallaxX = x;
} else {
const endX = this.width() - this.screenTileX();
this._displayX = endX < 0 ? endX / 2 : x.clamp(0, endX);
this._parallaxX = this._displayX;
}
if (this.isLoopVertical()) {
this._displayY = y.mod(this.height());
this._parallaxY = y;
} else {
const endY = this.height() - this.screenTileY();
this._displayY = endY < 0 ? endY / 2 : y.clamp(0, endY);
this._parallaxY = this._displayY;
}
};
/**
* Get the parallax origin x
*
* @return {number} The parallax origin x
*/
Game_Map.prototype.parallaxOx = function() {
if (this._parallaxZero) {
return this._parallaxX * this.tileWidth();
} else if (this._parallaxLoopX) {
return (this._parallaxX * this.tileWidth()) / 2;
} else {
return 0;
}
};
/**
* Get the parallax origin y
*
* @return {number} The parallax origin y
*/
Game_Map.prototype.parallaxOy = function() {
if (this._parallaxZero) {
return this._parallaxY * this.tileHeight();
} else if (this._parallaxLoopY) {
return (this._parallaxY * this.tileHeight()) / 2;
} else {
return 0;
}
};
/**
* Get the tileset object
*
* @return {Object} The tileset object
*/
Game_Map.prototype.tileset = function() {
return $dataTilesets[this._tilesetId];
};
/**
* Get the tileset flags
*
* @return {Array} The tileset's flags
*/
Game_Map.prototype.tilesetFlags = function() {
const tileset = this.tileset();
if (tileset) {
return tileset.flags;
} else {
return [];
}
};
/**
* Get the map display name
*
* @return {string} The display name
*/
Game_Map.prototype.displayName = function() {
return $dataMap.displayName;
};
/**
* Get the map width
*
* @return {number} The width
*/
Game_Map.prototype.width = function() {
return $dataMap.width;
};
/**
* Get the map height
*
* @return {number} The height
*/
Game_Map.prototype.height = function() {
return $dataMap.height;
};
/**
* Get the map data
*
* @return {Array} The map data
*/
Game_Map.prototype.data = function() {
return $dataMap.data;
};
/**
* Check if the map loops horizontally
*
* @return {boolean} True if the map loops horizontally
*/
Game_Map.prototype.isLoopHorizontal = function() {
return $dataMap.scrollType === 2 || $dataMap.scrollType === 3;
};
/**
* Check if the map loops vertically
*
* @return {boolean} True if the map loops vertically
*/
Game_Map.prototype.isLoopVertical = function() {
return $dataMap.scrollType === 1 || $dataMap.scrollType === 3;
};
/**
* Check if dashing is disabled
*
* @return {boolean} True if dashing disabled
*/
Game_Map.prototype.isDashDisabled = function() {
return $dataMap.disableDashing;
};
/**
* Get the map encounter list
*
* @return {Array} The encounter list
*/
Game_Map.prototype.encounterList = function() {
return $dataMap.encounterList;
};
/**
* Get the map encounter step
*
* @return {number} The encounter step
*/
Game_Map.prototype.encounterStep = function() {
return $dataMap.encounterStep;
};
/**
* Check if the map is an overworld type
*
* @return {boolean} True if overworld type
*/
Game_Map.prototype.isOverworld = function() {
return this.tileset() && this.tileset().mode === 0;
};
/**
* Get the screen tile x
*
* @return {number} The screen tile x
*/
Game_Map.prototype.screenTileX = function() {
return Math.round((Graphics.width / this.tileWidth()) * 16) / 16;
};
/**
* Get the screen tile y
*
* @return {number} The screen tile y
*/
Game_Map.prototype.screenTileY = function() {
return Math.round((Graphics.height / this.tileHeight()) * 16) / 16;
};
/**
* Get the adjusted x value
*
* @param {number} x - The x to adjust
* @return {number} The adjusted x value
*/
Game_Map.prototype.adjustX = function(x) {
if (
this.isLoopHorizontal() &&
x < this._displayX - (this.width() - this.screenTileX()) / 2
) {
return x - this._displayX + $dataMap.width;
} else {
return x - this._displayX;
}
};
/**
* Get the adjusted y value
*
* @param {number} y - The y to adjust
* @return {number} The adjusted y value
*/
Game_Map.prototype.adjustY = function(y) {
if (
this.isLoopVertical() &&
y < this._displayY - (this.height() - this.screenTileY()) / 2
) {
return y - this._displayY + $dataMap.height;
} else {
return y - this._displayY;
}
};
/**
* Get the rounded x value
*
* @param {number} x - The x to round
* @return {number} The rounded x value
*/
Game_Map.prototype.roundX = function(x) {
return this.isLoopHorizontal() ? x.mod(this.width()) : x;
};
/**
* Get the rounded y value
*
* @param {number} y - The y to round
* @return {number} The rounded y value
*/
Game_Map.prototype.roundY = function(y) {
return this.isLoopVertical() ? y.mod(this.height()) : y;
};
/**
* Get the x value with direction
*
* @param {number} x - The original x value
* @param {number} d - The direction
* @return {number} The x value after direction accounted for
*/
Game_Map.prototype.xWithDirection = function(x, d) {
return x + (d === 6 ? 1 : d === 4 ? -1 : 0);
};
/**
* Get the y value with direction
*
* @param {number} y - The original y value
* @param {number} d - The direction
* @return {number} The y value after direction accounted for
*/
Game_Map.prototype.yWithDirection = function(y, d) {
return y + (d === 2 ? 1 : d === 8 ? -1 : 0);
};
/**
* Get the rounded x value with direction
*
* @param {number} x - The original x value
* @param {number} d - The direction
* @return {number} The x value after direction accounted for
*/
Game_Map.prototype.roundXWithDirection = function(x, d) {
return this.roundX(x + (d === 6 ? 1 : d === 4 ? -1 : 0));
};
/**
* Get the rounded y value with direction
*
* @param {number} y - The original y value
* @param {number} d - The direction
* @return {number} The y value after direction accounted for
*/
Game_Map.prototype.roundYWithDirection = function(y, d) {
return this.roundY(y + (d === 2 ? 1 : d === 8 ? -1 : 0));
};
/**
* Get the delta between two x values
*
* @param {number} x1 - The first x value
* @param {number} x2 - The second x value
* @return {number} The delta between the x values
*/
Game_Map.prototype.deltaX = function(x1, x2) {
let result = x1 - x2;
if (this.isLoopHorizontal() && Math.abs(result) > this.width() / 2) {
if (result < 0) {
result += this.width();
} else {
result -= this.width();
}
}
return result;
};
/**
* Get the delta between two y values
*
* @param {number} y1 - The first y value
* @param {number} y2 - The second y value
* @return {number} The delta between the y values
*/
Game_Map.prototype.deltaY = function(y1, y2) {
let result = y1 - y2;
if (this.isLoopVertical() && Math.abs(result) > this.height() / 2) {
if (result < 0) {
result += this.height();
} else {
result -= this.height();
}
}
return result;
};
/**
* Get the distance between two sets of x/y coordinates
*
* @param {number} x1 - The first x value
* @param {number} y1 - The first y value
* @param {number} x2 - The second x value
* @param {number} y2 - The second y value
* @return {number} The distance
*/
Game_Map.prototype.distance = function(x1, y1, x2, y2) {
return Math.abs(this.deltaX(x1, x2)) + Math.abs(this.deltaY(y1, y2));
};
/**
* Get map x from canvas x
*
* @param {number} x - The x value to convert
* @return {number} The map x
*/
Game_Map.prototype.canvasToMapX = function(x) {
const tileWidth = this.tileWidth();
const originX = this._displayX * tileWidth;
const mapX = Math.floor((originX + x) / tileWidth);
return this.roundX(mapX);
};
/**
* Get map y from canvas y
*
* @param {number} y - The y value to convert
* @return {number} The map y
*/
Game_Map.prototype.canvasToMapY = function(y) {
const tileHeight = this.tileHeight();
const originY = this._displayY * tileHeight;
const mapY = Math.floor((originY + y) / tileHeight);
return this.roundY(mapY);
};
/**
* Autoplays map audio
*/
Game_Map.prototype.autoplay = function() {
if ($dataMap.autoplayBgm) {
if ($gamePlayer.isInVehicle()) {
$gameSystem.saveWalkingBgm2();
} else {
AudioManager.playBgm($dataMap.bgm);
}
}
if ($dataMap.autoplayBgs) {
AudioManager.playBgs($dataMap.bgs);
}
};
/**
* Refresh the map only if needed
*/
Game_Map.prototype.refreshIfNeeded = function() {
if (this._needsRefresh) {
this.refresh();
}
};
/**
* Refresh the map
*/
Game_Map.prototype.refresh = function() {
for (const event of this.events()) {
event.refresh();
}
for (const commonEvent of this._commonEvents) {
commonEvent.refresh();
}
this.refreshTileEvents();
this._needsRefresh = false;
};
/**
* Refresh tile events
*/
Game_Map.prototype.refreshTileEvents = function() {
this._tileEvents = this.events().filter(event => event.isTile());
};
/**
* Get events at the given coordinates
*
* @param {number} x - The x coordinate to check for events
* @param {number} y - The y coordinate to check for events
* @return {Game_Event[]} The events at the given coordinates
*/
Game_Map.prototype.eventsXy = function(x, y) {
return this.events().filter(event => event.pos(x, y));
};
/**
* Get no-through events at the given coordinates
*
* @param {number} x - The x coordinate to check for events
* @param {number} y - The y coordinate to check for events
* @return {Game_Event[]} The NT events at the given coordinates
*/
Game_Map.prototype.eventsXyNt = function(x, y) {
return this.events().filter(event => event.posNt(x, y));
};
/**
* Get tile events at the given coordinates
*
* @param {number} x - The x coordinate to check for events
* @param {number} y - The y coordinate to check for events
* @return {Game_Event[]} The tile events at the given coordinates
*/
Game_Map.prototype.tileEventsXy = function(x, y) {
return this._tileEvents.filter(event => event.posNt(x, y));
};
/**
* Get the event id at the given coordinates
*
* @param {number} x - The x coordinate to check for events
* @param {number} y - The y coordinate to check for events
* @return {number} The event id
*/
Game_Map.prototype.eventIdXy = function(x, y) {
const list = this.eventsXy(x, y);
return list.length === 0 ? 0 : list[0].eventId();
};
/**
* Scrolls the map down
*
* @param {number} distance - The distance to scroll
*/
Game_Map.prototype.scrollDown = function(distance) {
if (this.isLoopVertical()) {
this._displayY += distance;
this._displayY %= $dataMap.height;
if (this._parallaxLoopY) {
this._parallaxY += distance;
}
} else if (this.height() >= this.screenTileY()) {
const lastY = this._displayY;
this._displayY = Math.min(
this._displayY + distance,
this.height() - this.screenTileY()
);
this._parallaxY += this._displayY - lastY;
}
};
/**
* Scrolls the map left
*
* @param {number} distance - The distance to scroll
*/
Game_Map.prototype.scrollLeft = function(distance) {
if (this.isLoopHorizontal()) {
this._displayX += $dataMap.width - distance;
this._displayX %= $dataMap.width;
if (this._parallaxLoopX) {
this._parallaxX -= distance;
}
} else if (this.width() >= this.screenTileX()) {
const lastX = this._displayX;
this._displayX = Math.max(this._displayX - distance, 0);
this._parallaxX += this._displayX - lastX;
}
};
/**
* Scrolls the map right
*
* @param {number} distance - The distance to scroll
*/
Game_Map.prototype.scrollRight = function(distance) {
if (this.isLoopHorizontal()) {
this._displayX += distance;
this._displayX %= $dataMap.width;
if (this._parallaxLoopX) {
this._parallaxX += distance;
}
} else if (this.width() >= this.screenTileX()) {
const lastX = this._displayX;
this._displayX = Math.min(
this._displayX + distance,
this.width() - this.screenTileX()
);
this._parallaxX += this._displayX - lastX;
}
};
/**
* Scrolls the map up
*
* @param {number} distance - The distance to scroll
*/
Game_Map.prototype.scrollUp = function(distance) {
if (this.isLoopVertical()) {
this._displayY += $dataMap.height - distance;
this._displayY %= $dataMap.height;
if (this._parallaxLoopY) {
this._parallaxY -= distance;
}
} else if (this.height() >= this.screenTileY()) {
const lastY = this._displayY;
this._displayY = Math.max(this._displayY - distance, 0);
this._parallaxY += this._displayY - lastY;
}
};
/**
* Check if the x/y coordinates given are valid
*
* @param {number} x - The x coordinate to check
* @param {number} y - The y coordinate to check
* @return {boolean} True if the coordinates are within the map bounds
*/
Game_Map.prototype.isValid = function(x, y) {
return x >= 0 && x < this.width() && y >= 0 && y < this.height();
};
/**
* Check the passage of the tile at the given coordinates
*
* @param {number} x - The x coordinate to check
* @param {number} y - The y coordinate to check
* @param {number} bit - The bit to perform bitwise AND operation on with the tile
* @return {boolean} True if passage allowed
*/
Game_Map.prototype.checkPassage = function(x, y, bit) {
const flags = this.tilesetFlags();
const tiles = this.allTiles(x, y);
for (const tile of tiles) {
const flag = flags[tile];
if ((flag & 0x10) !== 0) {
// [*] No effect on passage
continue;
}
if ((flag & bit) === 0) {
// [o] Passable
return true;
}
if ((flag & bit) === bit) {
// [x] Impassable
return false;
}
}
return false;
};
/**
* Get the tile id by coordinate
*
* @param {number} x - The x coordinate to check
* @param {number} y - The y coordinate to check
* @param {number} z - The z index of the tile
* @return {number} The tile id
*/
Game_Map.prototype.tileId = function(x, y, z) {
const width = $dataMap.width;
const height = $dataMap.height;
return $dataMap.data[(z * height + y) * width + x] || 0;
};
/**
* Get the layered tiles at the given coordinates
*
* @param {number} x - The x coordinate
* @param {number} y - The y coordinate
* @return {Array} The tiles at the coordinates
*/
Game_Map.prototype.layeredTiles = function(x, y) {
const tiles = [];
for (let i = 0; i < 4; i++) {
tiles.push(this.tileId(x, y, 3 - i));
}
return tiles;
};
/**
* Get the tiles at the given coordinates
*
* @param {number} x - The x coordinate
* @param {number} y - The y coordinate
* @return {Array} The tiles at the coordinates
*/
Game_Map.prototype.allTiles = function(x, y) {
const tiles = this.tileEventsXy(x, y).map(event => event.tileId());
return tiles.concat(this.layeredTiles(x, y));
};
/**
* Get the autotile type at the given coordinates
*
* @param {number} x - The x coordinate
* @param {number} y - The y coordinate
* @param {number} z - The z index of the tile
* @return {number} The autotile type
*/
Game_Map.prototype.autotileType = function(x, y, z) {
const tileId = this.tileId(x, y, z);
return tileId >= 2048 ? Math.floor((tileId - 2048) / 48) : -1;
};
/**
* Check if the map is passable
*
* @param {number} x - The x coordinate
* @param {number} y - The y coordinate
* @param {number} d - The direction to check
* @return {boolean} True if passable
*/
Game_Map.prototype.isPassable = function(x, y, d) {
return this.checkPassage(x, y, (1 << (d / 2 - 1)) & 0x0f);
};
/**
* Check if the map is passable for the boat
*
* @param {number} x - The x coordinate
* @param {number} y - The y coordinate
* @return {boolean} True if passable
*/
Game_Map.prototype.isBoatPassable = function(x, y) {
return this.checkPassage(x, y, 0x0200);
};
/**
* Check if the map is passable for the ship
*
* @param {number} x - The x coordinate
* @param {number} y - The y coordinate
* @return {boolean} True if passable
*/
Game_Map.prototype.isShipPassable = function(x, y) {
return this.checkPassage(x, y, 0x0400);
};
/**
* Check if the airship can land at the given coordinates
*
* @param {number} x - The x coordinate
* @param {number} y - The y coordinate
* @return {boolean} True if landing is ok
*/
Game_Map.prototype.isAirshipLandOk = function(x, y) {
return this.checkPassage(x, y, 0x0800) && this.checkPassage(x, y, 0x0f);
};
/**
* Check the layered tile flags
*
* @param {number} x - The x coordinate to check
* @param {number} y - The y coordinate to check
* @param {number} bit - The bit to perform bitwise AND operation on with the tile
* @return {boolean} True if a layered tile flag exists
*/
Game_Map.prototype.checkLayeredTilesFlags = function(x, y, bit) {
const flags = this.tilesetFlags();
return this.layeredTiles(x, y).some(tileId => (flags[tileId] & bit) !== 0);
};
/**
* Check if the tile is a ladder
*
* @param {number} x - The x coordinate to check
* @param {number} y - The y coordinate to check
* @return {boolean} True if the tile is a ladder
*/
Game_Map.prototype.isLadder = function(x, y) {
return this.isValid(x, y) && this.checkLayeredTilesFlags(x, y, 0x20);
};
/**
* Check if the tile is a bush
*
* @param {number} x - The x coordinate to check
* @param {number} y - The y coordinate to check
* @return {boolean} True if the tile is a bush
*/
Game_Map.prototype.isBush = function(x, y) {
return this.isValid(x, y) && this.checkLayeredTilesFlags(x, y, 0x40);
};
/**
* Check if the tile is a counter
*
* @param {number} x - The x coordinate to check
* @param {number} y - The y coordinate to check
* @return {boolean} True if the tile is a counter
*/
Game_Map.prototype.isCounter = function(x, y) {
return this.isValid(x, y) && this.checkLayeredTilesFlags(x, y, 0x80);
};
/**
* Check if the tile is a damage floor
*
* @param {number} x - The x coordinate to check
* @param {number} y - The y coordinate to check
* @return {boolean} True if the tile is a damage floor
*/
Game_Map.prototype.isDamageFloor = function(x, y) {
return this.isValid(x, y) && this.checkLayeredTilesFlags(x, y, 0x100);
};
/**
* Get the terrain tag of a tile
*
* @param {number} x - The x coordinate to check
* @param {number} y - The y coordinate to check
* @return {number} The terrain tag of the tile
*/
Game_Map.prototype.terrainTag = function(x, y) {
if (this.isValid(x, y)) {
const flags = this.tilesetFlags();
const tiles = this.layeredTiles(x, y);
for (const tile of tiles) {
const tag = flags[tile] >> 12;
if (tag > 0) {
return tag;
}
}
}
return 0;
};
/**
* Get the region id of a tile
*
* @param {number} x - The x coordinate to check
* @param {number} y - The y coordinate to check
* @return {number} The region id of the tile
*/
Game_Map.prototype.regionId = function(x, y) {
return this.isValid(x, y) ? this.tileId(x, y, 5) : 0;
};
/**
* Start a map scroll
*
* @param {number} direction - The direction of the scroll
* @param {number} distance - The distance of the scroll
* @param {number} speed - The speed of the scroll
*/
Game_Map.prototype.startScroll = function(direction, distance, speed) {
this._scrollDirection = direction;
this._scrollRest = distance;
this._scrollSpeed = speed;
};
/**
* Check if the map is scrolling
*
* @return {boolean} True if scrolling
*/
Game_Map.prototype.isScrolling = function() {
return this._scrollRest > 0;
};
/**
* Update the map
*
* @param {boolean} sceneActive - If the scene is active
*/
Game_Map.prototype.update = function(sceneActive) {
this.refreshIfNeeded();
if (sceneActive) {
this.updateInterpreter();
}
this.updateScroll();
this.updateEvents();
this.updateVehicles();
this.updateParallax();
};
/**
* Update the map scroll
*/
Game_Map.prototype.updateScroll = function() {
if (this.isScrolling()) {
const lastX = this._displayX;
const lastY = this._displayY;
this.doScroll(this._scrollDirection, this.scrollDistance());
if (this._displayX === lastX && this._displayY === lastY) {
this._scrollRest = 0;
} else {
this._scrollRest -= this.scrollDistance();
}
}
};
/**
* Get the distance to scroll
*
* @return {number} The distance to scroll
*/
Game_Map.prototype.scrollDistance = function() {
return Math.pow(2, this._scrollSpeed) / 256;
};
/**
* Perform the scroll
*
* @param {number} direction - The direction to scroll
* @param {number} distance - The distance to scroll
*/
Game_Map.prototype.doScroll = function(direction, distance) {
switch (direction) {
case 2:
this.scrollDown(distance);
break;
case 4:
this.scrollLeft(distance);
break;
case 6:
this.scrollRight(distance);
break;
case 8:
this.scrollUp(distance);
break;
}
};
/**
* Update events
*/
Game_Map.prototype.updateEvents = function() {
for (const event of this.events()) {
event.update();
}
for (const commonEvent of this._commonEvents) {
commonEvent.update();
}
};
/**
* Update vehicles
*/
Game_Map.prototype.updateVehicles = function() {
for (const vehicle of this._vehicles) {
vehicle.update();
}
};
/**
* Update the parallax
*/
Game_Map.prototype.updateParallax = function() {
if (this._parallaxLoopX) {
this._parallaxX += this._parallaxSx / this.tileWidth() / 2;
}
if (this._parallaxLoopY) {
this._parallaxY += this._parallaxSy / this.tileHeight() / 2;
}
};
/**
* Changes the tileset by id
*
* @param {number} tilesetId - The new tileset id
*/
Game_Map.prototype.changeTileset = function(tilesetId) {
this._tilesetId = tilesetId;
this.refresh();
};
/**
* Changes the battleback images
*
* @param {string} battleback1Name - The filename of the battle back 1 image
* @param {string} battleback2Name - The filename of the battle back 2 image
*/
Game_Map.prototype.changeBattleback = function(
battleback1Name,
battleback2Name
) {
this._battleback1Name = battleback1Name;
this._battleback2Name = battleback2Name;
};
/**
* Changes the parallax image
*
* @param {string} name - The filename of the parallax image
* @param {boolean} loopX - If the parallax loops horizontally
* @param {boolean} loopY - If the parallax loops vertically
* @param {number} sx - The horziontal scroll of the parallax
* @param {number} sy - The vertical scroll of the parallax
*/
Game_Map.prototype.changeParallax = function(name, loopX, loopY, sx, sy) {
this._parallaxName = name;
this._parallaxZero = ImageManager.isZeroParallax(this._parallaxName);
if (this._parallaxLoopX && !loopX) {
this._parallaxX = 0;
}
if (this._parallaxLoopY && !loopY) {
this._parallaxY = 0;
}
this._parallaxLoopX = loopX;
this._parallaxLoopY = loopY;
this._parallaxSx = sx;
this._parallaxSy = sy;
};
/**
* Update the interpreter
*/
Game_Map.prototype.updateInterpreter = function() {
for (;;) {
this._interpreter.update();
if (this._interpreter.isRunning()) {
return;
}
if (this._interpreter.eventId() > 0) {
this.unlockEvent(this._interpreter.eventId());
this._interpreter.clear();
}
if (!this.setupStartingEvent()) {
return;
}
}
};
/**
* Unlock an event by id
*
* @param {number} eventId - The id of the event to unlock
*/
Game_Map.prototype.unlockEvent = function(eventId) {
if (this._events[eventId]) {
this._events[eventId].unlock();
}
};
/**
* Sets up a starting event
*
* @return {boolean} True if event set up
*/
Game_Map.prototype.setupStartingEvent = function() {
this.refreshIfNeeded();
if (this._interpreter.setupReservedCommonEvent()) {
return true;
}
if (this.setupTestEvent()) {
return true;
}
if (this.setupStartingMapEvent()) {
return true;
}
if (this.setupAutorunCommonEvent()) {
return true;
}
return false;
};
/**
* Sets up a test event
*
* @return {boolean} True if event set up
*/
Game_Map.prototype.setupTestEvent = function() {
if (window.$testEvent) {
this._interpreter.setup($testEvent, 0);
$testEvent = null;
return true;
}
return false;
};
/**
* Sets up a starting map event
*
* @return {boolean} True if event set up
*/
Game_Map.prototype.setupStartingMapEvent = function() {
for (const event of this.events()) {
if (event.isStarting()) {
event.clearStartingFlag();
this._interpreter.setup(event.list(), event.eventId());
return true;
}
}
return false;
};
/**
* Sets up an autorun common event
*
* @return {boolean} True if event set up
*/
Game_Map.prototype.setupAutorunCommonEvent = function() {
for (const commonEvent of this.autorunCommonEvents()) {
if ($gameSwitches.value(commonEvent.switchId)) {
this._interpreter.setup(commonEvent.list);
return true;
}
}
return false;
};
/**
* Check if any events are starting
*
* @return {boolean} True if any event is starting
*/
Game_Map.prototype.isAnyEventStarting = function() {
return this.events().some(event => event.isStarting());
};