Comments

Log in with itch.io to leave a comment.

Hey, I've been doing some work with the plugin again, and I found another bug. And while I am thinking about, I have some suggestions that I thought I would mention.

Bug

While loading a test file, I kept getting playtimes on the files that looked wrong. I am not super familiar with JavaScript, but it appeared to me that the code was:

  • e = system._framesOnSave from the old save
  • o (hours) = Math.floor(e/3600)
  • e (minutes this time) = Math.floor((e-3600*o)/60)

So unless I am overlooking something in the code, the intent appears to be to divide the number of frames by 60 to get minutes and then 60 again to get hours. Problem is that there are 60 frames per second. So you are actually getting minutes and seconds instead of hours and minutes.

I changed the formulas to:

  • o= Math.floor(e/216000)
  • e = Math.floor((e-216000*o)/3600)

And the numbers I am getting are looking more reasonable. Alternatively, this could be fixed by dividing the frames by 60 before using them to calculate the hours.

Minor Suggestion

Add spaces to the default Old Saves loading message parts. Currently by default, the message will appear as "Savefile:file1 Playtime:75hoursand50min." It looks better as: "Savefile: file1 Playtime: 75 hours and 50 min." While devs can certainly add spaces themselves, I think it just presents a better first impression.

Note: If you act on this, make sure you are changing the mainText default entry. I spent a good amount of time messing with the translation under ~struct~mainText for the default translations unable to figure out why it wasn't working. XD Although, I guess making the default English translation consistent with the default settings also wouldn't be a horrible idea.

Feature Suggestion - Additional Error Handling

While testing an import, I encountered a "Searching for an old value out of range." Reason for that was that I was intentionally testing a save that I knew would cause problems. But I checked all the variables that were being imported and I found one that could cause issues from a proper save. Basically, it is a variable for an entirely optional quest and everything with a variable number higher it is also optional.

I was able to just code around this by adding a length check and if the variable array isn't long enough, I just write a null value to extend it.

However, it might be useful to add in the ability to change the way the plugin handles out of range errors by treating them as 0s, the same way you can change how it handles nulls.

Feature Suggestion - Old Save Removal

So in the game I'm collaborating on, there are multiple potential valid conditions for the save being imported (e.g., variable 1 > 5 or variable 2 > 10). As a result, the game imports and then checks for both the conditions. If the player later realizes they don't have a save to import, the originally imported save could be left in their save forever. I handle this with "delete $gameSystem._currentOldSave;" as a script.

While my usage of deleting the old save might be an edge case, adding the functionality to the plugin could be useful for purposes of reducing save size if a developer has copied over all the data they want from the old save.

Feature Suggestion - Old Save Pruning

Speaking of reducing save size, there is a lot of unused data in the currentOldSave such as settings for plugins from the old game. This will needlessly balloon the save size. So maybe add an option to choose which data to import? By default have the pruning (if enabled) keep variables, actors, switches, selfSwitches, and CurrentOldSave(in case you import a save that already has imported data?) with the option to add or remove sections? Here is the script I used to handle pruning in the game I'm working on in case it is helpful. I did not keep self switches in this code. Also, I do not fully understand this code, just modified some code for removing properties that I found online.

const allowedProperties = ['variables', 'actors', 'switches'];
const allKeys1 = Object.keys($gameSystem._currentOldSave);
$gameSystem._currentOldSave = allKeys1.reduce((next, key) => { if (allowedProperties.includes(key)) { return { ...next, [key]: $gameSystem._currentOldSave[key] };
} else { return next; } }, {});

Random Musing - Importing Imported Data

This might be too niche to warrant acting on, but while working with the pruning stuff, it occurred to me that by default if you import a save that already has an import, all the data from the imported file will still be there, just unusable.

I think that covers everything I was thinking of. Hope this was helpful and not just the ramblings of a crazy person. :P

Hi, can you help me with this error?

"Error

WD_OlsSaveLoader: Trying to access a null variable"

It happens after using the get information from old save command for this single variable, whose number is 616. (i have loaded a save and confirmed it properly)

As far as  I know, the variable exists in both the "prequel" as well as in the new game. The only thing that comes to mind is that the variable might have been 0 in the prequel.

Sorry to bother you.

I'll need to run some tests as that message should only appear if the value is "null", not 0

Found thanks to a collaborator. I didn't know the difference between null (never initialized by the game) and 0 (actually set to zero). 

We solved it by changing the error manager: Variable null ->  Set it to Pass a zero value

Bug report. I was messing around with the plugin, and it initially didn't work. F12 console was giving the error "Uncaught SyntaxError: Unexpected end of JSON input."

After a bit of digging in the code, I found the issue was with errorManager. And when I figured out how to fix that, I got the same error with prereqSave. The reason the issue was happening is that default settings for the plugin leave these two fields as empty, which causes the processing of the settings to just give up on game start.

Reason the default settings are blank is because of the bane of all programmers, a stupid typo! Both of these plugin properties have "deafult" values instead of default values. Fixing the typo for both settings allowed the plugin to boot with no errors in the F12 console in a clean project with no settings changes.

