UNPKG

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
//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;