[RM2K3] DYNRPG COMPILING ERROR

Posts

I have no personal experience with using Image outside of battle, so I don't know what might be causing your issue. I'd suggest looking through the other DynRPG plugins on this site, a lot of them include their source code and I'm pretty sure some involve Images outside of battle.

How an array actually works in C++ is that the system allocates a chunk of memory big enough to hold however many you ask for of whatever variable type, all clumped together in a row. The array variable is a pointer to the start of that chunk of memory -- you can even use the -> operator on it, and it'll work like a regular pointer on the first element of the array. When you use the square brackets operator, what you're doing is asking it to look at the memory address, then shift right by the size of the variable type x times. So to get the first element, you shift 0 times because you're already there, like myArray(0). To get to the second element you need to shift to the right by 1, so myArray(1), etc. It's a "close to the metal" mentality.

In fact, you can ask for an index outside what the array was allocated for, and it'll just shift that far into who-knows-what memory and give you what it finds. The compiler was smart enough to catch the error when you gave it a hard-coded shift of 11 for an array that was only 11 elements (including the 0th) to begin with, but it generally won't do that if you're using other variables for your index, and once the code is compiled and running all bets are off. C++ is a dangerous language in that way, it foregoes the safety checks more modern languages have built up in favor of power and efficiency. If you have code that references the "11th" element of an array, it'll appear to work a lot of the time because it's just blindly using the memory just off the edge of the array, but the system doesn't think that spot's been allocated, so it might decide to use it for another variable and overwrite what you've put there, or you could overwrite something else. You might want to go back and review your old code to prevent that sort of thing.
That is actually how I found out my array was overflowing because it kept changing the value of another variable and so I went back and checked all my code to find out it was a memory issue. I fixed all the arrays now, so it is fine now. Thanks for the clarification, I was confused why it wasn't working, but now it makes total sense.

I've gone over all the image plug-ins, but they all function during battle, except for one which happens to be the text plug that isn't open source. I think the text plugin uses existing images to properly use the drawstring function which is why you have to show an image via the show image command in rm2k3 before being able to write text. The plugin also doesn't function in battle. My guess is that DynRPG doesn't support creating images outside of battle. Tomorrow I'll try experimenting with the window class and hopefully be able to properly use it with no issues.
Text plugin works in battle, if you use the patch named picsinbattle.
http://share.cherrytree.at/showfile-14985/picsinbattle.ips

For the source code I have an older version of it(not the last one).



#define AUTO_DLLMAIN
#include <DynRPG/DynRPG.h>
#include <sstream>
#include <cstdlib>
#include <cstring>
#include <cmath>

struct textObj
{
int x;
int y;
int color;
bool fixed;
std::string txt;
RPG::Image* img;
};

std::string parseText(std::string in);
typedef std::map<std::string, textObj> TextMap;

int picID;
TextMap drawList;

bool onDrawPicture(RPG::Picture* picture)
{
if(picture->id == picID)
{
TextMap::iterator itr = drawList.begin();
while(itr != drawList.end())
{
int x = itr->second.x;
int y = itr->second.y;
if(itr->second.fixed)
{
x -= RPG::map->getCameraX();
y -= RPG::map->getCameraY();
}
itr->second.img->alpha = 255 - picture->transparency/100.0 * 255;
RPG::screen->canvas->draw(x, y, itr->second.img);
//RPG::screen->canvas->drawStretched(x, y, itr->second.img->width*3, itr->second.img->height*3, itr->second.img);
itr++;
}
}
return true;
}

void onInitTitleScreen()
{
TextMap::iterator itr = drawList.begin();
while(itr != drawList.end())
{
TextMap::iterator tmp = itr;
RPG::Image::destroy(itr->second.img);
itr++;
drawList.erase(tmp);
}
}

bool onStartup(char *pluginName)
{
std::map<std::string, std::string> configuration = RPG::loadConfiguration(pluginName);
std::map<std::string, std::string>::iterator itr = configuration.find("PictureID");
if(itr != configuration.end())
{
picID = atoi(itr->second.c_str());
}
else
picID = 1;
return true;
}

void onSaveGame(int id, void __cdecl(*savePluginData)(char*data,int length))
{
std::string s;
TextMap::iterator itr = drawList.begin();
while(itr != drawList.end())
{
std::stringstream ss;
ss << itr->second.x << "," << itr->second.y << ",";
ss << itr->second.txt << "," << itr->second.color << ",";
ss << itr->second.fixed << "," << itr->first << ",";
s += ss.str();
itr++;
}
savePluginData((char *)s.c_str(), s.size());
}

void onLoadGame(int id, char* data, int length)
{
char* buffer;
if(data == NULL) return;
buffer = strtok(data, ",");
while(buffer != NULL)
{
textObj obj;
obj.x = atoi(buffer);
buffer = strtok(NULL, ",");
obj.y = atoi(buffer);
buffer = strtok(NULL, ",");
obj.txt = buffer;
buffer = strtok(NULL, ",");
obj.color = atoi(buffer);
buffer = strtok(NULL, ",");
obj.fixed = atoi(buffer);
buffer = strtok(NULL, ",");
obj.img = RPG::Image::create(obj.txt.size()*6 + 8, 16);
obj.img->setSystemPalette();
obj.img->useMaskColor = true;
obj.img->drawText(0, 0, obj.txt, obj.color);
drawList.insert(std::make_pair<std::string, textObj >(buffer, obj));
buffer = strtok(NULL, ",");
}
}

