How do I reference a Python Mod function from within SDK??

sirkris

Chieftain
Joined
Dec 16, 2005
Messages
57
I'm creating a very small Python mod, in fact it's just a single function that opens a remote URL (since this cannot be done from within the SDK's C++ configuration itself). This function is to be called from within the CvGameCore.dll (CvGame.cpp), passing a simple string variable to it.

You with me so far? Good. Now here's where I'm running into a snag: I don't know how to call that function from within the CvGame.cpp file!

As I understand it, here's how the game currently calls the non-mod Python functions:

In CvDefines.h, the following references are declared:

// python module names
#define PYDebugToolModule "CvDebugInterface"
#define PYScreensModule "CvScreensInterface"
#define PYCivModule "CvAppInterface"
#define PYWorldBuilderModule "CvWBInterface"
#define PYPopupModule "CvPopupInterface"
#define PYDiplomacyModule "CvDiplomacyInterface"
#define PYUnitControlModule "CvUnitControlInterface"
#define PYTextMgrModule "CvTextMgrInterface"
#define PYPerfTestModule "CvPerfTest"
#define PYDebugScriptsModule "DebugScripts"
#define PYPitBossModule "PbMain"
#define PYTranslatorModule "CvTranslator"
#define PYGameModule "CvGameInterface"
#define PYEventModule "CvEventInterface"


These are the only header declarations for the Python files that I could find in the SDK, and it only references the interface .py files that are in the following directory: <Civ4 game dir>\Assets\Python\EntryPoints


But, obviously, I wouldn't want to stick my mod in there. It would probably work, but it'd be very sloppy and not the way mods are intended to be installed. So my question is, where would I declare a .py file in the Mods directory? For example, let's say I have function "TestMe()" in the file, "<Civ4 game dir>\Mods\TestMod\MyModFile.py". Where would I declare that in the SDK? We'll return to this example in a moment.

Now let's see how Python functions are already called from within the C++ src. In CvGame.cpp, we have this at line 6155:

"gDLL->getPythonIFace()->callFunction(PYGameModule, "doHolyCity", NULL, &lResult);"


If you scroll back up to CvDefines.h, you'll see that "PYGameModle" refers to "CvGameInterface.py" in the Assets\Python\EntryPoints directory, and "doHolyCity" is the function being called.

So now let's go back to my example. If you remember, we had function "TestMe()" in the file, "<Civ4 game dir>\Mods\TestMod\MyModFile.py". So knowing what we've learned about the syntax, let's call the function from CvGame.cpp as follows:

"gDLL->getPythonIFace()->callFunction(PyTestModule, "TestMe", NULL, &lResult);"

In this example, you can see we're calling function TestMe() from within the Python file specified by PyTestModule.

Still with me so far? Yes? Good. No? Too bad. Anyway, we now run into my not-so-perverbial brick wall. How/where would I define "PyTestModule" so that it would refer to "<Civ4 game dir>\Mods\TestMod\MyModFile.py"? If I just add it to CvDefines.h, then it would presumably look for that file in the EntryPoints directory with the interfaces, not the Mods directory. Now do you understand my problem?


I know this is a long and complicated post, and I'm sure the solution is insultingly simple. But please, for the love of god, somebody respond to this post and at least point me in the right direction! I've searched the forum, read through the Python tutorials, but haven't found anything that answers this question!

Hell, even if you don't know, at least post THAT as a reply just so I know it's not just me! Please! I know I'm not crazy! Well ok, I am crazy, but still! There just HAS to be a way to do this..... :confused:


Thanks,

--Kristopher
 
sirkris said:
These are the only header declarations for the Python files that I could find in the SDK, and it only references the interface .py files that are in the following directory: <Civ4 game dir>\Assets\Python\EntryPoints


But, obviously, I wouldn't want to stick my mod in there. It would probably work, but it'd be very sloppy and not the way mods are intended to be installed. So my question is, where would I declare a .py file in the Mods directory? For example, let's say I have function "TestMe()" in the file, "<Civ4 game dir>\Mods\TestMod\MyModFile.py".

Well, in CvDefines, \\Assets\\Python should be the python directory in your mods directory. So if you used...

"gDLL->getPythonIFace()->callFunction(PyTestModule, "TestMe", NULL, &lResult);"

..assuming that PyTestModule was under defines for "MyModFile", then you should be able to call the python file under:

My Documents\My Games\Sid Meier's Civilization 4\MODS\TestMod\Python\EntryPoints\MyModFile.py

right? I haven't done this, so I'm not completely sure. Tell me how it works out for you.

I don't think that <Civ4 Game Directory> is going to be the game directory in Program Files if you're loading a mod. If you are making a new file to go into the custom assets folder, the new file probably wouldn't get seen because it's not in the Program Files folder like most files, and thus the file in the custom assets directory isn't really replacing a file, so it won't work (unless I have this wrong, I tried it once and seemed that that's how it worked). So, I think if you're making this for a loadable mod in the "My Documents/My Games/Sid Meier's Civilization 4/Mods" directory, you should be fine. If you're looking for something someone just throws in their custom assets folder, you may be out of luck.
 
Err wait, I thought mods were installed to the program files/civ4/Mods directory. I didn't even realize there was ANOTHER mods directory in My Documents, but sure enough you are right on that.

So why are there two separate MOD directories? The one under program files has the 4 default mods in subdirectories; i.e. tutorial, american revolution, etc. The "MODS" directory under My Documents is blank.

Now I'm more confused.... :sad:
 
sirkris said:
Err wait, I thought mods were installed to the program files/civ4/Mods directory. I didn't even realize there was ANOTHER mods directory in My Documents, but sure enough you are right on that.

So why are there two separate MOD directories? The one under program files has the 4 default mods in subdirectories; i.e. tutorial, american revolution, etc. The "MODS" directory under My Documents is blank.

Now I'm more confused.... :sad:

I have no idea. I'm guessing that the mods in the main civ directory are for official mods, while the ones in My Doc's are for user-based (unofficial) mods?

In any case, as long as you get your problem solved, cheer up :O)

Tell me how that comes along, I'm sure I'm going to have to eventually do it.
 
Heh - I always put my mods in the Civ4/Mods directory. IIRC there was a bug in the My Documents version which did something bad. I'm not sure if it's been fixed or not.
 
Well I finally figured out how to get it to compile without any errors at least. My solution was a bit hackish, but here's what I did: I modified CvDefines.h and added a define for a new Python file. I had to put it in the mod's entrypoints directory, but at least I was able to call it.

Now I'm just dealing with another annoying problem: It compiles fine, and it lists/loads the mod fine. Only problem is it doesn't do anything! That is, either the Python function isn't being called, or it's being called but not executing properly. Debugging this is gonna be next to impossible!

Is there a way to debug a Python file without loading the game? I.e. execute it through some independent environment, such as simulating a call to a particular function? If I could do that and it works, then I'll know the problem is in the C code. And if it doesn't work, then I'll know the problem is in the Python file.


Any ideas on how I can debug this? I just need to test to see if a certain section of code (both in the C++ file and in the Python file) is being executed at all at the event in question. In PHP, for example, I would just do something like: die( "DEBUG" ); to see if the program execution is reaching that point (i.e. to see if an ifcheck is firing properly, etc). I have no idea how I'd do this here though.

Any ideas??
 
sirkris said:
Well I finally figured out how to get it to compile without any errors at least. My solution was a bit hackish, but here's what I did: I modified CvDefines.h and added a define for a new Python file. I had to put it in the mod's entrypoints directory, but at least I was able to call it.

Now I'm just dealing with another annoying problem: It compiles fine, and it lists/loads the mod fine. Only problem is it doesn't do anything! That is, either the Python function isn't being called, or it's being called but not executing properly. Debugging this is gonna be next to impossible!

Is there a way to debug a Python file without loading the game? I.e. execute it through some independent environment, such as simulating a call to a particular function? If I could do that and it works, then I'll know the problem is in the C code. And if it doesn't work, then I'll know the problem is in the Python file.


Any ideas on how I can debug this? I just need to test to see if a certain section of code (both in the C++ file and in the Python file) is being executed at all at the event in question. In PHP, for example, I would just do something like: die( "DEBUG" ); to see if the program execution is reaching that point (i.e. to see if an ifcheck is firing properly, etc). I have no idea how I'd do this here though.

Any ideas??


Compile the dll as a debug build. If you're using Visual Studio, you should be able to use the debugger to connect to the Civ4 process and add breakpoints. If not, you can always try this in the C++ code...

FAssertMsg(false, "My function is being called!");

If the dll is built using debug mode, this should pop up an assertion failed box with that message.

If you're using Visual Studio, I think you're best off trying to get the debugger working. If you can, you can set a breakpoint right before and step through the code, making sure that the code is actually called. The debugger won't go through the python code, but in the python code you can just use something like...

CvUtil.pyPrint("My Message")

This will print out the message into the PythonDbg.log file.
 
Gerikes said:
Compile the dll as a debug build. If you're using Visual Studio, you should be able to use the debugger to connect to the Civ4 process and add breakpoints. If not, you can always try this in the C++ code...

FAssertMsg(false, "My function is being called!");

If the dll is built using debug mode, this should pop up an assertion failed box with that message.

If you're using Visual Studio, I think you're best off trying to get the debugger working. If you can, you can set a breakpoint right before and step through the code, making sure that the code is actually called. The debugger won't go through the python code, but in the python code you can just use something like...

CvUtil.pyPrint("My Message")

This will print out the message into the PythonDbg.log file.

I built it using the free method posted here, i.e. using Codeblocks. I thought that debugging mode didn't work with that?
 
The Great Apple said:
Heh - I always put my mods in the Civ4/Mods directory. IIRC there was a bug in the My Documents version which did something bad. I'm not sure if it's been fixed or not.

Mods stored in the My Documents folder were incorrectly prepending additional information to the file path of saved games using that mod, making it impossible to load them. I *think* that got fixed with the latest patch.
 
Back
Top Bottom