Get data from another map?

Lain

return "hi";
Member
Joined
Mar 11, 2017
Messages
10
Reaction score
1
First Language
German
Primarily Uses
RMMV
Hi,

In RGSS3 there was the possibility to get informations like height and width of non-active maps, by storing "load_data(sprintf("Data/Map%03d.rvdata2", mapid))" into a variable.

In MV, I can't seem to find a way to check height and width of a specific map that is not the current map. Any ideas?

thanks
 

Trihan

Speedy Scripter
Veteran
Joined
Apr 12, 2012
Messages
2,604
Reaction score
1,961
First Language
English
Primarily Uses
RMMV
DataManager.loadFile(NAME OF VARIABLE, FILENAME)

Example: DataManager.loadFile('map1Data', 'Map001.json');

You can then do map1Data.width or map1Data.height
 

Zalerinian

Jack of all Errors
Veteran
Joined
Dec 17, 2012
Messages
4,696
Reaction score
935
First Language
English
Primarily Uses
N/A
While that will work, it will make a global variable that anyone can see and edit. This is generally frowned upon, so only do this if you know what you're doing.
 

Lain

return "hi";
Member
Joined
Mar 11, 2017
Messages
10
Reaction score
1
First Language
German
Primarily Uses
RMMV
Thank you and sorry, my scripting is very rusty and I am new to javascript.

Do both the variable and the filename have to be in single quotes? DataManager.loadFile gives me an error, while DataManager.loadDataFile doesn't, but I don't seem to get the right information either way.

And is it possible to get the data based on a variable (mapid)?

This is the method I want it to use in:

// * [Method] mst_autotransfer
// Transfers the player depending on map meta data
Game_Player.prototype.mst_autotransfer = function(){
var edgedir = this.mst_overedge();
if(edgedir==8){var mapmeta = $dataMap.meta.north;}
if(edgedir==6){var mapmeta = $dataMap.meta.east;}
if(edgedir==4){var mapmeta = $dataMap.meta.west;}
if(edgedir==2){var mapmeta = $dataMap.meta.south;}
var transinfo = mapmeta.trim().split(' ');
var newmapid = eval(transinfo[0]);
if (edgedir == 8) {
var new_x = eval(transinfo[1]) || this.x;
var new_y = eval(transinfo[2]) || $dataMap.height - 1; //here I want it to use the new map instead of the current one
}
if (edgedir == 6) {
var new_x = eval(transinfo[1]) || 0;
var new_y = eval(transinfo[2]) || this.y;
}
if (edgedir == 4) {
var new_x = eval(transinfo[1]) || $dataMap.width - 1; //here I want it to use the new map instead of the current one
var new_y = eval(transinfo[2]) || this.y;
}
if (edgedir == 2) {
var new_x = eval(transinfo[1]) || this.x;
var new_y = eval(transinfo[2]) || 0;
}
var new_dir = eval(transinfo[3]) || this.direction();
var new_type = eval(transinfo[4]) || Lain.mst_fadetype;
this.reserveTransfer(newmapid, new_x, new_y, new_dir, new_type);
};
tl;dr: I want to be able to transfer the player to the right/bottom edges of the new map.
 

Llareian