std::string formatText(std::string s)
{
int size = 2;
while(size < s.size() && s!=']')size++;
size -= 2;
switch (s)
{
case 'x':
{
TextMap::iterator itr = drawList.find(s.substr(2, size));
if(itr != drawList.end())
return itr->second.txt;
return s;
}
case 'n':
{
int n = atoi(parseText(s.substr(2, size)).c_str());
return RPG::actors->getName();
}
case 'N':
{
int n = atoi(parseText(s.substr(2, size)).c_str());
return RPG::actors->getDegree();
}
case 'v':
{
int n = atoi(parseText(s.substr(2, size)).c_str());
std::stringstream ss;
ss << RPG::variables;
return ss.str();
}
case 'i':
{
int n = atoi(parseText(s.substr(2, size)).c_str());
return RPG::getItemName(n);
}
case 'I':
{
int n = atoi(parseText(s.substr(2, size)).c_str());
return RPG::getItemDescription(n);
}
case 't':
{
int n = atoi(parseText(s.substr(2, size)).c_str());
return RPG::getSkillName(n);
}
case 'T':
{
int n = atoi(parseText(s.substr(2, size)).c_str());
return RPG::getSkillDescription(n);
}
case 'a':
{
int n = atoi(parseText(s.substr(2, size)).c_str());
return RPG::getConditionName(n);
}
default:
return s;
}
}

std::string parseText(std::string in)
{
std::string out;
for(unsigned int i = 0; i < in.size(); i++)
{
if(in == '\\')
{
out += formatText(in.substr(i + 1, in.size()));
while(i < in.size() && in!=']')i++;
while(i + 1 < in.size() && in==']')i++;
}
else
out += in;
}
return out;
}

bool onComment( const char* text,
const RPG::ParsedCommentData* parsedData,
RPG::EventScriptLine* nextScriptLine,
RPG::EventScriptData* scriptData,
int eventId,
int pageId,
int lineId,
int* nextLineId )
{
std::string s = parsedData->command;

if(!s.compare("write_text"))
{
TextMap::iterator itr = drawList.find(parsedData->parameters.text);
if(itr == drawList.end())
{
textObj obj;
obj.x = parsedData->parameters.number;
obj.y = parsedData->parameters.number;
obj.color = (parsedData->parameters.type == RPG::PARAM_NUMBER && parsedData->parametersCount >= 6)?parsedData->parameters.number:0;
if(parsedData->parameters.type == RPG::PARAM_STRING)
{
std::string tmp = parsedData->parameters.text;
obj.fixed = (!tmp.compare("fixed"))?true:false;
}
else
obj.fixed = false;
if(parsedData->parameters.type == RPG::PARAM_NUMBER)
{
std::stringstream ss;
ss << parsedData->parameters.number;
obj.txt = ss.str();
}
else
obj.txt = parseText(parsedData->parameters.text);
obj.img = RPG::Image::create(obj.txt.size()*6 + 8, 16);
obj.img->setSystemPalette();
obj.img->useMaskColor = true;
obj.img->drawText(0, 0, obj.txt, obj.color);
drawList.insert(std::make_pair<std::string, textObj >(parseText(parsedData->parameters.text), obj));
}
return false;
}

if(!s.compare("append_line"))
{
TextMap::iterator itr = drawList.find(parseText(parsedData->parameters.text));
if(itr != drawList.end())
{
if(parsedData->parameters.type == RPG::PARAM_NUMBER)
{
std::stringstream ss;
ss << parsedData->parameters.number;
itr->second.txt = ss.str();
}
else
itr->second.txt = parseText(parsedData->parameters.text);
int width = itr->second.txt.size();
if(width < itr->second.img->width)width = itr->second.img->width;
RPG::Image* tmp = RPG::Image::create(width*6 + 8, 16 + itr->second.img->height);
tmp->drawText(0, itr->second.img->height, itr->second.txt, itr->second.color);
tmp->draw(0, 0, itr->second.img);
itr->second.img->init(width*6 + 8, 16 + itr->second.img->height);
memcpy(itr->second.img->pixels, tmp->pixels, tmp->width * tmp->height);
RPG::Image::destroy(tmp);
}
return false;
}

if(!s.compare("append_text"))
{
TextMap::iterator itr = drawList.find(parseText(parsedData->parameters.text));
if(itr != drawList.end())
{
if(parsedData->parameters.type == RPG::PARAM_NUMBER)
{
std::stringstream ss;
ss << parsedData->parameters.number;
itr->second.txt += ss.str();
}
else
itr->second.txt += parseText(parsedData->parameters.text);
itr->second.img->free();
itr->second.img->init(itr->second.txt.size()*6 + 8, 16);
itr->second.img->drawText(0, 0, itr->second.txt, itr->second.color);
}
return false;
}

if(!s.compare("change_text"))
{
TextMap::iterator itr = drawList.find(parseText(parsedData->parameters.text));
if(itr != drawList.end())
{
if(parsedData->parameters.type == RPG::PARAM_NUMBER)
{
std::stringstream ss;
ss << parsedData->parameters.number;
itr->second.txt = ss.str();
}
else
itr->second.txt = parseText(parsedData->parameters.text);
itr->second.color = (parsedData->parameters.type == RPG::PARAM_NUMBER)?parsedData->parameters.number:0;
itr->second.img->free();
itr->second.img->init(itr->second.txt.size()*6 + 8, 16);
itr->second.img->drawText(0, 0, itr->second.txt, itr->second.color);
}
return false;
}

if(!s.compare("change_position"))
{
TextMap::iterator itr = drawList.find(parseText(parsedData->parameters.text));
if(itr != drawList.end())
{
itr->second.x = parsedData->parameters.number;
itr->second.y = parsedData->parameters.number;
}
return false;
}

if(!s.compare("remove_text"))
{
TextMap::iterator itr = drawList.find(parseText(parsedData->parameters.text));
if(itr != drawList.end())
{
RPG::Image::destroy(itr->second.img);
drawList.erase(itr);
}
return false;
}

if(!s.compare("remove_all"))
{
TextMap::iterator itr = drawList.begin();
while(itr != drawList.end())
{
TextMap::iterator tmp = itr++;
RPG::Image::destroy(tmp->second.img);
drawList.erase(tmp);
}
return false;
}

if(!s.compare("debug"))
{
TextMap::iterator itr = drawList.begin();
while(itr != drawList.end())
{
MessageBox(NULL, itr->first.c_str(), "textPlugin", MB_ICONINFORMATION);
itr++;
}
return false;
}

return true;
}


