[RM2K3] DYNRPG COMPILING ERROR

Posts

author=McBick
I believe with the map function it is impossible to have multiples of the same key too, so this should protect me from memory leaks too

The map data structure does not really protect you from memory leaks as it the value can be overwritten the exact same way a regular variable can
std::map<int,RPG::Image*> images;
images[0] = RPG::Image::create();
images[0] = RPG::Image::create();
RPG::Image::destroy(images[0]);

The code above also leads to a memory leak. The key does not protect you. Just as a side note
RPG::Image* image;
image = RPG::Image::create();
if(!image)
    image = RPG::Image::create();
RPG::Image::destroy(image);

This code does not lead to a memory leak. You do not need the std::map data structure to use the if check. To be honest, if you have two static images which you use and you don't loop through a for loop anyway, it would generally make sense to give them more specific names and use them directly as a variable, like RPG::Image* battleHUD or something (they still need to be global though). You might already understand this, but I'm just trying to attack it from various angles, since there still seems to be some confusion given how keys do not give protection against memory leaks.

author=McBick
I think I know why there aren't really any plug-ins that change the default battle system though. There are many issues with the order in which rm2k3 changes battle variables and such. I would have been better off just making my battle system exist independently from the default battle system. Unfortunately that would mean the removal of battle events as well unless I really went out of my way to parse monster group pages and battle events, which would be very time consuming.


That's probably part of it, along with the fact that most of the C++ developers here probably don't understand the battle system all too well, and the ones which do don't code C++ all too well. That, and it probably is tricky to make something nice and generic which could be useful for other people based on the default battle system without limiting the ways a plugin user can make changes to the system to fit their specific needs. It's a lot easier to hack together something which does what you need for your own game than to something which is generic enough for a random person to be able to incorporate it in a useful manner in their own game which won't require them to learn about a lot of quirks and conditions to be able to use the plugin. The default battle system just doesn't make this easy.
std::map<int,RPG::Image*> images;
images[0] = RPG::Image::create();
images[0] = RPG::Image::create(); //A crash should happen here
RPG::Image::destroy(images[0]);
From what I studied this should not work. At least from my understanding you can not declare the same key twice, but perhaps I misunderstood this?


author=Kazesui
You do not need the std::map data structure to use the if check. To be honest, if you have two static images which you use and you don't loop through a for loop anyway, it would generally make sense to give them more specific names and use them directly as a variable
Yes, I have learned this upon cleaning up my code. I have kept the map structure only for any HUD text now, but have since changed the objects for the window graphics to each have their own variable.

author=Kazesui
The default battle system just doesn't make this easy.
This is an understatement. I can't tell you how many times I had to recode my plugin to take into account how the default battle system handles their window objects. I still don't completely understand how they are handled, but I have managed to manipulate them enough to do what I want, after much testing, emphasis on "must." Some of them just will not cooperate with you and I had to either hide them and create my own window to replace it entirely or omit the feature from the battle system. For example I originally wanted to do a turn based system where you gave commands to your entire party before any actions took place, but this proved to be impossible as there were many bugs that came along with this method, especially with window objects. So now my current plugin has each battler takes a single turn based on the order of their agility until each battler has taken a turn and then the round is cycled over.

I've based my battle system off of Dragon Quest XI's battle system for a lot of things. Considering you can easily make a Final Fantasy type game with rm2k3 and I always wanted to make a Dragon Quest type instead, I ended up basing the battle system on that instead. Future installments of my plugin might see the function of a message box that describes each action taken, similar to Dragon Quest. For now such a feature is met with many issues like the game being unable to give me the amount of damage dealt, although this could be circumvented, but there are many issues like this.

author=Kazesui
RPG::Image* image;
image = RPG::Image::create();
if(!image) //Error cannot convert image from RPG::Image to type bool.
    image = RPG::Image::create();
RPG::Image::destroy(image);
I'm not sure how this is supposed to work as the if condition will always be false and the destroy function will always be called immediately after creating the Image. Also this does not compile. This is what I ended up doing to make things cleaner in my script.
std::map<std::string, RPG::Image*> myImage;
std::map<int, RPG::Image*> myText;
if(!myImage["winStats"])
    myImage["winStats"] = RPG::Image::create(320, 64);
if(!myImage["winParty"])
    myImage["winparty"] = RPG::Image::create(320, 64);
...
if(!myText["winStats"])
    myText["winStats"] = RPG::Image::create(160, 16);