Jack of All Trades, Master of None
Veteran
Joined
Jan 26, 2017
Messages
604
Reaction score
1,421
First Language
English
Primarily Uses
RMMV
Looks like if you use the function DataManager.loadMapData(mapId), it will overwrite $dataMap with the map you provide it. Normally I'd say this would be a terrible idea, but since you're transferring the player to that map anyway, it might work out just fine? (Disclaimer: I'm new to JS and MV, too...)

So I think it would look like this:

var newmapid = eval(transinfo[0]); //this is a line you already have
DataManager.loadMapData(newmapid); // this is the line I'm suggesting you add, then just let the rest of the code go as-is
 

Lain

return "hi";
Member
Joined
Mar 11, 2017
Messages
10
Reaction score
1
First Language
German
Primarily Uses
RMMV
Awesome, I think that is the right approach. For some reason, it doesn't instantly make width/height available, though. If I just put in the new line, it gives me this error:

"Cannot read property 'width' of null"

Maybe I need to refresh something? I have trouble finding a reference point for that stuff.
 

LTN Games

Indie Studio
Veteran
Joined
Jun 25, 2015
Messages
704
Reaction score
631
First Language
English
Primarily Uses
RMMV
It won't be available until it's loaded. Your best bet is to make a whole new function that handles the callbacks on it's own.

PHP:
// RM native loadDataFile but we handle the callbacks on our own
var loadDataFile = function(src, onLoad, onError, context) {
    var xhr = new XMLHttpRequest();
    var url = 'data/' + src;
    var result = null
    xhr.open('GET', url);
    xhr.overrideMimeType('application/json');
    xhr.onload = function() {
        if (xhr.status < 400) {
            result = JSON.parse(xhr.responseText);
            onLoad.call(context, result)
        }
    };
    xhr.onerror = function(err) {
        onError.call(context, err)
    };
    xhr.send();
};

//Call it like so
loadDataFile("Map%02", loadSuccess)

// This function will be called when the data file is loaded
var loadSuccess = function (data) {
    console.log('Load Success', data);
    console.log('Map Width: ', data.width);
}
If you don't quite know what is going on here, here is a different version

PHP:
// RM native loadDataFile but we handle the callbacks on our own
var loadDataFile = function(src, onLoad, onError, context) {
    var xhr = new XMLHttpRequest();
    var url = 'data/' + src;
    var result = null
    xhr.open('GET', url);
    xhr.overrideMimeType('application/json');
    xhr.onload = function() {
        if (xhr.status < 400) {
            result = JSON.parse(xhr.responseText);
            // The data file is loaded and you should be able to get the width and height of map
            console.log('Load Success', result.width);
        }
    };
    xhr.onerror = function(err) {
        console.log('ERROR! RUN!!');
    };
    xhr.send();
};
If you make this function in a class which is instantiated you will need to be sure to assign the context to 'this' of the class.
 

Lain

return "hi";
Member
Joined
Mar 11, 2017
Messages
10
Reaction score
1
First Language
German
Primarily Uses
RMMV
Thanks. I think that I understand the idea and I will try to implement that tomorrow.

Should I put all of it inside of my method or wouldn't it be better to create new methods in DataManager or Game_Player?
 

Lain

return "hi";
Member
Joined
Mar 11, 2017
Messages
10
Reaction score
1
First Language
German
Primarily Uses
RMMV
Thanks to that function, I am able to store width and height of another map into a variable.

But I have difficulties reading the data in my method in time.

I have expected this code to work, but it seems like it executes the transfer BEFORE it stores the result. Means I always get either an error or old data:

PHP:
Lain.mst_newmapdata = null;
Game_Player.prototype.mst_autotransfer = function(){
    var edgedir = this.mst_overedge();
    if(edgedir==8){var mapmeta = $dataMap.meta.north;}
    if(edgedir==6){var mapmeta = $dataMap.meta.east;}
    if(edgedir==4){var mapmeta = $dataMap.meta.west;}
    if(edgedir==2){var mapmeta = $dataMap.meta.south;}
    var transinfo = mapmeta.trim().split(' ');
    var newmapid = eval(transinfo[0]);
    DataManager.mst_loadMapDataInfo(newmapid);
    if (edgedir == 8) {
        var new_x = eval(transinfo[1]) || this.x;
        var new_y = eval(transinfo[2]) || Lain.mst_newmapdata.height - 1; //error (cant read) or old value
    }
    if (edgedir == 6) {
        var new_x = eval(transinfo[1]) || 0;
        var new_y = eval(transinfo[2]) || this.y;
    }
    if (edgedir == 4) {
        var new_x = eval(transinfo[1]) || Lain.mst_newmapdata.width - 1; //error (cant read) or old value
        var new_y = eval(transinfo[2]) || this.y;
    }
    if (edgedir == 2) {
        var new_x = eval(transinfo[1]) || this.x;
        var new_y = eval(transinfo[2]) || 0;
    }
    var new_dir = eval(transinfo[3]) || this.direction();
    var new_type = eval(transinfo[4]) || Lain.mst_fadetype;
    this.reserveTransfer(newmapid, new_x, new_y, new_dir, new_type);
};

DataManager.mst_loadMapDataInfo = function(mapId) {
    var src = 'Map%1.json'.format(mapId.padZero(3));
    var xhr = new XMLHttpRequest();
    var url = 'data/' + src;
    var result = null;
    xhr.open('GET', url);
    xhr.overrideMimeType('application/json');
    xhr.onload = function() {
        if (xhr.status < 400) {
            result = JSON.parse(xhr.responseText);
            Lain.mst_newmapdata = result;
        }
    };
    xhr.onerror = function(err) {
        console.log("Failed to load Map Info");
    };
    xhr.send();
};
Is there a way to make sure, that "DataManager.mst_loadMapDataInfo" gets completely executed before the transfer happens?

Edit: For now, I will just use $dataMap.height and $dataMap.width for auto transfers. My game's overworld has maps with the same size anyways and it's not the end of the world, if the user has to manually add the transfer coordinates in the notetags.
 
Last edited:

LTN Games

Indie Studio
Veteran
Joined
Jun 25, 2015
Messages
704
Reaction score
631
First Language
English
Primarily Uses
RMMV
okay, again it has to do with the asynchronous behavior of an XHR request. It does not return the data you want instantly which is why we handle the callbacks on our own. That being said, I'm unsure of exactly what you're attempting to achieve but it has something to do with a transfer.

So a solution again, would be to handle the transfer on a successful load of the map. I showed you how to do it in the previous post but, I know this stuff can be very confusing especially if your not entirely familiar with JS or programming in general. I have a solution below but with more commented lines in hopes to clear things up for you.

Let me know ifyou understand everything going on.

PHP:
// We add an onload callback argument which takes a function as it's value.
// We then add a context argument which is used for keeping refrence to 'this'
DataManager.mst_loadMapDataInfo = function(mapId, onload, context) {
    var src = 'Map%1.json'.format(mapId.padZero(3));
    var xhr = new XMLHttpRequest();
    var url = 'data/' + src;
    var result = null;
    xhr.open('GET', url);
    xhr.overrideMimeType('application/json');
    xhr.onload = function() {
        if (xhr.status < 400) {
            result = JSON.parse(xhr.responseText);
            Lain.mst_newmapdata = result;
            // On a succesful map load we then call our 'onload' function and pass in the result.
           // notice context is an argument as well. you're probably used to seeing .call(this)
            onload.call(context, result)
        }
    };
    xhr.onerror = function(err) {
        console.log("Failed to load Map Info");
    };
    xhr.send();
};


Game_Player.prototype.mst_autotransfer = function () {
  var edgedir = this.mst_overedge();
  if (edgedir == 8) { var mapmeta = $dataMap.meta.north; }
  if (edgedir == 6) { var mapmeta = $dataMap.meta.east; }
  if (edgedir == 4) { var mapmeta = $dataMap.meta.west; }
  if (edgedir == 2) { var mapmeta = $dataMap.meta.south; }
  var transinfo = mapmeta.trim().split(' ');
  var newmapid = eval(transinfo[0]);
// So here we load the map data and in the "onload" argument we create a new function which will
// run once the map data is loaded. Which means all info is available to us now, including the result // which is the mapdata info
  DataManager.mst_loadMapDataInfo(newmapid, function (result) {
    if (edgedir == 8) {
      var new_x = eval(transinfo[1]) || this.x;
      var new_y = eval(transinfo[2]) || Lain.mst_newmapdata.height - 1; //error (cant read) or old value
    }
    if (edgedir == 6) {
      var new_x = eval(transinfo[1]) || 0;
      var new_y = eval(transinfo[2]) || this.y;
    }
    if (edgedir == 4) {
      var new_x = eval(transinfo[1]) || Lain.mst_newmapdata.width - 1; //error (cant read) or old value
      var new_y = eval(transinfo[2]) || this.y;
    }
    if (edgedir == 2) {
      var new_x = eval(transinfo[1]) || this.x;
      var new_y = eval(transinfo[2]) || 0;
    }
    var new_dir = eval(transinfo[3]) || this.direction();
    var new_type = eval(transinfo[4]) || Lain.mst_fadetype;
    this.reserveTransfer(newmapid, new_x, new_y, new_dir, new_type);
  /// remember the context argument in our loaddata function? well we assign context to 'this'
  // so we don't lose refrence to the current class using this.
  }, this);
};
 

Lain

return "hi";
Member
Joined
Mar 11, 2017
Messages
10
Reaction score
1
First Language
German
Primarily Uses
RMMV
Ah yes, I didn't mention what I actually want to achieve with the code. I am currently recreating a script I wrote for VXA years ago. It lets the player move through the map edge and transfer him to another map with a slide effect. My goal is to make it as flexible as possible for users.

The code works perfectly now. One mistake I made was, that I haven't understood why and how to use the .call you added. I don't need the additional variable now.

PHP:
Game_Player.prototype.mst_autotransfer = function(){
    var edgedir = this.mst_overedge();
    if(edgedir==8){var mapmeta = $dataMap.meta.north;}
    if(edgedir==6){var mapmeta = $dataMap.meta.east;}
    if(edgedir==4){var mapmeta = $dataMap.meta.west;}
    if(edgedir==2){var mapmeta = $dataMap.meta.south;}
    var transinfo = mapmeta.trim().split(' ');
    var newmapid = eval(transinfo[0]);
    DataManager.mst_loadMapDataInfo(newmapid, function (result) {
        if(eval(transinfo[1])!==false){var new_x = eval(transinfo[1])+1;}else{var new_x = false;}
        if(eval(transinfo[2])!==false){var new_y = eval(transinfo[2])+1;}else{var new_y = false;}
        var new_dir = eval(transinfo[3]) || this.direction();
        var new_type = eval(transinfo[4])+1 || Lain.mst_fadetype+1;
        new_type--;
        if (edgedir == 8) {
            var new_x = new_x || this.x+1;
            var new_y = new_y || result.height;
        }
        if (edgedir == 6) {
            var new_x = new_x || 1;
            var new_y = new_y || this.y+1;
        }
        if (edgedir == 4) {
            var new_x = new_x || result.width;
            var new_y = new_y || this.y+1;
        }
        if (edgedir == 2) {
            var new_x = new_x || this.x+1;
            var new_y = new_y || 1;
        }
        new_x--;
        new_y--;
        this.reserveTransfer(newmapid, new_x, new_y, new_dir, new_type);
    }, this);
};

DataManager.mst_loadMapDataInfo = function(mapId, onload, context) {
    var src = 'Map%1.json'.format(mapId.padZero(3));
    var xhr = new XMLHttpRequest();
    var url = 'data/' + src;
    var result = null;
    xhr.open('GET', url);
    xhr.overrideMimeType('application/json');
    xhr.onload = function() {
        if (xhr.status < 400) {
            result = JSON.parse(xhr.responseText);
            onload.call(context, result)
        }
    };
    xhr.onerror = function(err) {
        console.log("Failed to load Map Info");
    };
    xhr.send();
};
Thanks again. It's a pretty complex solution for such a simple thing (automatically teleporting the player to the right or bottom map edge if the meta data doesn't say otherwise). But I have learned quite a bit.
 

