My take on stuff

10818
  • Optimized and fixed some bugs in Partisan.py.
  • Font of messages created by the Partisan.py code will now scale by resolution.
Hey man, went to take a quick look at this. looks good, Im very glad to see that pointless log function at the bottom removed. I'm pretty sure partisans have always spawned on water because long ago more water terrain types were added and this file was never updated.
Code:
Old Version:
if ( pPlot.getTerrainType()!=tt_noterrain and pPlot.getTerrainType()!=tt_coast and pPlot.getTerrainType()!=tt_ocean and pPlot.getFeatureType()!=ft_ice and pPlot.isPeak()==False ):

Improved Version:
      if pPlot.getFeatureType() != ft_ice and pPlot.getTerrainType() not in (-1, tt_coast, tt_ocean):
still missin water terrain right? I came across isWater() in CyPlot.cpp and it uses the plot type which I like. I assume it would work good.
 
Hi Toffer90,

Will you release a final version of this before moving to GIT or will this stay as is Post-GIT ?

Cheers
Colonelflag
 
MToS v0.2.2.6 ▬ Aug. 18.
SVN rev. 11010
  • Added some custom cpp files that makes the AI smarter about training and using gatherers to build the buildings they can build.
    • Especially important for them to get the rock gatherer which is required for the stone tool maker. which gives stone tools bonuses that allows training of builders which opens up the ability to create the first route types.
    • However, you need to run the MakeDLLRelease.bat (fast) or the MakeDLLFinalRelease.bat (slow) to get this fix.
      • Final release gives faster end turns than the other one does.
      • These bat files are in the \Tools folder at the root of the mod.
    • This modmod works without that dll fix too, so you don't have to build the dll if you don't want to for some reason.
MToS v0.2.2.7 ▬ Aug. 26.
SVN rev. 11022
MToS v0.2.2.8 ▬ Sep. 3.
SVN rev. 11027
MToS v0.2.2.9 ▬ Sep. 5.
SVN rev. 11028
MToS v0.2.2.10 ▬ Sep. 13.
SVN rev. 11032
MToS v0.2.2.11 ▬ Sep. 13.
SVN rev. 11032
  • Scavenging camp no longer provide map bonuses.
 
Last edited:
I was startin to think of the PPIO thread as C2C's Python thread. I guess I'll post here now if you don't mind toffer.

Somebody just posted about Spartacus creating gladiators from animals. It could be changed with 1 line, so I opened the file.
I ended up lookin at this stuff:
Code:
    # Field Medic
    if CyUnitW.isHasPromotion(giFieldMedic):
        # 10% chance
        if not CyRandom().get(10, "Gods"):

            if not SDTK.sdObjectExists('Heroes', CyUnitW):
                CyUnitW.setDamage(0, False)
                SDTK.sdObjectInit('Heroes', CyUnitW, {})
                SDTK.sdObjectSetVal('Heroes', CyUnitW, 'HealTurn', GAME.getGameTurn())

            elif GAME.getGameTurn() > SDTK.sdObjectGetVal('Heroes', CyUnitW, 'HealTurn'):
                CyUnitW.setDamage(0, False)
                SDTK.sdObjectSetVal('Heroes', CyUnitW, 'HealTurn', GAME.getGameTurn())
I just switched it around a little but it works the same as Github version still.
These so called sdObjects are being made when necessary but never cleaned up.

I also did some reading the other day and if python's debug mode is off, asserts and other debug stuff won't even get compiled with the rest of the code.
In my mind as long as you guys inform players that the ini option may slow turn times, you can fill the python with asserts worry free. Just like the Dll - quantity over quality.
I was wondering if maybe the print statement has the same sort of compiler flags attached to the ini option and you (toffer) already figure this stuff out...
If that's true then print has an advantage over the other log functions.

Last thing - saw this, thought it might be worth copy/pasting.
I use the following code in the map exporter of DoC:

Code:
IMAGE_LOCATION = os.getcwd() + "\Mods\\RFC Dawn of Civilization\\Export"

os.getcwd() is the working directory of the process, which is the BTS folder in program files.

That won't work if the player places the mod in my documents. Instead I will recommend asking the exe for the mod location.
PHP:
const char* CvDLLUtilityIFaceBase::getModName(bool bFullPath = true) const;
gDLL->getModName()
Expose this to python by adding gc.getModName() and you should have a reliable way of getting the mod root dir in python.