...
I have no destroy functions as the code will never create multiples of the same Image objects.
author=McBick
std::map<int,RPG::Image*> images;
images[0] = RPG::Image::create();
images[0] = RPG::Image::create(); //A crash should happen here
RPG::Image::destroy(images[0]);
From what I studied this should not work. At least from my understanding you can not declare the same key twice, but perhaps I misunderstood this?

You're half right. That you cannot declare the same key twice is true, but a declaration of the key is actually only done the first time. If you would use the "insert" method, it would probably have failed, but not when using the subscript operator (the square brackets). What actually happens is that when you use this, it will first check if a key exists for they key you give, and if it does not exist, it will create a key. This is what happens the first time, but the second time it just gives you access to the pointer variable without trying to create another key.


author=Kazesui
You do not need the std::map data structure to use the if check. To be honest, if you have two static images which you use and you don't loop through a for loop anyway, it would generally make sense to give them more specific names and use them directly as a variable

Yes, I have learned this upon cleaning up my code. I have kept the map structure only for any HUD text now, but have since changed the objects for the window graphics to each have their own variable.

author=McBick
author=Kazesui
RPG::Image* image;
image = RPG::Image::create();
if(!image) //Error cannot convert image from RPG::Image to type bool.
    image = RPG::Image::create();
RPG::Image::destroy(image);
I'm not sure how this is supposed to work as the if condition will always be false and the destroy function will always be called immediately after creating the Image. Also this does not compile.

You sure you remembered to make "image" an RPG::Image* rather than an RPG::Image? While I don't have a compiler to validate with at the moment (or rather, I don't have one compatible with DynRPG), I'm pretty sure this should compile.
Also, the code was just for demonstrative purpose rather than being something which can actually be used. I was simply trying to make sure you didn't think you needed the map data structure to make the if statement work (which in this code example should be perpetually false, as you say).

author=McBick
std::map<std::string, RPG::Image*> myImage;
std::map<int, RPG::Image*> myText;
if(!myImage["winStats"])
    myImage["winStats"] = RPG::Image::create(320, 64);
if(!myImage["winParty"])
    myImage["winparty"] = RPG::Image::create(320, 64);
...
if(!myText["winStats"])
    myText["winStats"] = RPG::Image::create(160, 16);
...

I have no destroy functions as the code will never create multiples of the same Image objects.