Shoot! Thanks for the comprehensive report, I'll release a patch tomorrow πŸ€—

Okay, so, I added it to my project and in the plugin manager. 

Created "oldsaves" folder and put a bunch of .rmmzsave files in it.

I put all three plugin commands in an event, but nothing happens. I disabled all other plugins, nothing happens, why could this be?

Thanks

So nothing at all happens? There is no selection window coming up but there isn't also an error?


That sound like RPG Maker not registering the command at all, is the plugin ON, the plugin file name hasn't been changed?

Exactly, the plugin is ON, i didn't change the name, and I disabled all the other plugins. I'm not using the latest MZ build (I'm on 1.7.0), would that be an issue?

Otherwise no idea. I'll try on a fresh project.

That's weird, version 1.7.0 shouldn't be the problem 😨

Can you send me a pic of the event and a pic of the plugin parameters?

Of course, where do I send it?

(1 edit)

You can send it to my mail ( winterdreamgamecreator@gmail.com ) or on Discord ( winthorp ) πŸ™‚

Very interesting. Does it only read or does it copy the data? I mean, can it check if switch X was on, and just tell me if so, then I can decide what to do with switch X in the new game?

Or does it find switch X is on and then automatically sets it as on in the new game?

Thanks

It copies and read, you instruct the plugin what to search and what to do with the results. Like you said, if old save had switch X on you can decide to turn new game switch Y on.


It can do it with switch, self switch, variables, heroes data and general game system informations

https://github.com/BossRpg/MVMZ-Advanced_ChangeSaveLocation/blob/main/Advanced_C...

It is best to use it with this plug-in, so that you can solve the problem of publishing games on Steam, but I have not tested whether your plug-in supports "%USERPROFILE%/Saved Games/" + $dataSystem.gameTitle + "/save/"

It doesn't as the directory is a string, not an eval, so it won't catch + and $dataSystem


But adding a "pro" option to use the evaluation could be something to add in the ToDo list! ☺️

So, without the +$dataSystem part, it should work? I actually mainly want to know if I can read "My Documents"

(1 edit)

If you mean by using environmental variables like %USERPROFILE%, no, not in v1.0
I'll work on adding the possibility!

Right now the plugin can either read a normal string path (ex: "C:\Mygame\") or he can detect his installation directory and from from there (option autodetect + data/ will result in a string heading toward the data folder of the game)

The following reference code is from a website that is not allowed to be linked by itch. You can directly refer to the code

'use strict';

/*

====================================================================================================================

 RoamingSavePath.js

 License: DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE

 Usage: add this lines to your plugins.js:

{"name":"RoamingSavePath","status":true,"description":"Save directory to game save dir instead of www","parameters":{}}

====================================================================================================================

*/

(function () {

if (!StorageManager.isLocalMode() || typeof process === 'undefined' || !process.env || !process.platform) return;

const fs = require('fs');

const path = require('path');

var globalSavePath = null;

const initPlugin = function () {

const defaultDir = process.env.APPDATA ?

"%USERPROFILE%/Saved Games/" + $dataSystem.gameTitle + "/save/" :

(process.platform == "darwin" ? "%HOME%/Library/Preferences/" : "%HOME%/.local/share/");

const params = PluginManager.parameters('RoamingSavePath');

var savePath = ((params['Save Directory'] || defaultDir).trim().replace(/^[/\\\.]+|[/\\\.]+$/g, '') + path.sep).replace(/[/\\]/g, path.sep);

for (var e in process.env) {

savePath = savePath.replace('%' + e + '%', process.env[e]);

}

globalSavePath = savePath;

}

const validateDirTree = function (targetDir) {

if (fs.existsSync(targetDir)) return true;

const parts = targetDir.split(path.sep); 

var currentPath = parts[0]; 

for (var i = 1; i < parts.length; i++) { 

if (!parts[i]) continue;

currentPath +=  path.sep + parts[i]; 

if (!fs.existsSync(currentPath)) { 

try {

fs.mkdirSync(currentPath); 

} catch (e) {

return false;

}

}

}

return true;

}

const oldDMOL = DataManager.onLoad;

DataManager.onLoad = function(object) {

oldDMOL.apply(this, arguments);

if (object === $dataSystem)

initPlugin();

}

StorageManager.localFileDirectoryPath = function() {

return globalSavePath;

};

const oldSTLF = StorageManager.saveToLocalFile;

StorageManager.saveToLocalFile = function() {

//if (!fs.existsSync(globalSavePath))

//fs.mkdirSync(globalSavePath, { recursive: true }); // needs newer nwjs sometimes

if (validateDirTree(globalSavePath))

oldSTLF.apply(this, arguments);

}

})();

I like this. I don't think there's ever been a system made that does this, for any other iteration of RM, not even VX Ace.

Yes, searching for this option leads to a lot of questions and a very few answers, guess this will be a useful one 😁