EDIT: based on experience some people have a tendency to rename mods. Don't ask me why, but people do that. Using getModName means the path will work even if the user renames the mod. It also allows the mod creator(s) to have multiple installs of the same mod, like one development and one stable release for (multiplayer) gaming.
 
Last edited:
I was startin to think of the PPIO thread as C2C's Python thread. I guess I'll post here now if you don't mind toffer.

Somebody just posted about Spartacus creating gladiators from animals. It could be changed with 1 line, so I opened the file.
I ended up lookin at this stuff:
Code:
    # Field Medic
    if CyUnitW.isHasPromotion(giFieldMedic):
        # 10% chance
        if not CyRandom().get(10, "Gods"):

            if not SDTK.sdObjectExists('Heroes', CyUnitW):
                CyUnitW.setDamage(0, False)
                SDTK.sdObjectInit('Heroes', CyUnitW, {})
                SDTK.sdObjectSetVal('Heroes', CyUnitW, 'HealTurn', GAME.getGameTurn())

            elif GAME.getGameTurn() > SDTK.sdObjectGetVal('Heroes', CyUnitW, 'HealTurn'):
                CyUnitW.setDamage(0, False)
I just switched it around a little but it works the same as Github version still.
These so called sdObjects are being made when necessary but never cleaned up.
I'll look into it later.
I also did some reading the other day and if python's debug mode is off, asserts and other debug stuff won't even get compiled with the rest of the code.
In my mind as long as you guys inform players that the ini option may slow turn times, you can fill the python with asserts worry free. Just like the Dll - quantity over quality.
Are you thinking about the HidePythonExceptions in option? It doesn't slow down stuff very much as the code it enables will only run when an error happens, which means it enables code that will never run if there's no errors.

A lot of python printing is hidden behind a bDebugMode boolean, this debug mode can only be toggled by hitting Ctrl+Shift+Alt+D, or by messing in the in-game terminal.
I was wondering if maybe the print statement has the same sort of compiler flags attached to the ini option and you (toffer) already figure this stuff out...
If that's true then print has an advantage over the other log functions.
I don't know of any way to stop "print" from writing to file what it prints to the terminal, I think that is hardcoded in the BtS python implementation...
Last thing - saw this, thought it might be worth copy/pasting.
Doesn't help much as our thm files reference stuff in vanilla BtS folder like this:
GBitmap("../../../../Resource/Civ4/Custom/MultiListItem.tga", HVGrid, 8, 1, 0, 0);

And the xml that tells the exe where our thm files are does that like this:
<Path>Mods/Caveman2Cosmos/Resource/C2C.thm</Path>
Must be relative to BtS.exe

So we would need to write some code that edits the content of our thm files and that xml file during first time installation of C2C, but then if we were to make an installer I think it would be so much easier to make that installer require that the BtS.exe folder to be selected when asked for install path during installation so that everyone has the same mod path and that all python and dll code can assume the path instead of computing it.
 
Last edited:
===============================================================
In C we write code like

#ifdef DEBUG
printf("Some debug log... This could probably be achieved by python logging.Logger");
/* Do some sanity check code */
assert someCondition
/* More complex sanitycheck */
while(list->next){
assert fooCheck(list)
}
#endif

Is there a way to do this in python?

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

What you are looking for is a preprocessor for python. Generally you have three options:
  1. Write a selfmade script/program which replaces parts of your sourcecode based on certain templates before passing the result on to the interpreter (May be difficult)
  2. Use a special purpose python preprocessor like pppp - Poor's Python Pre-Processor
  3. Use a general purpose preprocessor like GPP
