+++ DYNRPG - THE RM2K3 PLUGIN SDK +++
Posts
author=Kazesui
As for the problems you mentioned with conflicting data for different savefiles, this can be remedied by using the onLoad and onSave callbacks. This way you can store savefile specific data (like the battle speed), and reload it upon loading.
You are very right! It took a few hours to get right (still learning c++), but I finished what could be considered a pretty definitive "Faster ATB" plugin.
http://rpgmaker.net/users/PepsiOtaku/locker/faster_atb_advanced.rar
(source included)
Here's what it does:
Via the ini, you can set a Variable ID, along with a Default % multiplier for when the variable is set to 0. In the maker, you simply set the variable to a specified value (-4, -3, -2, -1, 1-16) and the battle speed will update accordingly. Check out the chart below:
Variable value | Percentage
===========================
-4 | 0 = Paused
-3 | 25
-2 | 50
-1 | 75
1 | 100 = RM2003's default
2 | 200 = 2x (Recommended)
3 | 300 = 3x (Also Recommended)
4 | 400 = 4x (Not bad, but hectic if using Active mode)
5 | 500
6 | 600
7 | 700
8 | 800
9 | 900
10 | 1000
11 | 1100
12 | 1200
13 | 1300
14 | 1400
15 | 1500
16 | 1600
Uses: A "battle speed" settings slider, Haste & Slow type spells, etc.
Hmmmm... I think what I want really, is not so much faster ATB at all (if anything, I found even trying to make monster and hero about equal if anything it feels too fast, but then I set it to 600). I liked the way turn-based worked. But... I discovered it didn't work correctly with DynRPG. I had David replacing the rpg2003.exe (no problem), and then I tried to run it and either none of my plugins seemed to work or it caused an actual crash on startup.
Basically, I want a sort of "pause" between monster and hero battler sequences. I sort of got something similar by doing this.
Would it be possible to write a code that turns off a switch if any party member attacks and on if the monster attacks (currently, I'd have to write this for each party member, then each battle event, resulting in ((286 battle events x 9 characters) + 344 monsters, or 2918 redundant code strings)). The switch would be called TurnEnd, and would basically create a gap where monsters would not attack (Switch ON TurnEnd as Precondition, Do Nothing) until any party member attacks. I'd saywould probably do it, but I have a few problems working with battle code (as in, I'm scared to death of it).
I'm gonna check out that code, and see if it helps any.
Basically, I want a sort of "pause" between monster and hero battler sequences. I sort of got something similar by doing this.

Would it be possible to write a code that turns off a switch if any party member attacks and on if the monster attacks (currently, I'd have to write this for each party member, then each battle event, resulting in ((286 battle events x 9 characters) + 344 monsters, or 2918 redundant code strings)). The switch would be called TurnEnd, and would basically create a gap where monsters would not attack (Switch ON TurnEnd as Precondition, Do Nothing) until any party member attacks. I'd say
RPG::Battler::turnsTaken
I'm gonna check out that code, and see if it helps any.
Yeah, I was making the ATB plugin mostly for my own benefit. I'm not sure how to approach turn-based combat though. I too am scared to start rewriting battle system code. :-/
My next coding project is going to utilize the CustomSaveLoadPatch, but I'm gonna keep it under wraps for now!
My next coding project is going to utilize the CustomSaveLoadPatch, but I'm gonna keep it under wraps for now!
I figured out the solution to the problem without a plugin.
Turn 7x or so:
If Turns is 0 (To reset things)
Turns is equal to Monster Number
Turn Wait On
And another thing to countdown turns before shutting off Turn Wait, using every possible character action in another Turn 1x even to basically say Turns -1 and shut off at 0.
The only other thing is putting all the monsters (I want) with Do Nothing for TurnWait ON. It's sort of a screwy mix of ATB and turn-based. Which is exactly what I wanted.
Edit: Sorry, that's wrong.
Turn-based code is...
Turn 1x
(Inside Common Event: Enemy Turn)
If Turn Wait OFF
If Turns is >= Monster Number
Turn Wait ON
Else
Turns +1
End Event Processing
Then you set to each party action under another Turn 1x (tedious...) such as
Hero1 uses Attack. You don't need fifty pages, just one page with a very long list.
(Inside Common Event: Your Turn)
If Turn Wait ON
If Turns is <= 0
Turn Wait ON
Else
Turns -1
End Event Processing
It's basically a seesaw effect of numbers. At the start of battle, you'll need to set it at one or the other end.
If Turns is 0 (To reset things)
Turns is equal to Monster Number
Turn Wait On
And another thing to countdown turns before shutting off Turn Wait, using every possible character action in another Turn 1x even to basically say Turns -1 and shut off at 0.
The only other thing is putting all the monsters (I want) with Do Nothing for TurnWait ON. It's sort of a screwy mix of ATB and turn-based. Which is exactly what I wanted.
Edit: Sorry, that's wrong.
Turn-based code is...
Turn 1x
(Inside Common Event: Enemy Turn)
If Turn Wait OFF
If Turns is >= Monster Number
Turn Wait ON
Else
Turns +1
End Event Processing
Then you set to each party action under another Turn 1x (tedious...) such as
Hero1 uses Attack. You don't need fifty pages, just one page with a very long list.
(Inside Common Event: Your Turn)
If Turn Wait ON
If Turns is <= 0
Turn Wait ON
Else
Turns -1
End Event Processing
It's basically a seesaw effect of numbers. At the start of battle, you'll need to set it at one or the other end.
author=PepsiOtaku
Say you had 2+ save files setup. In both save files, the ATB mode was set to 200. If you were to go into one of them and change it to 400 (via an event through some kind of custom menu), quit back to the title screen and then go into the other save file that in theory should be 200, it would now be set to 400. Therefor, you could have a menu slider that says "Battle Speed: 200" since that's what the variables say, but it could still be different based on one of your other saves. If you absolutely had to give the player the ability to change battle speed in-game, it would have to be a setting in the title screen you build.
I had written a similar variation of that plugin to say "if a variable is 0 (default): use 200 battle speed, if 1: use 100 battle speed, if 2: use 200, if 3: use 300, if 4: use 400," but it was quickly scrapped after I found out the above.
That's why you have to save and load these settings like battle speed, battle layout or anything in DBSystem or DBActor manually (in onSaveGame/onLoadGame).
@Kazesui: In your code, I wouldn't use global_vol as absolute value, but as percentage. So you will multiply the volume by global_vol/100... This way people can still control a relative volume of sound effects...
author=Cherry
That's why you have to save and load these settings like battle speed, battle layout or anything in DBSystem or DBActor manually (in onSaveGame/onLoadGame).
@Kazesui: In your code, I wouldn't use global_vol as absolute value, but as percentage. So you will multiply the volume by global_vol/100... This way people can still control a relative volume of sound effects...
Yeah, the onSaveGame/onLoadGame stuff makes more sense now. I've been reading more about C++ and the DynRPG SDK this week, so I'm definitely seeing more possibilities and workarounds.
With that, I'm making a really slick plugin right now that lets you save a range of variables to binary file after saving your game, starting at an identifier defined by var 3351 (via the CustomSaveLoad patch). The file acts as a "global" save file to store variable data from multiple save files.
By setting the variable to a particluar identifier again in your save/load menu (essentially querying the binary file), you can pull specific save game variables, querying information like other party member info, game locations, gold, treasure chests collected, or anything you could ever want/desire, and load them back into that range of variables. I've kept the actual range value low, since you shouldn't need more than 100 variables to query. With 99 potential saves, the binary file's size comes out to only about 50k.
The end result is that when you can press up and down in your menu to select save files, you can query for this information and show it on-screen. The CustomSaveLoad only supports the first party member's name, HP and level otherwise. You could make the YanFly save engine in 2k3 if you wanted to.
So far, the write portion of this plugin is coded and tested (works beautifully) and I have the read portion coded, but won't be able to test until later today. There's also a "check" to make sure the global save file is present upon startup, but there's a minor bug with that so far that I need to fix.
I'm gonna post the plugin/source probably over the weekend since I'd like to event my menu and make sure everything works first. Stay tuned!
I did something similar for SU. I wanted to have a block of switches be global, in order to do things like config options, that would remain identical between RPG Maker save files.
Might as well dump it here; it may help you or someone else:
You can load your switches with @loadconfig and write their values with @saveconfig comments.
Switches 2615-2620 are hard-coded as the global switches.
If there's an I/O error, 2621 is set to true so you can handle in 2k3.
EDIT: data is stored in a plain text file -- 'config.dat'
Might as well dump it here; it may help you or someone else:
#define AUTO_DLLMAIN
#include <fstream>
#include <iostream>
#include <DynRPG/DynRPG.h>
using namespace std;
// creates our config based on the values in the switches
void createFile(){
ofstream myfile;
myfile.open ("config.dat");
if(myfile.is_open()){
for(int i=0; i<6; i++){
myfile << RPG::system->switches[2615+i] << "\n";
}
myfile.close();
} else {
RPG::system->switches[2621] = true;
}
}
// loads our config settings
void readFile(){
string line;
ifstream myfile ("config.dat");
if (myfile.is_open()){
int index = 2615;
while ( myfile.good() ){
getline (myfile,line);
if (line.compare(0,1,"1",0,1)){
RPG::system->switches[index] = false;
} else {
RPG::system->switches[index] = true;
}
if (index > 2620){
break;
}
index++;
}
myfile.close();
} else {
// cannot open file! -- try to create it
createFile();
}
}
void onLoadGame(int id, char *data, int length){
readFile();
}
bool onComment (const char* text, const RPG::ParsedCommentData* parsedData, RPG::EventScriptLine* nextScriptLine,RPG::EventScriptData* scriptData, int eventId, int pageId, int lineId, int* nextLineId){
if (strcmp(parsedData->command, "loadconfig") == 0){
readFile();
} else if (strcmp(parsedData->command, "saveconfig") == 0){
createFile();
}
return true;
}
Switches 2615-2620 are hard-coded as the global switches.
If there's an I/O error, 2621 is set to true so you can handle in 2k3.
EDIT: data is stored in a plain text file -- 'config.dat'
Hello guys, i've spotted a bug recently on dynrpg and that's about character transparency , for instance events and my character cant be shown semi - transparent, obscure bottom half and Obscure bottom third. Also events can be shown transparent when they are placed below hero or above hero.Is there a way to fix this bug?
Are you also gonna work on the stuff that's "Not Implemented Yet" (ActorLearning, Chipset, MoveRouteItem, AuroraDrawMain)?
And maybe something to mess with wherever the menu items/skills/etc are stored. I tried to find someway of finding the spells used/possessed (something like if you use a certain skill, you can trigger something or turn on a switch or variable). And then I found that there didn't seem to be one. They just had battle menu item/skills.
And maybe something to mess with wherever the menu items/skills/etc are stored. I tried to find someway of finding the spells used/possessed (something like if you use a certain skill, you can trigger something or turn on a switch or variable). And then I found that there didn't seem to be one. They just had battle menu item/skills.
It seems that bulmabriefs144 found just the same issue that troubles me. I'll ask again: is there any way to fix the national alphabet with DynRPG?
National alphabet?
I did however get a glitch after patching all my stuff for DynRpg. I'm not very good at font patching to start with, and for some reason alot of my visual stuff (condition_icons for instance) went out the window after I tried the turn-based. So I had to fix and replace thing, and then repatch things.
No DynRPG
After DynRPG
My font suddenly went from two distinct fonts to a very default font. Is there a way to patch this back in?
I did however get a glitch after patching all my stuff for DynRpg. I'm not very good at font patching to start with, and for some reason alot of my visual stuff (condition_icons for instance) went out the window after I tried the turn-based. So I had to fix and replace thing, and then repatch things.
No DynRPG

After DynRPG

My font suddenly went from two distinct fonts to a very default font. Is there a way to patch this back in?
Of course, just use Hyper Patcher 2 ( http://cherrytree.at/download/?did=10 ) or the Font Changer to re-set the font name to yours.
Whew! Thanks, the Font Changer worked. I can't get HyperPatcher 2 to work for anything (something about how I don't have a valid RTP file, either because I've been using Resource Hacker alot, or because I didn't ever get the original RTP copy). Nvm, I seldom use it.
What's Cerberus mean by national alphabet?
What's Cerberus mean by national alphabet?

MUAHAHAHAHA!
So my custom save/load menu has been evented. I finished the global save data plugin and a delete save plugin. I came across a weird issue over the weekend where the save data plugin caused a memory leak or something, and ended up filling up hard drive space on drive C (over the course of a day while I was testing things). Upon restarting, that space gets cleared up, but obviously it's a huge issue. I think I fixed it by adding a fstream "flush" command, but I'm still skeptical. I'm thinking it should be placed after the write command (within write_to_binary) but I need a second opinion. Would someone mind looking this over? I know it's not the most efficient in terms of variables declared etc, but from a functional standpoint, it works great in-game.
#define AUTO_DLLMAIN
#include <DynRPG/DynRPG.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
using namespace std;
int saveSlotID;
int saveSlotOffset;
int varRangeStart = 4101;
int varRangeEnd = 4199;
int varRangeDiff = varRangeEnd - varRangeStart;
signed int varArray[9999];
int checkVarIndex;
int varPointer;
//signed int readVariable;
//char filePath [31] = "DynPlugins\\globalVariables.dyn";
char filePath [31] = "SaveGlobal.dyn";
int blankData = 0;
fstream binary_file;
// function required to write values to a binary file
void write_to_binary(signed int id, signed int p_Data, int offset){
fstream binary_file;
binary_file.open(filePath,fstream::in|fstream::out|fstream::binary);
if (binary_file.is_open()) {
binary_file.seekp(offset);
//binary_file.write(NULL,sizeof(id));
binary_file.write(reinterpret_cast<char *>(&p_Data),sizeof(id));
//binary_file.close();
}
}
// function required to read values from a binary file
int read_from_binary(signed int id, signed int g_Data, int offset) {
fstream binary_file;
binary_file.open(filePath,fstream::in|fstream::binary);
if (binary_file.is_open()) {
binary_file.seekg(offset);
binary_file.read(reinterpret_cast<char *>(&g_Data),sizeof(id));
//binary_file.flush();
//binary_file.close();
}
return g_Data;
}
bool onStartup(char *pluginName) {
// FindFirstFile function load
WIN32_FIND_DATA lpFindFileData;
HANDLE hFind;
// Find the file defined in char "filePath"
hFind = FindFirstFile(filePath, &lpFindFileData);
if(hFind != INVALID_HANDLE_VALUE) {
FindClose(hFind);
} else {
fstream binary_file;
binary_file.open(filePath,fstream::out|fstream::binary);
if (binary_file.is_open()) {
//fill it with zeros!
write_to_binary(blankData, blankData, 40000);
binary_file.close();
}
}
return true;
}
// used to read values from the binary, and pass them back to rpg2003
bool onSetVariable(int id, int value){
if (id == 3351){
if (value > 0){
binary_file.flush();
saveSlotID = value;
saveSlotOffset = (saveSlotID-1)*400;
checkVarIndex = read_from_binary(saveSlotID, saveSlotID, saveSlotOffset); // make sure data's available
varPointer = varRangeStart;
RPG::variables[4098] = checkVarIndex; // output result to game for testing purposes
if (checkVarIndex == value) { // if index and saveslot are equal, run loop to read variables
for (int i=1; i<=varRangeDiff; i++) { // loops through each variable value in binary, and loads it to game
varArray[i] = read_from_binary(varArray[i], varArray[i], saveSlotOffset+(4*i));
RPG::variables[varPointer] = varArray[i];
varPointer++;
}
}
if (binary_file.is_open()) {
binary_file.close();
}
}
}
// used to save variable range to binary
if (id == 3346){
if (value > 0){
// Write to external file upon saving game
binary_file.flush();
saveSlotID = value;
saveSlotOffset = (saveSlotID-1)*400;
write_to_binary(saveSlotID, saveSlotID, saveSlotOffset);
varPointer = varRangeStart;
for (int i=1; i<=varRangeDiff; i++) {
varArray[i] = RPG::variables[varPointer];
write_to_binary(varArray[i], varArray[i], saveSlotOffset+(4*i));
varPointer++;
//RPG::variables[4099] = saveSlotID;
}
if (binary_file.is_open()) {
binary_file.close();
}
}
}
return true;
}
Would someone mind looking over this code
What I think is causing the memory leak is keeping the fstream open for that for.
My C++ is kinda shaky but I remember being taught to close this thing almost right after opening it. You could possibly do this alot better with each of the 30 something files individually done (yes, it would be a pain in the bum, but shutting these files after they do their job means not having some screwy overlap of information).
Then again, I've only done very basic fstream operations, so you might want a third opinion. I'm gonna test it out on my slow-ass computer to see how it works.
My C++ is kinda shaky but I remember being taught to close this thing almost right after opening it. You could possibly do this alot better with each of the 30 something files individually done (yes, it would be a pain in the bum, but shutting these files after they do their job means not having some screwy overlap of information).
Then again, I've only done very basic fstream operations, so you might want a third opinion. I'm gonna test it out on my slow-ass computer to see how it works.
author=bulmabriefs144
What's Cerberus mean by national alphabet?
The cyrillic letters became too wide after applying the patch.
Before:

After:

It's almost impossible to read, as you can see. With another font in the project settings - the same issue. Font Changer haven't used yet, maybe it will help...
I'd recommend the Lufia SDK. Among other stuff it has, it has FontChanger and a bunch of fonts as a bonus.
Pepsi could you make a demo (with variables defined by user)? I don't really know how to use it, so all I see is another storage thing with my old, not a new save system. The other thing is to restrict memory leaks, make an onExit code where you make sure everything is closed up good and tight. I didn't notice that last night, but I remembered alot of these image scripts had image destruction as a safeguard for creating runaway memory. File close/flush at the very end (again, my grasp on fstream beside the very basic is weak, so some of this you'll need to experiment yourself) will probably do the same.
Pepsi could you make a demo (with variables defined by user)? I don't really know how to use it, so all I see is another storage thing with my old, not a new save system. The other thing is to restrict memory leaks, make an onExit code where you make sure everything is closed up good and tight. I didn't notice that last night, but I remembered alot of these image scripts had image destruction as a safeguard for creating runaway memory. File close/flush at the very end (again, my grasp on fstream beside the very basic is weak, so some of this you'll need to experiment yourself) will probably do the same.
author=bulmabriefs144
I'd recommend the Lufia SDK. Among other stuff it has, it has FontChanger and a bunch of fonts as a bonus.
Pepsi could you make a demo (with variables defined by user)? I don't really know how to use it, so all I see is another storage thing with my old, not a new save system. The other thing is to restrict memory leaks, make an onExit code where you make sure everything is closed up good and tight. I didn't notice that last night, but I remembered alot of these image scripts had image destruction as a safeguard for creating runaway memory. File close/flush at the very end (again, my grasp on fstream beside the very basic is weak, so some of this you'll need to experiment yourself) will probably do the same.
I'll make a demo at some point when I'm confident with everything. Between that plugin and the event code, it's a huge working mess right now, haha. The menu still needs some optimizations, mainly with how it cycles through files. I plan on testing it on my netbook and figuring out what's laggy, and going from there.
As a preface, I haven't added configuration stuff in the plugin yet, so the code I posted actually only supports 100 variables at a time. The "400" value you see in the SaveSlotOffset ((saveSlotID-1)*400) is basically the number of variables in your range times 4. So if you want a range of say 1000 variables (not sure why you would need this many) you would start by changing that number to 4000.
As for how it works: get aquainted with the BetterAEP patch and the CustomSaveLoadPatch here first as it follows one of the conventions used: http://rpgmaker.net/forums/topics/9751/
So the big drawback to this patch out of the box is that it can only query the first hero's level, HP, and name. Considering the default save/load menu does more than that, there's room for improvement. Hence the reason for my plugin.
Explaining this whole thing is gonna make me puke, but here goes:
My plugin basically ignores the query conventions of the CustomSaveLoadPatch and checks variable 3351 for the save state ID, and pulls the values from the variable range (4101-4199) that are stored in globalVariables.dyn and stores them into 4101-4199 in-game. With that in mind, they need to exist in globalVariables.dyn first, so there has to be some kind of trigger in RPG maker to store them there. That's where variable 3346 comes in (very last section of code). If 3346 has been set to a value (the save state's value, above 0). It takes what is stored in variables 4101-4199, and places them in the database, using the save state's ID as a starting point, so no data is ever overwritten or corrupted.
When you do this:
A) SAVING THE GAME
1) Write the number of the save slot you want to use into variable 3351 (not limited to 1-15! Can also be zero or a number greater than 15.)
2) Open the save menu
EXAMPLE:
<> Change Variable {3351:SaveID} = 20
<> Call Save Menu
This will save the game into slot 20.
The plugin adds an extra step that requires this:
EXAMPLE:
<> Change Variable {3346:SaveExport} = 20
-- Saves variables 4101-4199 to globalVariables.dyn
<> Change Variable {3351:SaveID} = 20
<> Call Save Menu
This will save the game into slot 20.
Save 20 is calculated with ((saveSlotID-1)*400) so if you open globalVariables.dyn and jump to decimal position 7600, you'll see your variables placed there in sequential order. The binary file starts at position 0, so that formula has to have "-1" in case you are saving to slot 1 (which will equate to 0).
The for loops are used to go through each variable, and assign them a spot in the array "varArray" using i. The (saveSlotOffset+(4*i)) calculates the actual decimal position in the binary file each variable will be stored in. It has to be a multiple of 4, since it takes 4 bytes to store 1 variable. Every 4 hex values will contain a new one. Reading is coded the same way, but in reverse.
As an aside, the "onStartup" function checks if the file "globalVariables.dyn" exists, and if it does not, creates one and writes "0" (blankData) to position 40000 (since this position is greater than (99-1)*400. 40000 is another value you would need to change if you wanted to support more than 100 variables. This is necessary, because if the file doesn't exist, then the fstream read/write functions won't do anything, and if a user decided to delete globalVariables.dyn, then they'd break the save/load menu. This function prevents a situation like that.
The eventing process kind of goes in this order:
1) Create some variables in the range of 4101-4199, and make a common event that saves hero stats, game stats or anything you want to query in your save menu.
2) Create some kind of way to set the save slot ID to variable 3346. For test purposes, you can use the Input Number command w var 3346.
3. Use <> Change Variable {3351:SaveID} = 20 & <> Call Save Menu to actually save your game as you would normally using the CustomSaveLoadPatch.
At this point, you should have your .lsd game save, along with data in the globalVariables.dyn database, so you can query for them.
1) Start by setting variables 4101-4199 to 0 so that you know the values you get are being pulled from globalVariables.dyn. Use a "Wait until key pressed" event and hit F9 ingame to verify this.
2) Use "<> Change Variable {3351:SaveID} = 20" or "Input Number" command w var 3351 to query for various saves (20 is used in this example). At this point, the variables will be automatically pulled into rpg maker. If your .lsd file exists, variable 3352 will return "1", otherwise it will return "0" (per the CustomSaveLoadPatch notes) So you could then write a conditional that says "if var 3352 is 1, show me the data on the screen." You could do this a number of ways but the easiest thing to do for testing purposes is a "Wait until key pressed" event, hit F9 ingame and find your variables. They should have the values contained in your database. Do this with multiple save files and you should be able to query information from any save file, into any of them.
To actually load a game, you can just do this (per the SaveLoadPatch):
<> Change Variable {3351:SaveID} = 20
<> Change Variable {3350:BetterAEP} = 1
<> End Event Processing
It only gets more complicated from there when you have to event your menu, but you basically want to query for information every time you select a new save file, so that you can load those variables, and then use something like the DynText plugin to show it onscreen, and you only want to save to the database upon actually saving your game.
TL;DR: RPG Maker 2003 is my bitch.
I posted some info about how the actual menu works here: http://rpgmaker.net/games/20/images/34230/

