I'm going to assume that the std::maps are global and that the ifs are within a callback function (I believe it should crash if this was all global). There's no need for the if statements at this point, since the keys can't exist at the point of the check, and as long as you're not using a callback which is called multiple times (which you shouldn't anyway for something meant to be allocated once like here). Apart from that, as mentioned, this should be fine.
author=Kazesui
You're half right. That you cannot declare the same key twice is true, but a declaration of the key is actually only done the first time. If you would use the "insert" method, it would probably have failed, but not when using the subscript operator (the square brackets). What actually happens is that when you use this, it will first check if a key exists for they key you give, and if it does not exist, it will create a key. This is what happens the first time, but the second time it just gives you access to the pointer variable without trying to create another key.
I will have to be careful of this in the future then.


author=Kazesui
You sure you remembered to make "image" an RPG::Image* rather than an RPG::Image?
I stand corrected, I did not declare the variable as a pointer which was the issue.


author=Kazesui
I'm going to assume that the std::maps are global and that the ifs are within a callback function (I believe it should crash if this was all global). There's no need for the if statements at this point, since the keys can't exist at the point of the check, and as long as you're not using a callback which is called multiple times (which you shouldn't anyway for something meant to be allocated once like here). Apart from that, as mentioned, this should be fine.
Your assumption is correct, they are all global maps. The if statements exist within battle callbacks. The reason for this is it makes it easier for me to see all the objects used within my functions. I could move them all to the onInit callback, but it can get annoying going back and forth between the callback and my function when editing my function to have more objects. Also I believe I tried that before and the game would not run upon execution. It would attempt to run and then close out right away. I think the object's class, ie RPG::Image, was not loaded yet when I was trying to declare my keys.

Is there a reason I can't include the if statements in a callback that is called multiple times? From my understanding nothing will happen, at worst it will check a single line of execution. I think the battle callbacks are only called 30 times a second, so that means the callback will be called 30 times a second? This seems quite negligible as even the weakest CPUs could run millions of lines of code a second.
author=McBick
Is there a reason I can't include the if statements in a callback that is called multiple times? From my understanding nothing will happen, at worst it will check a single line of execution. I think the battle callbacks are only called 30 times a second, so that means the callback will be called 30 times a second? This seems quite negligible as even the weakest CPUs could run millions of lines of code a second.


This is just a code thing, as there shouldn't be any performance issues from this (that aside, I would have thought it would be called 60 times a second, as rm2k3 otherwise generally runs at a fixed 60 FPS if it is able to keep up. Never checked for battles though).

While it's not going to be a performance issue, it will look like a curiosity though, since that if will be processed many times for no real reason. Ideally, you wouldn't need to go back and forth between the callback functions, since one would ideally just allocate it once and then use it in the other function. If you have a variable amount of text you might want to add. It's up to your discretion to do so or not though, and your plugin should function perfectly fine without doing this as well.

Another little tip which requires minimal change and keeps the code in the battle callback
if(!myImage["winStats"]){
    myImage["winStats"] = RPG::Image::create(320, 64);
    myImage["winparty"] = RPG::Image::create(320, 64);
    ...
    myText["winStats"] = RPG::Image::create(160, 16);
    ...
}

since you only allocate all images at once, you only need to check for one of your images. Either all of the images will have been allocated or none of them. This will prevent a little bit of code clutter from have a long list of if statements.
author=Kazesui
if(!myImage["winStats"]){
    myImage["winStats"] = RPG::Image::create(320, 64);
    myImage["winparty"] = RPG::Image::create(320, 64);
    ...
    myText["winStats"] = RPG::Image::create(160, 16);
    ...
}
I didn't think of that, I will implement that for sure. Ideally I would like to load all the objects once at startup, but for some reason the game just won't run when I do that. It is also useful to see all the objects in my functions while working on them as I can easily edit them on the fly without switching to different headers.

On another note is there any good way to sort learned skills? For example this:
//I get the current skill selected in the skill window here.
//I have to some how differentiate the different skill types here.
//The winSkill->currentChoice is shared with all skill types, in my case
//I have 2, skills and spells. learnedSkills is stored as a first in first out
//array, so there is no easy way to sort the different types. This results
//in incorrect skill descriptions being displayed in my plugin.
RPG::Actor::partyMember(CBS::currentBattler)->learnedSkills[RPG::battleData->winSkill->currentChoice]
//Refresh my text Image
myText["winDescription"]->clear();
//Write the skill description onto the text image
myText["winDescription"]->drawString(8, 8, RPG::skills[n]->description, 1);
//Draw the text on screen
RPG::screen->canvas->draw(0, 0, myText["winDescription"]);
As it is now, I might have to remove this feature which is unfortunate because I discovered a graphical glitch in rm2k3, outside of DynRPG, that this feature was hiding. If you select a skill to target a monster and then cancel before selecting a monster and then repeat the process again, the winParty and winPartyTarget window will not be redrawn causing it to become blank with no HP/MP/ATB showing on screen. I've tried to fix this, but these window objects aren't easy to manipulate, so I had to forgo manipulating them.

Edit: I solved my issue.
I finally finished my plugin, at least the first version of it. It is still missing quite a few features, but at least I now have a solid foundation to build upon in the future when I add the rest of the features. I'm just doing some last minute crash testing and then I will submit it. It likely won't be bug free as there are way too many things to test for in the default battle system, so I will have to rely on people's feed back for future bug fixes.
Is there an easy way to save variables into the game itself? I am working on a plugin that extends the number of stats each hero has, but every time I shut down the game the new stats are reset. The values are stored in global variables in the plugin. I could save them to the DynRPG ini file and have them read at start up, but is there an easier way than this?
The conventional way of doing this would be to use onSaveGame and onLoadGame callbacks and the functionality within it to save the data to files, assuming your data is save game specific.

You could use the text plugin source given on page 2 of this thread as an example of how this functionality can be used.

If this gives a headache and you can convert the values into integers, you could just store them directly into the RPG::variables, or you could even store in at actors which are only used as variable deposits, as then the ingame load and savegame functionality should take care of it and you just need to query these values directly from the database upon loading a gamefile.
As I thought, there is only that way. The problem with using the game's variables or hero database to store the values is that there is no way to know if the game maker will use them and also the number of values stored is not a fixed number, it depends on the plugin user's amount of heroes used.

@Kazesuu
I have been using enumerators and I am confused why I don't have to define it as a string, int, or other? Some how the compiler knows what it is when I am using the values. Why is this?
Yup, if you want to make it general for other people to use, then you'll have make use of that functionality.

As for enumerators, they are there more for the programmer's convenience than other things.
In the strictest sense, they are practically named constants which are automatically assigned an integer value if you don't explicitly assign a value to them.

// semantically, this is relatively similar
enum color
{
   RED,
   GREEN,
   BLUE
}

// to this
const int RED = 0;
const int GREEN = 1;
const int BLUE = 2;

// and to a certain extent even this
#define RED 0
#define GREEN 1
#define BLUE 2
Of course, note that each of these code blocks are not meant to be appear in any code base all at the same time.

enums are generally there to store named states or specific values which would be cryptic to keep track of between multiple programmers for a common code base.
// It's easier to understand what is happening here
if(myColor == RED)
    ...
// Than it is to understand this
if(myColor == 0)
    ...
Note that common convention dictates that constant values (like those found in enums) are generally all upper-case.
author=Kazesui
enums are generally there to store named states or specific values which would be cryptic to keep track of between multiple programmers for a common code base.
That is what I have been using them for, but it is weird to me that I don't have to define them as an int, string, or elsewise.


Do you know if there is a way to play animations from DynRPG, specifically during battle? This is the only thing I can find for playing animations in battle:
RPG::AnimationInBattle->isAnimationPlaying = true;
RPG::AnimationInBattle->currentAnimationId = n;
This does nothing when executed though.
author=McBick
That is what I have been using them for, but it is weird to me that I don't have to define them as an int, string, or elsewise.

As mentioned, the compiler automatically considers them to be integers (unless other specified, though limited to being some integer type variant, e.g. no float or string).

author=McBick
Do you know if there is a way to play animations from DynRPG, specifically during battle? This is the only thing I can find for playing animations in battle:
RPG::AnimationInBattle->isAnimationPlaying = true;
RPG::AnimationInBattle->currentAnimationId = n;

This does nothing when executed though.

Nope, do not know how to use the native battle animations. If I felt the need to use animations in the default battle system, I would probably just use RPG::Image directly, though that would be tricky on a potential non-savvy end-user, as you'd lose the battle animation generation interface.
That is the route I was going to go, but instead create image copies of each cel in the animation and play it like it would in the animation database. This would take a bit of work to get right as I have to copy only part of the battle animation image which means I have to figure out an algorithm to determine the size of the cel for each cel of the image file.

I'm not sure how taxing it would be to create so many Image class objects either. I can't just use one for the entire animation as you can only draw an Image object in a limited time frame, although I would have to test it to see how limited that time frame is. Ideally I would only use one Image object and just copy the cel properties to it and draw it on screen, but I'm not sure if that would work for the aforementioned reasons.
I guess this is already solved, but I just wanted to say that the error 1114 is an actual Windows error code and it means "A dynamic link library (DLL) initialization routine failed" which means that the DllMain function (which the compiler usually generates) returned FALSE. Either some misconfiguration with the compiler, or you have some global variables that are getting initialized with things that don't yet exist when the library is loaded, for example if you try to create some game objects before onInitFinished (the engine hasn't started yet).
author=Cherry
I guess this is already solved, but I just wanted to say that the error 1114 is an actual Windows error code and it means "A dynamic link library (DLL) initialization routine failed" which means that the DllMain function (which the compiler usually generates) returned FALSE. Either some misconfiguration with the compiler, or you have some global variables that are getting initialized with things that don't yet exist when the library is loaded, for example if you try to create some game objects before onInitFinished (the engine hasn't started yet).
I did resolve it, but I did so by rewriting the code and getting lucky. This is very helpful to know as I have run into this issue in another plugin I am working on. I had a hunch that it was the variable initialization, but wasn't sure. Thanks to this information, I should be able to avoid this issue completely in the future now.
Can someone explain how I can change the following value without an enum?
class Skill {
    public:
        SkillType type; //what is this object, doesn't seem to be static or an int?
...

//Something like this works...
RPG::skills[1]->type = RPG::SKILL_NORMAL;

//But this doesn't...
RPG::skills[1]->type = 5; //to access subsets you need to use 4 or higher.
//invalid conversion from 'int' to 'RPG::SkillType' [-fpermissive]
What error message do you get? The code doesn't look correct in the first place because I guess it needs to be `RPG::skills` and not `RPG::Skills`.

(Also while doing something like that, keep in mind it's not saved and loaded, unless you implement that yoursave in hooks. It will stay until you close the game, regardless of saving or loading, and won't be restored next time.)
author=Cherry
What error message do you get? The code doesn't look correct in the first place because I guess it needs to be `RPG::skills` and not `RPG::Skills`.

(Also while doing something like that, keep in mind it's not saved and loaded, unless you implement that yoursave in hooks. It will stay until you close the game, regardless of saving or loading, and won't be restored next time.)

I have it as RPG::skills in my code, typo in my post. The error is:
RPG::skills[1]->type = 5;
//invalid conversion from 'int' to 'RPG::SkillType' [-fpermissive]

I am trying to modify skills during gameplay. I am only experimenting now to see how far I can take it.

Try converting it explicitly:

RPG::skills[1]->type = (RPG::SkillType)5;