Wow, that is a lot more code then I thought it would be. From what I have interpreted though, he is using the image::drawText()(the old text function) when a picture is drawn to create an image ontop of it (or replaces it?) and then using the canvas::draw() function to draw the text onscreen and canvas::drawStretch() function to make the image big enough for the text to fit on the image. He doesn't actually use the image:::loadFromFile() function though, which will allow for loading up pictures in a plugin directly.

With that said, I should at least be able to create a text image even if I can't use the image::loadFromFile function, but when I try to do so, it results in nothing happening. I am however able to do so in battle, which leads me to believe either the image::drawString function doesn't allow its function in the overworld and the image::drawText function does or there is something I am missing.

This is the code I am using to draw text:
std::string pathName = "Picture\\Field.png";
RPG::Image* myImagePtr = RPG::Image::create(320, 240);
myImagePtr->useMaskColor = true;
myImagePtr->loadFromFile(pathName, true, false); //Even if I omit this, the image loads blank outside of battle, only.
myImagePtr->drawString(0, 0, pathName, 8);
myImagePtr->setSystemPalette();
RPG::screen->canvas->draw(132, 108, myImagePtr);

So is there something wrong with my code? I trigger it through a comment command for both battle and outside battle, but it only works in battle, or rather only visible in battle. I ran a debugger to check if the code is being executed outside battle and it seemingly is, so I am stumped.

EDIT So I figured out what was wrong, kinda. When I create an image in a function that only runs once, for example the onComment() function. My RPG::Image object is destroyed after the function finishes executing the code which results in nothing happening. I had to use the onFrame() function to ensure it would persists in every scene. Unfortunately, now I have run into another issue and that is my images are being immediately destroyed after being made and I am not sure why. I at least see my image for a frame before it is destroyed though, unlike before where nothing would happen. The only solution I found is to have it draw to the canvas every frame which makes me think the game automatically destroys all images every frame and redraws them, excluding the new images.
Does anyone know which parameter I need to change for this not to crash?

bool onDrawBattleActionWindow(paramters...)
if(RPG::battleData->navLevel = RPG::BNAV_IN_PARTY_WINDOW
&& RPG::Actor::partyMember(CurBattler)->atbValue = 300001)
{
RPG::battleData->navLevel = RPG::BNAV_IN_COMMAND_WINDOW;
}

This should open the command window for the actor whose atb bar is full, instead of having to select the the battler and press the decision key to open the battler's command menu. This results in a read error when I run it during battle though.

I am assuming it's because I haven't set the battler whom the winCommand window should open for. The only variable that looks like what I need is the RPG::battleData::currentHero, but I can't do anything with it.
The equals signs in the if statement should be ==, not =. == checks WHETHER something is equal, = ASSIGNS one thing to be equal to another.
author=AubreyTheBard
The equals signs in the if statement should be ==, not =. == checks WHETHER something is equal, = ASSIGNS one thing to be equal to another.
That's a typo on here, it is "==" in my code. I've tried experimenting with it more and still can't identify the issue, but I am pretty sure I need to change a variable somwewhere before executing that line of code.

So I started using the Window class and I am able to manipulate existing windows, but I am still unable to create new ones without a run time error. When I create an object of the Window class the plugin fails to load giving me the "cannot load plugin (DYnRPG 1114)" error and continues to run the game without loading it. It seems if I initialize any Window objects in my plugin the game will always fail to load the plugin, no matter where I initialize them. And if I use uninitialized Window objects the game will get a memory read error, for obvious reasons. I'll continue to experiment with them, but it might just be easier to create my own Window class inheriting the Image class objects. I also tried mapping my Window objects, but that results in a memory write error.

Also do you or anyone else know why this line of code won't compile, "RPG::WindowMenuSkill->winInfo->y = 120;"? I looked into the header and this line should point to class WindowMenuSkill, object winInfo, member int "y", but it results in the compiling error "expected unqualified-id before -> token, after RPG::WindowMenuSkill. I checked the header to see if there is a reinterpreter for that class, but there isn't and if there was I would have gotten the error WindowMenuSkill is not a class or namespace. I also checked to make sure winInfo is a static object.
author=McBick
So I figured out what was wrong, kinda. When I create an image in a function that only runs once, for example the onComment() function. My RPG::Image object is destroyed after the function finishes executing the code which results in nothing happening. I had to use the onFrame() function to ensure it would persists in every scene. Unfortunately, now I have run into another issue and that is my images are being immediately destroyed after being made and I am not sure why. I at least see my image for a frame before it is destroyed though, unlike before where nothing would happen. The only solution I found is to have it draw to the canvas every frame which makes me think the game automatically destroys all images every frame and redraws them, excluding the new images.


A quick lesson in C++ (slightly simplified)
There are two types of memory which are relevant during runtime of a program called "stack" and "heap". When you define a variable inside a function, like an integer, this is put on the "stack" memory, and is only valid within it's scope, usually defined by the curly brackets. You can define an integer within an if bracket, in which case that integer will not be usable once the code execution is outside the if block (as denoted by the curly brackets).
The nice thing about the stack is that it cleans itself and does not cause problems.

The heap memory is for variables which are generally supposed to persist outside of the scope of functions. You normally allocate the memory for these variables with the "new" operator in C++, or calling a function which uses this (or C equivalent like malloc()). Usually, the variable you use to associate with this memory block allocated, is by a pointer. And it is important to keep track of the address stored in this pointer, since stuff which is put on the heap does not go away unless you specifically remove it (usually with the "delete" operator in C++).

Now, to take it back to your issue, what you're doing might a whole lot worse than you're imagining.
Whenever you call
RPG::Image* myImagePtr = RPG::Image::create(320, 240);

