jams_mapper
Version:
A RPG Maker MZ plugin that allows you to load maps while walking rather than warping.
583 lines (515 loc) • 21 kB
JavaScript
//Initialize Map Sectors
$leftSector = null;
$rightSector = null;
$upperSector = null;
$lowerSector = null;
$upperLeftSector = null;
$upperRightSector = null;
$lowerLeftSector = null;
$lowerRightSector = null;
//this smooths out the gameplay, but I need to disable it, and handle the load balancing within my part of the application to avoid issues.
var JAMS_isMapLoaded = DataManager.isMapLoaded;
DataManager.isMapLoaded = function () {
var b = JAMS_isMapLoaded.call(this) && !!Jams.Mapper.map && Jams.Mapper.map.isSectorAlignmentLoaded();
Jams?.Logger?.log("DataManager.isMapLoaded", { return: b });
return b;
};
Game_Player.prototype._reserveTransfer = Game_Player.prototype.reserveTransfer;
Game_Player.prototype.reserveTransfer = function (mapId, x, y, d, fadeType) {
Jams?.Logger?.log("Game_Player.prototype.reserveTransfer", { mapId: mapId }, { x: x }, { y: y }, { d: d }, { fadeType: fadeType });
//perhaps I should just adjust the coordinates when loading the events instead of overriding this function.
Jams.Mapper._transfer = true;
x += $center.width;
y += $center.width;
this._reserveTransfer(mapId, x, y, d, fadeType);
};
var Jams_isMapObject = DataManager.isMapObject;
DataManager.isMapObject = function (object) {
Jams?.Logger?.log("DataManager.isMapObject", { object: object });
if (Jams_isMapObject(object)) {
Jams.Mapper.getNotes(object);
return true;
}
return false;
};
//Add src to object, so that we can add the notes to the world object.
DataManager.JAMSonXhrLoad = DataManager.onXhrLoad;
DataManager.onXhrLoad = function (xhr, name, src, url) {
Jams?.Logger?.log(`DataManager.onXhrLoad`, { xhr: xhr }, { name: name }, { src: src }, { url: url });
if (xhr.status < 400) {
obj = JSON.parse(xhr.responseText);
obj.src = src;
xhr = { status: xhr.status, responseText: JSON.stringify(obj) }
}
DataManager.JAMSonXhrLoad(xhr, name, src, url);
if (name == "$dataMap") {
Jams.Mapper.map = new Jams_Map($dataMap.src);
}
};
class Jams_Map {
xPos = 0;
yPos = 0;
constructor(src) {
Jams?.Logger?.log("Jams_Map.constructor", { src: src });
this.createLoadingSectors(src);
}
createLoadingSectors(src) {
Jams?.Logger?.log("Jams_Map.createLoadingSectors", { src: src });
//Start loading files
const filename = src;
const mapId = parseInt(src.replace(".json", "").replace("Map", ""));
Jams.Mapper.loadingSectors = [];
Jams.Mapper.sectorAlignment.forEach(arr => {
[world, x, y] = Jams.Mapper.maps[filename];
arr.map = null;
var xPos = (parseInt(x) + parseInt(arr.x)).toString();
var yPos = (parseInt(y) + parseInt(arr.y)).toString();
if (Jams.Mapper.Sectors.hasOwnProperty(world) && Jams.Mapper.Sectors[world].hasOwnProperty(xPos) && Jams.Mapper.Sectors[world][xPos].hasOwnProperty(yPos)) {
arr.map = Jams.Mapper.Sectors[world][xPos][yPos];
arr.sector = new Jams_Sector(arr.name, arr.map, xPos, yPos);
} else {
arr.sector = new Jams_Sector(arr.name, arr.map, xPos, yPos);
}
Jams.Mapper.loadingSectors.push(arr);
});
this.create(mapId);
}
create(mapId) {
Jams?.Logger?.log("Jams_Map.create", { mapId: mapId });
$dataMap.width *= 3;
$dataMap.height *= 3;
this.clearMapData($dataMap.width, $dataMap.height);
$gameMap._events.forEach(e => {
if (e) {
$dataMap.events[e._eventId] = null;
e.erase();
$gameMap._events[e._eventId] = null;
Jams.Mapper.openID.push(e._eventId);
}
});
//this.loadSectors();
};
//loadSectors = function () {
// Jams?.Logger?.log("Jams_Map.loadSectors");
// for (var i in Jams.Mapper.loadingSectors) {
// var s = Jams.Mapper.loadingSectors[i];
// s.sector.refresh();
// }
//};
clearMapData = function (w, h) {
Jams?.Logger?.log("Jams_Map.clearMapData", { w: w }, {h:h});
for (let k = 0; k < w * 3 * h * 3 * 6; k++) { //Zero out the original map
$dataMap.data[k] = 0;
}
};
isSectorAlignmentLoaded = function () {
DataManager.checkError();
var b = false;
for (const sector of Jams.Mapper.loadingSectors) {
if (sector.sector.isLoaded()) {
b = true;
}
}
Jams?.Logger?.log("Jams_Map.isSectorAlignmentLoaded", {return:b});
return b;
}
}
/*:
* @plugindesc Mapper is a plugin that combines maps together and points to the new maps when the game is ran.// Describe your plugin
* @author Michael Stephens
*/
function JamsMapper() {
this.initialize(...arguments);
}
JamsMapper.prototype.initialize = function () {
this._transfer = false;
this.map;
this.Sectors = {};//Lookup map filename by position.
this.maps = {}; //Lookup sector position by map filename.
//Unique Id generation
this.openID = new Array();
this.generateID = this.eventIDGenerator();
this.loadMetaData = true;//only need to load this once
this.isSectorLoading = true;
this.loadingSectors = []; //loaded sectors
this.sectorAlignment =
[
{ name: "$leftSector", x: -1, y: 0 },
{ name: "$rightSector", x: 1, y: 0 },
{ name: "$upperSector", x: 0, y: 1 },
{ name: "$lowerSector", x: 0, y: -1 },
{ name: "$upperLeftSector", x: -1, y: 1 },
{ name: "$upperRightSector", x: 1, y: 1 },
{ name: "$lowerLeftSector", x: -1, y: -1 },
{ name: "$lowerRightSector", x: 1, y: -1 },
{ name: "$center", x: 0, y: 0 }
];
this._mapSectionEvent = new JamsPlayerPosEvent("mapSection");
this._mapSectionEvent.update({
"x": "",
"y": ""
});
//Creaate Subscriptions
Jams.EventBus.subscribe(
"$dataMapInfos",
object => this.loadDataFiles(object)
);
Jams.EventBus.subscribe(
"playerPos",
object => this.triggerMapSection(object, $dataMap)
);
Jams.EventBus.subscribe(
"mapSection",
object => this.loadSectorAxis(object)
);
Jams.EventBus.subscribe(
"Character Sprites Loaded",
object => this.getCharacterSprites(object)
);
this.createDebug();
};
/**
* @description create an auto incrementing identity
* @yields {number} the identity
*/
JamsMapper.prototype.eventIDGenerator = function* () {
var id = 0;
while (true) {
yield id++;
}
};
//load positional data from all maps.
JamsMapper.prototype.loadDataFiles = function () {
if (this.loadMetaData) {
window.$dataMapInfos.forEach(map => {
if (map?.id > 0) {
const id = parseInt(map.id).toString();
const filename = "Map%1.json".format(id.padZero(3));
DataManager.loadDataFile("$center", filename);
}
});
this.loadMetaData = false; //this needs to happen only once.
}
};
/**
* @description Add Character sprites and tile map to object for easy reference.
*/
JamsMapper.prototype.getCharacterSprites = function (object) {
this._characterSprites = object._characterSprites;
this._tilemap = object._tilemap;
};
/**
* @description trigger Map Section Event
* @param object Map section event
*/
JamsMapper.prototype.triggerMapSection = function (playerPos, dataMap) {
if (dataMap) {
this._mapSectionEvent.update(this.getMapSector(playerPos, dataMap));
}
};
/**
* @description Add debugger metrics;
*/
JamsMapper.prototype.createDebug = function () {
Jams.FPSManager.addMetric("Map Sect: ", "mapSection", 0);
};
JamsMapper.prototype.getMapSector = function (playerPos, dataMap) {
if (playerPos && dataMap) {
const { width, height } = dataMap;
const sectionWidth = width / 3;
const sectionHeight = height / 3;
const { x, y } = playerPos;
const xSection = (x - x % sectionWidth) / sectionWidth - 1;
const ySection = -(y - y % sectionHeight) / sectionHeight + 1;
return { "x": xSection, "y": ySection };
}
return { "x": null, "y": null };
}
/**
* @description verify if event already exists in the data map.
* @param uniqueId A unique identifier associated with each event.
*/
JamsMapper.prototype.eventExist = function (uniqueId) {
let bool = false;
$dataMap.events.forEach(e => {
if (e?.uniqueId == uniqueId) {
bool = true;
}
});
return bool;
}
/**
* @description Load the map notes to get sector position.
*/
JamsMapper.prototype.getNotes = function (object) {
const result = object.note.split(/\r?\n/) || new Array();
result.forEach(str => {
if (str.substring(0, 8) === "worldpos") {
const arr = str.substring(9).split(" ");
this.maps[object.src] = arr;
[world, x, y] = arr;
this.Sectors[world];
if (!this.Sectors.hasOwnProperty(world)) {
this.Sectors[world] = {};
}
if (!this.Sectors[world].hasOwnProperty(x)) {
this.Sectors[world][x] = {};
}
this.Sectors[world][x][y] = object.src;
}
});
};
JamsMapper.prototype.calcRangePos = function (min, max, number) {
const count = max + 1 - min;
if (number < 0) {
number += count * (Math.floor(-number / count) + 1); //Turn negatives into positives
}
return (number - min) % count + min;
};
JamsMapper.prototype.getSectionClear = function (newX, newY, xChange, yChange) {
let x = null;
let y = null;
if (xChange !== 0) {
x = this.calcRangePos(-1, 1, newX + xChange);
} else if (yChange !== 0) {
y = this.calcRangePos(-1, 1, newY + yChange);
}
return { "x": x, "y": y };
};
JamsMapper.prototype.getRelativeMapPosition = function (pos, prevPos) {
if (Math.abs(pos - prevPos) === 2) {
if (pos > prevPos) {
return -1;
} else {
return 1;
}
} else {
return pos - prevPos;
}
};
JamsMapper.prototype.loadSectorAxis = function (object) {
//console.trace("loadSectorAxis");
const x = this.getRelativeMapPosition(object.x, this.map.xPos);
const y = this.getRelativeMapPosition(object.y, this.map.yPos);
this.updateSection = this.getSectionClear(object.x, object.y, x, y);
this.map.xDir = x
this.map.yDir = y;
this.map.xPos = object.x;
this.map.yPos = object.y;
};
var Imported = Imported || {};
Imported.Jams = "1.0.0";
var Jams = Jams || {};
Jams.Mapper = Jams.Mapper || new JamsMapper();class Jams_Sector {
constructor(...args) {
this.initialize(...args);
}
initialize(...args) {
Jams?.Logger?.log("Jams_Sector.initialize("+this.name+")", { args: args });
this.name = args[0];
Jams.EventBus.
subscribe(
this.name,
object => this.refresh()
);
Jams.EventBus.subscribe(
"SectorChange",
object => this.test()
);
this.active = Jams_Sector.ActiveSector;
this.filename = args[1];
this.x = parseInt(args[2]);
this.y = parseInt(args[3]);
this.loadDataFile();
Jams.EventBus.subscribe(
"mapSection",
object => this.checkPrimary(object)
);
}
checkPrimary = function (object) {
Jams?.Logger?.log("Jams_Sector.checkPrimary(" + this.name + ")", { object: object });
if (object.x == this.x && object.y == this.y) {
if (!this.filename) {
console.error(this);
}
Jams_Sector.ActiveSector = this;
this.pushMapMeta();
Jams.EventBus.Jams_Event = Jams.EventBus.Jams_Event || new JamsEvent("SectorChange");
Jams.EventBus.publish("SectorChange", this);
}
}
test = function (){
const { x, y } = Jams.Mapper.updateSection;
if (x == this.x || y == this.y) {
if (!Jams_Sector.ActiveSector) {
console.error("ActiveSector is null");
}
console.log(Jams_Sector.ActiveSector);
console.log(Jams.Mapper.maps);
const { x, y, filename } = Jams_Sector.ActiveSector;
const [world, activeX, activeY] = Jams.Mapper.maps[filename];
var xOffset = this.x - x;
if (Math.abs(xOffset) == 2) {
xOffset = xOffset * -0.5;
}
var yOffset = this.y - y;
if (Math.abs(yOffset) == 2) {
yOffset = yOffset * -0.5;
}
var destX = parseInt(activeX) + xOffset;
var destY = parseInt(activeY) + yOffset;
if (Jams.Mapper.map.xDir != 0) {
destX = parseInt(activeX) + Jams.Mapper.map.xDir;
}
if (Jams.Mapper.map.yDir != 0) {
destY = parseInt(activeY) + Jams.Mapper.map.yDir;
}
this.filename = null;
if (Jams.Mapper.Sectors.hasOwnProperty(world) && Jams.Mapper.Sectors[world].hasOwnProperty(destX) && Jams.Mapper.Sectors[world][destX].hasOwnProperty(destY)) {
this.filename = Jams.Mapper.Sectors[world][destX][destY];//need to calculate which map to load.
}
this.loadDataFile();
Jams?.Logger?.log("Jams_Sector.test(" + this.name + ")", {xOffset:xOffset,yOffset:yOffset, "Jams.Mapper.map.xDir": Jams.Mapper.map.xDir, "Jams.Mapper.map.yDir": Jams.Mapper.map.yDir, world:world,activeX: activeX, activeY: activeY, destX:destX,destY:destY, x: x, y: y }, { this: { x: this.x, y: this.y } });
}
}
loadDataFile = function () {
if (this.filename) {
window[this.name] = null;
DataManager.loadDataFile(this.name, this.filename);
} else {
var emptySector = {};
emptySector.data = [];
for (let k = 0; k < $dataMap.width * 3 * $dataMap.height * 3 * 6; k++) { //Zero out the original map
emptySector.data[k] = 0;
}
emptySector.events = [];
emptySector.width = $dataMap.width/3;
emptySector.height =$dataMap.height/3;
emptySector.scrollType = 3;
window[this.name] = emptySector;
this.refresh();
}
Jams?.Logger?.log("Jams_Sector.loadDataFile(" + this.name + ")", { Jams_Sector: this }, {object:window[this.name]});
}
isLoaded = function () {
var b = false;
if (window[this.name]) {
b = true;
}
Jams?.Logger?.log("Jams_Sector.isLoaded(" + this.name + ")",b, { Jams_Sector: window[this.name] });
return b;
}
refresh = function () {
//this.clear();
//this.clearEvents();
this.clearEvents();
Jams?.Logger?.log("Jams_Sector.refresh(" + this.name + ")", { Jams_Sector: this });
var width = $dataMap.width;
var SectorWidth = width / 3;
var SectorVolume = SectorWidth * SectorWidth; //technically width*height, but we always assume a square.
var yVolume = SectorVolume * 3;
var mapVolume = SectorVolume * 9;
var m = window[this.name].data;
var xOffset = this.x + 1;
var yOffset = -this.y + 1;
let i = 0;
while (i < m.length) {
var mod = i % SectorWidth;
var layerMod = i % SectorVolume;
var Layer = (i - layerMod) / SectorVolume;
var Sector = (i - mod) / SectorWidth - SectorWidth * Layer;
var DestinationPosition = i + SectorWidth * Sector * 2 + xOffset * SectorWidth + yVolume * yOffset - Layer * SectorVolume + Layer * mapVolume;
$dataMap.data[DestinationPosition] = m[i];
i++;
}
this.createEvents();
}
createEvents = function () {
Jams?.Logger?.log("Jams_Sector.createEvents(" + this.name + ")", { Jams_Sector: this });
var m = JSON.parse(JSON.stringify(window[this.name])); //I need the original data in place for the other maps.
m.events.forEach(e => {
var id = m.src.replace(".json", "")
id = parseInt(id.substr(id.length - 3));
if (e && !Jams.Mapper.eventExist(id + e.id.padZero(5))) {
e.uniqueId = id + e.id.padZero(5);
if (Jams.Mapper.openID.length > 0) {
e.id = Jams.Mapper.openID.shift();
} else {
e.id = Jams.Mapper.generateID.next().value;
}
e.x += (this.x + 1) * m.width;
e.y += (this.y + 1) * m.width;
$dataMap.events[e.id] = e;
$gameMap._events[e.id] = new Game_Event(id, e.id);
if (Jams.Mapper._characterSprites) {
const sprite = new Sprite_Character($gameMap._events[e.id]);
Jams.Mapper._characterSprites.push(sprite);
Jams.Mapper._tilemap.addChild(sprite);
}
}
});
};
clearEvents = function () {
Jams?.Logger?.log("Jams_Sector.clearEvents(" + this.name + ")", { Jams_Sector: this });
$gameMap._events.forEach(e => {
if (e) {
const pos = this.getMapSector(e);
if (pos.x == this.x && pos.y == this.y) {
console.log(pos, e, window[this.name]);
$dataMap.events[e._eventId] = null;
e.erase();
$gameMap._events[e._eventId] = null;
Jams.Mapper.openID.push(e._eventId);
}
}
});
};
getMapSector = function (playerPos) {
//Jams?.Logger?.log("Jams_Sector.getMapSector", { playerPos: playerPos });
if (playerPos && window[this.name]) {
const { width, height } = window[this.name];
const { x, y } = playerPos;
const xSector = (x - x % width) / width - 1;
const ySector = -(y - y % height) / height + 1;
return { "x": xSector, "y": ySector };
}
return { "x": null, "y": null };
}
getRelativePosition = function () {
Jams?.Logger?.log("Jams_Sector.getRelativePosition(" + this.name + ")", { Jams_Sector: this });
const { x, y } = this.getActiveSector();
return { x: this.getRelativeMapPosition(this.x, x), y: this.getRelativeMapPosition(this.y, y) };
}
getActiveSector = function () {
Jams?.Logger?.log("Jams_Sector.getActiveSector(" + this.name + ")", { Jams_Sector: this });
if ($gamePlayer) {
const { width, height } = window[this.name];
const { x, y } = $gamePlayer;
const xSector = (x - x % width) / width - 1;
const ySector = -(y - y % height) / height + 1;
return { "x": xSector, "y": ySector };
}
return { "x": null, "y": null };
}
getSector = function () {
Jams?.Logger?.log("Jams_Sector.getSector(" + this.name + ")", { Jams_Sector: this });
width = $dataMap.width / 3;
x = ($gamePlayer.x - $gamePlayer.x % width) / width;
y = ($gamePlayer.y - $gamePlayer.y % width) / width;
for (i in this.sectorAlignment) {
if (x == this.sectorAlignment[i].x && y == this.sectorAlignment[i].y) {
return this.sectorAlignment[i].name;
}
}
};
pushMapMeta = function () {
Jams?.Logger?.log("Jams_Sector.pushMapMeta(" + this.name + ")", { Jams_Sector: this });
var map = window[this.name];
Object.keys(map).forEach(function (key) {
if ($dataMap[key] !== map[key] && key !== "data" && key !== "events" && key !== "width" && key !== "height" && key !== "scrollType") {
$dataMap[key] = map[key];
}
});
};
}
Jams_Sector.ActiveSector = null;