The main advantage of a preprocessor compared to setting a DEBUG flag and running code if (DEBUG == True) is that conditional checks also cost CPU cycles, so it is better to remove code that does not need to be run (if the python interpreter doesn't do that anyway), instead of skipping it.

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

Mohammad's answer is the right approach: use if __debug__.

In fact, Python completely removes the if statement if the expression is a static constant (such as True, False, None, __debug__, 0, and 0.0), making if __debug__ a compile-time directive rather than a runtime check.

The -O option is explained in detail in the python documentation for command line options, and there is similar optimization for assert statements.

So don't use an external preprocessor—for this purpose, you have one built in!

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

Matt: python has a built in debug mode which I assume is set by that option since the option toggles all the debug mode stuff and it cannot be changed in game.
I could be wrong about that tho - it could be always on.
If it's not always on then you can use if __debug__ instead of regular if statement for debug stuff. Only disadvantage would be that u can't change the setting in game.
 
Matt: python has a built in debug mode which I assume is set by that option since the option toggles all the debug mode stuff and it cannot be changed in game.
I could be wrong about that tho - it could be always on.
If it's not always on then you can use if __debug__ instead of regular if statement for debug stuff. Only disadvantage would be that u can't change the setting in game.
Right, your'e talking about "__debug__".
I don't know how start BtS in such a way that "__debug__" is set to "False".

HidePythonExceptions is not tied to "__debug__" in any way and "__debug__" is always True in standard BtS installations afaik; so using it is out of the question.

Simple "if" checks here and there to check a boolean does only take nanoseconds, so we don't loose much by hiding lots of debug code behind the bDebugMode variable.
 
Doesn't help much as our thm files reference stuff in vanilla BtS folder like this:
GBitmap("../../../../Resource/Civ4/Custom/MultiListItem.tga", HVGrid, 8, 1, 0, 0);

And the xml that tells the exe where our thm files are does that like this:
<Path>Mods/Caveman2Cosmos/Resource/C2C.thm</Path>
Must be relative to BtS.exe

So we would need to write some code that edits the content of our thm files and that xml file during first time installation of C2C, but then if we were to make an installer I think it would be so much easier to make that installer require that the BtS.exe folder to be selected when asked for install path during installation so that everyone has the same mod path and that all python and dll code can assume the path instead of computing it.
Is this really a problem? :confused:
Usually when the exe tries to open a file where it got the path from xml, it will try to set path prefixs in the following order: mod, bts, warlords, original. It stops the first time it encounters a file. If you want to read a vanilla file, do it by not adding a file with the same name in your mod. Your modded file could then be called something else if you want both. This also applies to files not specified in xml, like reading the xml files (which are hardcoded in CvXMLLoadUtilitySet.cpp).

Assuming this doesn't work, then you can mod the xml reading code. Either add another tag, which tells the prefix the dll should insert (as in getModName() or whatever) or add keywords like if path starts with WARLORDS, replace the first 7 characters with whatever path the dll seems correct to insert.

I have yet to see the need to set full paths in a mod and I'm not convinced you will ever need to do so. It's just a question of figuring out what you need to do in order to avoid it.
 
Is this really a problem? :confused:
:confused: No, I don't see any problems...
Usually when the exe tries to open a file where it got the path from xml, it will try to set path prefixs in the following order: mod, bts, warlords, original. It stops the first time it encounters a file. If you want to read a vanilla file, do it by not adding a file with the same name in your mod. Your modded file could then be called something else if you want both. This also applies to files not specified in xml, like reading the xml files (which are hardcoded in CvXMLLoadUtilitySet.cpp).
The exe doesn't follow that convention when looking for the theme files, it looks in exactly one position defined in CIV4ArtDefines_Misc.xml.
Assuming this doesn't work, then you can mod the xml reading code. Either add another tag, which tells the prefix the dll should insert (as in getModName() or whatever) or add keywords like if path starts with WARLORDS, replace the first 7 characters with whatever path the dll seems correct to insert.
It may be possible to get the exe to look for the thm files in "My Games\Beyond the Sword\MODS" this way; but I don't feel it's worth the effort. I personally don't want to figure out how to modify CvXMLLoadUtility::LoadGlobalClassInfo(...) to do this.

One would still need a dedicated C2C installer to, based on install location, modify the thm files to correctly use relative paths to all the vanilla art files it reference because these thm files are parsed by the exe.... So there's little we can do about how these files are parsed.
So again, I will state that I prefer that people have C2C in the mods folder located with the BtS.exe as the effort to allow it to be in "my documents" is not worth the extra flexibility in mod install location.
 
I personally don't want to figure out how to modify CvXMLLoadUtility::LoadGlobalClassInfo(...) to do this.
You add a read() function to CvArtInfoMisc. First line should be calling CvArtInfoScalableAsset::read (the parent). After that you can do whatever read stuff you like. In most cases you don't have to mod CvXMLLoadUtility itself.
 
You add a read() function to CvArtInfoMisc. First line should be calling CvArtInfoScalableAsset::read (the parent). After that you can do whatever read stuff you like. In most cases you don't have to mod CvXMLLoadUtility itself.
Reading the xml values isn't really all that relevant though, since the DEFAULT_THEME_NAME value in the xml is not necessarily correct depending on the mod install path.
How to report the adjusted path value for DEFAULT_THEME_NAME to the exe is what is not obvious to me.
One could modify the xml from the dll if its value is wrong... One would have to do that before the exe gets the value of DEFAULT_THEME_NAME.

Does the exe read the value of this xml...? Does the dll report it to the exe...? I don't know, perhaps you know?
 
Last edited:
I ended up lookin at this stuff:
Code:
    # Field Medic
    if CyUnitW.isHasPromotion(giFieldMedic):
        # 10% chance
        if not CyRandom().get(10, "Gods"):

            if not SDTK.sdObjectExists('Heroes', CyUnitW):
                CyUnitW.setDamage(0, False)
                SDTK.sdObjectInit('Heroes', CyUnitW, {})
                SDTK.sdObjectSetVal('Heroes', CyUnitW, 'HealTurn', GAME.getGameTurn())

            elif GAME.getGameTurn() > SDTK.sdObjectGetVal('Heroes', CyUnitW, 'HealTurn'):
                CyUnitW.setDamage(0, False)
                SDTK.sdObjectSetVal('Heroes', CyUnitW, 'HealTurn', GAME.getGameTurn())
I just switched it around a little but it works the same as Github version still.
These so called sdObjects are being made when necessary but never cleaned up.
Looked into this myself a bit, that unit script data is automatically cleaned up whenever the unit dies, it is data stored in the unit object instance, so if the instance of the unit is removed its object data is removed too.
It stands to reason that a unit that has this hero unit specific promotion won't ever loose the promotion without dying, so there is no wasted caching in this case.
 
Last edited:
Right on.

:confused: No, I don't see any problems...
I personally don't want to figure out how to modify CvXMLLoadUtility::LoadGlobalClassInfo(...) to do this.
No worries man, your allowed to say that.

Another bug was posted by SO that's the same as the other 2. Seems to fit with your theory for the last 1. Bug happen on expire event. That apparently garbage player index value should be the same as it was for the start of the event and you should've had problems there.

Code:
CyPlayer* CyGlobalContext::getCyPlayer(int idx)
{
    static CyPlayer cyPlayers[MAX_PLAYERS];
    static bool bInit=false;

    if (!bInit)
    {
        int i;
        for(i=0;i<MAX_PLAYERS;i++)
            cyPlayers[i]=CyPlayer(&GET_PLAYER((PlayerTypes)i));
        bInit=true;
    }

    FAssertMsg(idx >= 0 && idx < MAX_PLAYERS, "Player index requested isn't valid");

    return idx >= 0 && idx < MAX_PLAYERS ? &cyPlayers[idx] : NULL;
}
I think that FAssert is new, so that's good but if the index value is being check on the release builds anyways y not add an error message to go with it - one that will display the value of idx (im curious).
That's also the only FAssert in that file. I don't mind adding a bunch more if you guys want.

Adding FAsserts makes more sense then making a copy of CyGlobalContext in Python so you could add debug stuff to the funcs and then turn it on and off by switching GC (or whatever) to that file. That's too much messing around to be a good idea. ha

One of my ideas that might be a bit better is you could add a call to the dll in the dispatch event function in BugeventManager with eventType (string) as an arg to keep track on the dll. then add info to FAsserts. Just need a basic get and set func and 1 member in dll.

that file is incomplete btw. and it's gonna stay that way.
 

Attachments

I think that FAssert is new, so that's good but if the index value is being check on the release builds anyways y not add an error message to go with it - one that will display the value of idx (im curious).
The player index value was -1 when I checked, only checked once though, but I suspect it's always -1 when the error occur.
 
Last edited:
Hi Toffer90,

Not sure if it is your Modmod or not but when updated to the latest SVN (today) and applied your Modmod i noticed that 3/4 of the map improvements (seems random which ones) do not display any more (although they do in the city screen). Any ideas on what the issue could be ?

Cheers
Peter B
 
This is new paging system. It seems to have trouble with displaying stuff.
Previous one didn't work at all after save was loaded - panning caused memory leak.
This one seems to be bit too aggressive - it should display everything in current view.

Upload save so @billw2015 can adjust improvement paging.
 
Back
Top Bottom