You're allocating an image of 320x240 pixels on the heap, and you store the address to that data in the pointer "myImagePtr". Problem is, that this pointer is put on the stack, and when you leave the function, it goes out of scope and it loses the address of that data, which now can never be deleted (until the termination of the program). This is known as a memory leak, and if you're calling this functionality at every frame without freeing that image, you probably have a massive leak going on. (You might want to open the task manager and look at the memory consumption of your game application during runtime. If it keeps increasing, that's a pretty bad sign).
In other words the game does not destroy the images at every frame, you're just losing track of them (also, the game is re-drawing everything every frame, so trying to call canvas draw with the onComment callback will not do much as it will "maybe" draw it for the single frame where the comment is triggered and will be lost immediately afterwards)

What you need to do, is to make a global variable of some sort. You could create one instance of that 320x240 image, and just draw text on that directly, but it makes it tricky to remove text afterwards, so you'll probably have to "clean" the image every time you want to remove something. You need make the drawing of the image happens in a callback which is drawn at every frame you want it to be visible, and here the order can be important.
@Kazesui
So I actually considered that, but I thought the game was deleting them. I use a global variable for my image objects, but when I create an object via a function, for example onComment, my image is destroyed after that function is executed, so I don't even see it being created. I haven't noticed any high memory usage at all, but I will check for them. I thought it was frowned on to use the new operator as the compiler is supposed to allocate memory for you? This is basically how I have created images before and currently.

Before
//Plugin Name
#include <DynRPG/DynRPG.h>
#include <CBS.h>
#include <vector>
#include <iostream>
#include <string>
#include <iterator>
std::map<int, RPG::Image*> myImages;

bool onComment(parameters...)
{
static std::string cmd;
cmd = parsedData->command;
if(0 == cmd.compare("cbs_image"))
{
std::string pathName = "Picture\\Monster1.png";
myImages(0) = RPG::Image::create();
myImages(0)->loadFromFile(pathName);
myImages(0)->useMaskColor = true;
RPG::screen->canvas->draw(132, 108, myImages(0));
return false;
}
return true;
}

Current
//Plugin Name
#include <DynRPG/DynRPG.h>
#include <CBS.h>
#include <vector>
#include <iostream>
#include <string>
#include <iterator>
std::map<int, RPG::Image*> myImages;
static bool getImage;

onFrame(parameters...)
{
if(getImages)
{
std::string pathName = "Picture\\Monster1.png";
//Should I add a destroy function here to stop the memory leak?
//Should I add an If(myImages(0)) for the following three lines of code?
myImages(0) = RPG::Image::create();
myImages(0)->loadFromFile(pathName);
myImages(0)->useMaskColor = true;
RPG::screen->canvas->draw(132, 108, myImages(0));
}
}


This is just made for testing purposes right now. I thought in c++ objects created are destroyed after the function is terminated, unless you return an object? From what I am to understand I am generating an infinite amount of Image objects? How can that be though, if I am creating the same object? And how is it that my image is constantly being destroyed over and over? From what I can tell the game is destroying it every frame which is why I have it draw every frame, otherwise if I only initiate it once through the onFrame function then my image literally shows for one frame, I've tracked it to be sure.

I'm actually studying up more about c++ memory allocation now since it seems to be a major issue I have run into for creating my turn based battle plugin. I'm currently trying to utilize the Window class, with minor success because of memory write issues. Also can't get the battle navigation to not crash with a DynRPG 1114 error. So the info about stacks and heap is quite helpful. I'll try to look online for more info because I think you're right that my code is leaking memory. The problem is I don't know at what point to destroy my images, as I am not sure why they keep disappearing in game.

EDIT So I added an if statement to check if there was an image object before creating it and it solved my memory issue, so thanks for pointing it out.
The "new" operator is an essential part of the language and is not really something frowned upon. If you've read the DynRPG manual, you might have gotten this idea since it explicitly tells you not to use new with any of it's classes, which is very correct but for different reasons. Don't try to use "new" on any of the DynRPG classes, you'll probably break things.

That said, I imagine you can get away without using this operator, since it's often implicitly called for you. RPG::Image::create() somewhere along the lines of function calls does put this memory on the heap, while returning a pointer to this memory. std::map also allocated part of it's memory dynamically, most likely with the new operator. It's just that it does it all for you so you do not have to think about it. The compiler is not the one which do these. This is in fact a weakness of stuff put on the stack, as it needs to know exactly how much memory needs to be allocated for these objects beforehand and does not allow for dynamic scaling (i.e . it expects all sizes to be known at the time the code is compiled).

In the way your current code is setup, you wouldn't lose the address in the pointer when you go out of scope thanks to the global std:map, but you would lose it the second you call RPG::Image::create() again, since it now allocated new space and gives you a new pointer to the address of the newly allocated memory.

It's also important to know that just because an image is not visible on the screen when you call draw does not necessarily mean it has been destroyed. For every single frame displayed by the game everything is redrawn. Normally, what happens is that everything is drawn onto the canvas by a predetermined order. Anything drawn later will be drawn on top of what was already drawn (i.e. graphics from events set as "above hero" will be drawn after anything related to the tileset, and any picture will be drawn on top of everything else (except a picture with a higher ID). First when everything has been drawn on to the canvas, the canvas will be displayed to the player.
I'm not sure exactly when the event script commands are triggered (which is what would trigger onComment), but it's quite possible that this happens before the rest of the stuff is drawn to the canvas, meaning that when you draw an image to canvas in the onComment callback, you are indeed drawing it to the canvas, but everything is drawn on top of that afterwards, and you end up not seeing it. Nothing has been destroyed, you're just not seeing the results for other reasons.

So, even if you put the comment in a parallel process (which you would need to since otherwise you'd only be drawing the image for the single frame you executed the comment), there's still no guarantee that you will see it.

onFrame does a better job here, since I believe this is called after RPG Maker is done drawing everything it wants to draw, which is done for every frame. onFrame or onDrawScreen are proabably your best bets here. You could also use onBattlerDrawn, but you'd probably want to include an if statement there to make sure you're only executing the code after the last Battler has been drawn.

The answers to this is kind of contained in the wall of text up there, but just to directly address the various questions
author=McBick
I thought in c++ objects created are destroyed after the function is terminated, unless you return an object?

Only stuff which is put on the stack. RPG::Image::create allocated memory on the heap and returns a pointer to it which is not destroyed after the function is terminated.

author=McBick
From what I am to understand I am generating an infinite amount of Image objects?

Still looks like it. Try calling
myImages[0]->init(width, height)
instead after having called RPG::Image::create one time instead, as this will clear the image without creating a new one. Only works after you have created an Image though.

author=McBick
How can that be though, if I am creating the same object?

You might use the same variable name, but the code don't consider that to be the same object. You might have saved the address of that memory block in some other variable somewhere else in the code and want to reuse that variable name for a new pointer, which is what's happening it the code you outlined.

author=McBick
And how is it that my image is constantly being destroyed over and over?

Is it actually being destroyed or just not drawn? Not necessarily the same thing. You need to draw an image every frame, because if you don't the next frame is drawn on top of the old image and you won't see it anymore. This is why the text plugin also uses the onDrawPicture callback, since this something which is drawn for every frame (if the picture exists), but still allows for some graphics chosen by the developer to be put on top of the text (which is why I did not go for onFrame or onScreen myself).

What I would recommend, is to create all the images necessary in onComment callback at the start of a battle, and then to draw the images created in onFrame (without the use of RPG::Image::create in this callback). You use Destroy when the image is not used anymore or when the battle is over at which point you'll have to stop drawing as well (onFrame will keep drawing whatever it's told to draw whether you're in a battle or not, so you'll need a way to discern when you're in battle).

also, tiny tip. Use the code tags when posting code. This allows you to use square brackets, and the formatting is a bit easier to read.
So if I am to understand correctly using the map operator is in fact allocating the proper memory for me? I just want to make sure. I have changed my code to this for images.
//Plugin
void onFrame(RPG::Scene scene)
{
    if(scene == RPG::SCENE_MAP) //I change this to different scenes for testing purposes, but will change it to a pointer.
    {
        if(getImage) //This is a global bool
        {
            CBS::createImage(0, 120, 120, 16, 24);
        }
    }
}
//header
std::map<int, RPG::Image*> myImage;
std::map<int, RPG::Image*> myText;
void createImage(int img, int x, int y, int stringX, int stringY)
    {
        std::string pathName = "Picture\\Field.png"; //I will probably change this to a global string or parameter later.
        if(!myImage[img])
        {
            myImage[img] = RPG::Image::create();
            myImage[img]->loadFromFile(pathName);
            myImage[img]->useMaskColor = true;
            myText[img+1] = RPG::Image::create(myImage[img]->width, myImage[img]->height);
            myText[img+1]->useMaskColor = true;
            myText[img+1]->drawString(stringX, stringY, pathName, 8);
            myText[img+1]->setSystemPalette();
        }
        RPG::screen->canvas->draw(x, y, myImage[img]);
        RPG::screen->canvas->draw(x, y, myText[img+1]);
    }
I didn't know there was a code tag, thanks for pointing it out. So is this code good now? Right now this is just for testing purposes, so I will probably redesign it, but is the process of how I am handling classes and objects okay now? Also I am unsure exactly how the map operator works. How big of an array could I use with it and how does the compiler know how big of an array to allocate memory for if I am creating new objects during run time?

If I create new RPG::class objects will I have to destroy them with the onExit function or will they terminate themselves? I have run into an issue before where closing the game did not end the program on my system and I had to manually end it via task manager, but that could have been bad code as I was experimenting at the time on how image functions work and wrote it differently then.

author=Kazesui
You might use the same variable name, but the code don't consider that to be the same object. You might have saved the address of that memory block in some other variable somewhere else in the code and want to reuse that variable name for a new pointer, which is what's happening it the code you outlined.
How can that be? I thought variables are an address in memory, so if I use the same variable it is using the same memory? Otherwise how would you manipulate memory? How can I ensure I am using the same memory then?

author=Kazesui
Is it actually being destroyed or just not drawn? Not necessarily the same thing. You need to draw an image every frame, because if you don't the next frame is drawn on top of the old image and you won't see it anymore. This is why the text plugin also uses the onDrawPicture callback, since this something which is drawn for every frame (if the picture exists), but still allows for some graphics chosen by the developer to be put on top of the text (which is why I did not go for onFrame or onScreen myself).

What I would recommend, is to create all the images necessary in onComment callback at the start of a battle, and then to draw the images created in onFrame (without the use of RPG::Image::create in this callback). You use Destroy when the image is not used anymore or when the battle is over at which point you'll have to stop drawing as well (onFrame will keep drawing whatever it's told to draw whether you're in a battle or not, so you'll need a way to discern when you're in battle).
This is very useful info thanks. I was going to experiment with different functions to figure out the order in which it draws to canvas. This will save me time and frustration. I am currently using this for onComment function, so I can manipulate images in different RPG::scenes.
bool onComment(const char* text,
               const RPG::ParsedCommentData* 	parsedData,
               RPG::EventScriptLine* 	nextScriptLine,
               RPG::EventScriptData* 	scriptData,
               int 	eventId,
               int 	pageId,
               int 	lineId,
               int* 	nextLineId)
{
    static std::string cmd;
    std::string textString;

    cmd = parsedData->command;

    //Call Image through comment.
    if(0 == cmd.compare("cbs_image"))
    {
        getImage = !getImage;
        return false;
    }
    return true;
}

By any chance do you know how the Window class/functions operate? I keep running into a memory read error. Also any idea why this line of code "RPG::battleData->navLevel = RPG::BNAV_IN_COMMAND_WINDOW;" results in an access violation model type read error? I execute it when the hero battler is selected in the winParty window, their atb bar is full, and when "RPG::battleData->navLevel == RPG::BNAV_IN_PARTY_WINDOW" is true. I am trying to open the winCommand window without having to select a battler and press the decision key.

std::map<int, RPG::Window> myWindow;
void createWindow()
    {
        myWindow[0].create(64, 64, 120, 96, false);
    }
This function results in a memory read error, "A violation in C08BC35D occured at C08BC35D with Read".
First of all, thank you for using the code tags. It makes it so much easier to read the code.

author=McBick
So if I am to understand correctly using the map operator is in fact allocating the proper memory for me? I just want to make sure. I have changed my code to this for images.


std::map is not an operator, but rather a "data structure", which is an umbrella term for objects focused on storing data. In particular, map is a binary tree, to quickly find the value associated with a given key. In your case, the integers are the key and the pointers are the value.
std::map dynamically allocate the necessary memory as needed, so your RAM is pretty much what defines the limit. In other words, nothing you need worry about. As long as you keep it global it should be fine as is.

If you don't need direct access to the various pointers, there are also other alternatives you could use, like std::list or std::vector.
std::vector resembles a normal array which you can call with the square bracket operator, but dynamically increases it's size as needed (assuming you use the right methods).
If you're looking at learning a little bit of C++, having a quick look at all three of these could be a good start as they are very common, and generally useful. If you simply want to draw all pictures you've made, it could be easier to just put them all in a std::vector and then iterate over all the elements in the array.

For all of these, you do not need to worry about the memory of the data structures themselves... but if they contain pointers to dynamically allocated memory, (like the RPG::Images), you still need to care for those yourself.

author=McBick
How can that be? I thought variables are an address in memory, so if I use the same variable it is using the same memory? Otherwise how would you manipulate memory? How can I ensure I am using the same memory then?


This was specifically related to the code you put before you added the if test for your image. With this if statement, this should work a lot better
That said, I want to highlight something about that if statement of yours as well, i.e. the
if(!myImage[img])

What it does, is not not to check if there is an image in std::map myImage, but rather if there is a key with the same value as "img" in myImage. The reason this is relevant is because it doesn't say anything about whether the RPG::Image* has been allocated or not. This should not be a problem right now, but something to keep in mind when you start removing images because you're transitioning from battle to non battle and back. The best thing to do is probably to make sure to completely empty myImage inbetween these, while remembering to destroying each instance of RPG::Image first.

author=McBick
If I create new RPG::class objects will I have to destroy them with the onExit function or will they terminate themselves?


I'm assuming you're referring to RPG::Image and RPG:Window, because as mentioned, in general you should not make new RPG::class objects outside a few exceptions. As for terminating themselves, effectively, they should. Once a program terminates, it will generally free up the heap and stack memory it was using, but that's more of an implicit cleanup rather than a real one, but you should be fine even if you don't use onExit to clean stuff.
You might want to consider doing some cleanup still for whenever there are scene changes still though.

author=McBick
By any chance do you know how the Window class/functions operate?

This was added with the updated DynRPG version, which I never got around to use. Also, I never really dealt much with stuff related to the battle scene, as I personally wasn't very interested in it.
What I can say though is that to try and assign values to most of the RPG classes will usually lead to bad things in my experience. Exactly why, is hard to say as I would like to see the source code of RPG Maker for that, but for the navLevel thing, it could be because it expects the state to be RPG::BNAV_IN_PARTY_WINDOW, and from the perspective of RPG Maker, the only way to transition from this window to another, is to do a certain action (involving selecting a certain option), and the rest of the code operates on the assumption that this holds true. When the state is suddenly changed without going through the normal process of changing the state, the variables of this new state might not have been initialized properly and thus leads to what is referred to as a segfault in c++ lingo, i.e. trying to access something you should not have access to because you either messed up the indexing or you didn't assign / allocate / create it yet.

I guess there are some parameters which you can change the value of (like the ATB gauge from the sound of it), but this should be not be the expectation when it comes to the various members of the various classes.

author=McBick
std::map<int, RPG::Window> myWindow;
void createWindow()
    {
        myWindow[0].create(64, 64, 120, 96, false);
    }

This function results in a memory read error, "A violation in C08BC35D occured at C08BC35D with Read".


You made a mistake in there. When you write
myWindow[0].create(64, 64, 120, 96, false);
it assumes you've already instantiated an object of the Window class with 0 as a key

std::map<int, RPG::Window> myWindow;
void createWindow()
{
    myWindow[0] = RPG::Window()
    myWindow[0].create(64, 64, 120, 96, false)
}


I can't guarantee that the code above will work, as I don't have a good way of testing it, and as mentioned, I've never worked with the RPG::Window class, but this would probably be how you should be doing it. It assumes you're allowed to instantiate it like this rather than like a pointer, which generally wasn't allowed with any classes I used in DynRPG (Not saying it isn't correct, just pointing out a potential cause in case it doesn't work).
author=Kazesui
If you don't need direct access to the various pointers, there are also other alternatives you could use, like std::list or std::vector.
std::vector resembles a normal array which you can call with the square bracket operator, but dynamically increases it's size as needed (assuming you use the right methods).
If you're looking at learning a little bit of C++, having a quick look at all three of these could be a good start as they are very common, and generally useful. If you simply want to draw all pictures you've made, it could be easier to just put them all in a std::vector and then iterate over all the elements in the array.
This is immensely useful to know, thanks. This gives me a better understand of these data structures and will make coding in the future more efficient. I'll continue to learn more about these 3 structures and better utilize them.

author=Kazesui
std::map<int, RPG::Window> myWindow;
void createWindow()
{
myWindow = RPG::Window()
myWindow.create(64, 64, 120, 96, false)
}
I tried this too, but it gives the same error. I think the issue is the destructor in the class, but I am not familiar with how destructors work, so I could be wrong. I may just be better off creating my own window function as nothing I have tried works, not to mention I would have more customization options if I make my own.

I experimented with the RPG::battleData::navLevel and I have discovered some things. If I set it to 0 first, I will then be allowed to change it to whatever value I want, but this ends up doing nothing if I set it to RPG::BNAV_IN_COMMAND_WINDOW, so useless. Also this is the exact error I receive, "Access violation in module "RPG_RT.exe" in with address 004BFF9E and offset 00000034 of type Read occured". If I understand correctly the address is to RPG::battleData and the offset is RPG::battleData->navLevel, but I'm not sure why it is a Read type violation.

Is there a way to force input? I could do that instead, but I don't see a way to force input in DynRPG.
author=McBick
I tried this too, but it gives the same error. I think the issue is the destructor in the class, but I am not familiar with how destructors work, so I could be wrong. I may just be better off creating my own window function as nothing I have tried works, not to mention I would have more customization options if I make my own.

I experimented with the RPG::battleData::navLevel and I have discovered some things. If I set it to 0 first, I will then be allowed to change it to whatever value I want, but this ends up doing nothing if I set it to RPG::BNAV_IN_COMMAND_WINDOW, so useless. Also this is the exact error I receive, "Access violation in module "RPG_RT.exe" in with address 004BFF9E and offset 00000034 of type Read occured". If I understand correctly the address is to RPG::battleData and the offset is RPG::battleData->navLevel, but I'm not sure why it is a Read type violation.

Is there a way to force input? I could do that instead, but I don't see a way to force input in DynRPG.


As mentioned, it could be because it the only way RPG Maker expects to be able to transition from one state to another involves processing key inputs. It's quite possible that they allocate a pointer of some sort internally in case the player acts upon a nav position, which is not always valid. Again, I believe it's safe to assume this particular member variable does not expect to be messed with. And no, the address of BattleData should be 0x4CDD38 not 0x4BFF9E (note, prefixing numbers with 0x implies that the number following it is given in hexadecimals), at least based on the headerfile. Either way, it boils down to it trying to access something it shouldn't, for reasons which will be hard to determine without the source code.

There are ways to simulate key presses with C++ code, but it's very hacky and I would not really recommend this as a solution. Apart from that I'm also not sure how to force the change.
author=Kazesui
There are ways to simulate key presses with C++ code, but it's very hacky and I would not really recommend this as a solution. Apart from that I'm also not sure how to force the change.
I looked into it and you're not kidding. I will try experimenting more with navLevel a bit more and if I can't figure it out then I will just do away with all of the windows and battle data and create my own system from scratch using custom windows or possibley just altering the existing windows if I can figure out why every time I change the window's image size it just becomes a scrambled mess of pixels.

Also thanks for all the input with both DynRPG and C++, it was very helpful.

Does anyone know why this occurs to my window?

I adjusted the window's width and it seems to not redraw the frame correctly now.

void getWindowPos()
{
if(RPG::battleData->winCommand->width != 96)
{
RPG::battleData->winCommand->width = 96;
RPG::battleData->winCommand->image->width = 96;
RPG::battleData->winCommand->redraw();
}
Also does anyone know what the Window::refresh() function is supposed to do?

EDIT: I figured out why the window becomes a scrambled mess of pixels when changing the size. It is necessary to use the RPG::Image::init() function instead of changing the image's width of the window. I have only been successful doing this with the imageText though. For some reason when changing the frame size, the game continues to redraw the same sized window despite using the init() function to alter it's width and height. It is also necessary to use the Window::refresh() function any time you alter the window's dimensions, so the game can readjust it's internal pointers for navigating windows and redrawing them correctly.
@Kazesui
Could you explain the differences of std::map and vector? From what I understand they can both be used for the same thing? So when would I use one over the other?

For instance what is the difference or limitation between these two types of arrays, if any?
std::map<int, RPG::Image*> images
//and
std::vector<RPG::Image*> images

Also what is the difference between these arrays?
const char* myText[3] = {A, B, C};
//and
static std::string myText[3] = {A, B, C};
author=McBick
@Kazesui
Could you explain the differences of std::map and vector? From what I understand they can both be used for the same thing? So when would I use one over the other?

For instance what is the difference or limitation between these two types of arrays, if any?
std::map<int, RPG::Image*> images
//and
std::vector<RPG::Image*> images


Also what is the difference between these arrays?
const char* myText[3] = {A, B, C};
//and
static std::string myText[3] = {A, B, C};


Both std::map and std::vector store data, so they can be used for the same thing in terms of accessing and using the data. Where there's a relevant difference in terms of how the access is done and how you add and remove data.

std::vector is in essence a simple array. You generally add elements with the "push" method, and access them with square brackets and the integer index. Note that these integers here will always be contiguous since the memory is listed from 0 to n, with n being the size of the array (n is excluded from the loop since the last element will be at position n - 1).

removing single elements from std::vector is considered slow, and should be avoided unless it is at the end of the array... but this will likely not matter too much within the context of usage for DynRPG. I would be very surprised if you managed to run into performance issue because of this.

std::map is a binary tree which store two values, the "key" and the "value", and is sorted on the former. Important difference here is that you do not need to use integers as key values, and they do not need to be contiguous. e.g. you could have an RPG::Image* associated with the keys 1, 3, 42, and that would be perfectly fine. You could also use "battler1", "battler2", "hero1" as keys, and it would give you an easier time manipulating specific pictures as you don't have to remember the integer index assigned to them. If you don't need to manipulate individual images much, this is not really needed.

There are some performance considerations here, where std::vector will likely outperform std::map if you don't manipulate the images and you just want to show all them in a specific order (with the order being easier to enforce in an std::vector), but ultimately, you can use what you're comfortable with as non of these performance issues are likely going to impact you in a meaningful way at this stage. The code will be simpler for std::vector if it provides all the functionality you need, and that would be my incentive to use it.

As an example, for the text plugin however, I also used std::map, because I think it's easier for the user to give specific names to their images and allow them to manipulate each individually. This is of course different if the plugin is for private use, or supposed to contain a full system using images rather than giving users control of the individual images.

as for the differences of your strings.
Using char* for strings is the C way of doing things, while std::string is the C++ way of doing things.
char* is just a pointer to an array of 8bit values used to represent characters (or letters and symbols if you'd like), which under normal circumstances should be terminated with "\0" to signify the end of the string.

std::string is a class which holds a similar array, but also provides some more functionality out of the box by holding methods which can operate on the string directly.

For a lot of intents and purposes, they are quite similar in terms of behavior as strings, and the biggest difference is in terms of how you manipulate them, which generally require C libraries for char* strings, and C++ libraries for std::string.

const and static are more generic and don't deal with text variables specifically but operate on mutability and scope. const implies that you're not allowed to change the following variable, though special care must be taken when using pointers as where you place the const relates to whether it's the address stored in the pointer you're not allowed to change, or the contents at the end of that address. There's a lot of nuance here, so further reading is probably best to properly understand it.

static is used in a couple of ways in C++.
You can use static in a class member to make sure that all objects created of that class will share the value of this member variable, or a method might be belonging to the class itself rather than objects instantiated with it (like RPG::Image::create() which does not belong to a single RPG::Image object, unlike with RPG::Window::create() which does belong to the object, at least as defined in the documentation).

It can also be used within a function to add persistence to that variable without being declared initially in global scope.

int foo()
{
    static int counter = 0;
    counter = counter + 1;
    return counter
}

the "counter" variable in this case would always return 1 if not for the static keyword. The static keyword makes this variable instantiated the first time the function is called, and reused whenever this function is called again, meaning the second time you would call this function, it would return "2". This does not mean that you can use this variable as you'd like outside of this function however. In other words, statics make the variable not be "destroyed" upon leaving a function, but is not quite the same as making the variable global.
So basically for manipulating Rm2k3 objects I should, and need to, use std map, but for integer arrays I should use vectors? I thought vectors could store other values such as with std::vector<Rpg::Image> myImage, but I guess not.

When I get a compiling error with strings it always refers to them as chars or const chars despite only using static std string and std string variables, so I thought that maybe they were the same.

For global variables I must use static or const outside the main() and all functions correct? That is what I have been doing anyways. I've also used static variables inside functions, so it only initiates the value once and can be changed within the function later if need be.

For arrays why does something like int N = RPG::monsters.size(), not work? I am trying to find a way to easily keep track of the size of certain rm2k3 arrays without using a loop every time I need their array size. As it is now I have created a function just to count array sizes as I am tired of constantly using loops every time I need the array size.
author=McBick
So basically for manipulating Rm2k3 objects I should, and need to, use std map, but for integer arrays I should use vectors? I thought vectors could store other values such as with std::vector<Rpg::Image> myImage, but I guess not.

both std::map and std::vector can store any type of object (as defined by what you put in the <>). Accessing the entries of a std::vector is only done with integers, while with std::map you can access them with almost anything.

std::map<std::string, std::string> example;
example["foo"] = "bar";

This is possible with std::map but not with std::vector. With std::vector it's easy to do this however

std::vector<RPG::Image*> images;

...

for(int i = 0; i < images.size(); i++)
{
    RPG::screen->canvas->draw(x[i], y[i], images[i]);
}

This is not something which is guaranteed to work if you're using std::map, and if you use it this way, it might work, but it will look a bit weird (but the concept ought to still work).


author=McBick
When I get a compiling error with strings it always refers to them as chars or const chars despite only using static std string and std string variables, so I thought that maybe they were the same.

std::string most likely stored the actual string as a char* so that could be a possible reason for it. I have to admit, I haven't been actively coding in C++ for a rather long time now, so I don't remember what compile errors ought to look like when it comes to std::string any longer. As mentioned, they are similar, but not exactly the same. A simple char* is a bit more bare-bones than std::string.

author=McBick
For global variables I must use static or const outside the main() and all functions correct? That is what I have been doing anyways. I've also used static variables inside functions, so it only initiates the value once and can be changed within the function later if need be.

Nope, there is no need to declare global variables as static. The reason to do so would be to make sure that the global variable is only global to the file in which it is defined only, which is only of concern if you're actually compiling more than one file, or are building a code base which is meant for others to expand upon (with more files). If this is not the case, there is no need to declare any of these variables as static. At least that's what I read. I've never used static in this way myself. File also likely means .cpp file here, not .h file, as these are kind of added to the .cpp file at compile time.
Bottom line is still the same though, you probably won't need them for global variables.

It's also not necessary to declare anything as const, unless you want it to be unchangeable. There are very good reasons for using const, but I don't believe it is something you need to worry about at this point. The biggest thing you need to know is that there will be variables which are given as const which will throw a compile error if you try to alter their values, meaning if you want to manipulate those values, you need to make a copy of that variable first (one which is not const).

author=McBick
For arrays why does something like int N = RPG::monsters.size(), not work? I am trying to find a way to easily keep track of the size of certain rm2k3 arrays without using a loop every time I need their array size. As it is now I have created a function just to count array sizes as I am tired of constantly using loops every time I need the array size.

I can't give you the exact syntax, but it ought to be something along the lines of
RPG::dbMonsterGroups[group_id]->monsterList->count()

It is possible that you need to substitute the -> with a . at the last one, and it's possible there is something else I'm forgetting. As mentioned, haven't done much C++ in quite a while, and haven't done any DynRPG in even longer. Also note that this value should be the number of enemies in the group as given by the database, not the monsters still alive in the battle. I didn't see any obvious reference to the number of currently living monsters.