Trihan

Speedy Scripter
Veteran
Joined
Apr 12, 2012
Messages
2,604
Reaction score
1,961
First Language
English
Primarily Uses
RMMV
Ah, so you were basically doing Zelda-style map transitions. Neat.
 

LTN Games

Indie Studio
Veteran
Joined
Jun 25, 2015
Messages
704
Reaction score
631
First Language
English
Primarily Uses
RMMV
Nice, I really like those transitions. I love Zelda!. I'm glad I could be a part of this re-creation and I'm glad I could help. It may seem like a complex solution but most of the complex stuff is getting around JavaScripts single threaded nature. Anyways, good luck, can't wait to see the final results.
 

Lain

return "hi";
Member
Joined
Mar 11, 2017
Messages
10
Reaction score
1
First Language
German
Primarily Uses
RMMV
Agreed, the transitions in the topdown Zelda games are awesome and it's a crime, that they aren't a native option in RMMV. Thanks again. I will post the results as soon as possible. Transfering through the map edges already works and I "just" need to add the Sliding Effect to it. This is the work in progress code.
 

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Profile Posts

Day 9 of giveaways! 8 prizes today :D
He mad, but he cute :kaopride:

Our latest feature is an interview with... me?!

People4_2 (Capelet off and on) added!

Just beat the last of us 2 last night and starting jedi: fallen order right now, both use unreal engine & when I say i knew 80% of jedi's buttons right away because they were the same buttons as TLOU2 its ridiculous, even the same narrow hallway crawl and barely-made-it jump they do. Unreal Engine is just big budget RPG Maker the way they make games nearly identical at its core lol.

Forum statistics

Threads
106,040
Messages
1,018,476
Members
137,824
Latest member
dobratemporal
Top