• Our friends from AlphaCentauri2.info are in need of technical assistance. If you have experience with the LAMP stack and some hours to spare, please help them out and post here.

Quick Modding Questions Thread

Hello! I'm trying to figure out if it is possible to rename your cities with more than 15 characters, I was looking through the xml files and couldn't find anything. Any help please? Thanks a lot!
Python/CvEventManager.py
Search for the line with "def __eventEditCityNameBegin" (line 956 in vanilla). This function takes care of creating the rename city window. The second last line in this function is
PHP:
popup.setEditBoxMaxCharCount( 15 )
Change this number to whatever you want and it will likely work just fine.
 
Hello there,

I would like to make a tool to look at save files. Rather than try to reverse-engineer the file, it would be so much easier to just see the code that generates the save file. I found:

virtual void SaveGame(CvString& szFilename, SaveGameTypes eType = SAVEGAME_NORMAL) = 0;

in CvDLLEngineIFaceBase.h, but I can't seem to find the code for this function. I have the steam version, so I'm relying on downloaded files (from here: https://forums.civfanatics.com/resources/civ4colonization-cvgamecoredll.23339/). I may not have the necessary file at the moment. Finding this for the base game would be a good start to get the general format of the file, but I would eventually like to figure this out for a modded version of Colonization (RaR specifically).

If someone could point me in the right direction, I would really appreciate it.

Thanks,
Grant
 
Hello there,

I would like to make a tool to look at save files. Rather than try to reverse-engineer the file, it would be so much easier to just see the code that generates the save file. I found:

virtual void SaveGame(CvString& szFilename, SaveGameTypes eType = SAVEGAME_NORMAL) = 0;

in CvDLLEngineIFaceBase.h, but I can't seem to find the code for this function. I have the steam version, so I'm relying on downloaded files (from here: https://forums.civfanatics.com/resources/civ4colonization-cvgamecoredll.23339/). I may not have the necessary file at the moment. Finding this for the base game would be a good start to get the general format of the file, but I would eventually like to figure this out for a modded version of Colonization (RaR specifically).

If someone could point me in the right direction, I would really appreciate it.

Thanks,
Grant
CvDLLEngineIFaceBase.h contains functions located in the exe file, meaning we do not actually have the save function itself. Luckily it's not that difficult to figure out with debugging and reading the savegame with a hex editor. Even better, there is no encryption, compression or anything like that.
The savegame is as follows:
Some header containing name of mod, exe version and possibly something else. The good part about this is that it appears to have a fixed length. For your purpose you can likely get away with ignoring the first X bytes.
CvInitCore
CvGameAI
CvMap
CvTeamAI for each team (MAX_PLAYERS)
CvPlayerAI for each player (MAX_PLAYERS)

Each of those classes have functions like
PHP:
void CvInitCore::read(FDataStreamBase* pStream)
void CvInitCore::write(FDataStreamBase* pStream)
Those functions do call read/write in other classes, like cities are saved inside the owner, meaning CvPlayerAI::read will call CvCityAI::read.

pStream has a bunch of overloaded Read() and Write() functions. They do what you would expect, which is to read or write variables. If the argument is an int, it will read 4 bytes. If it's a short, it will read 2 bytes and so on. When given two arguments, it will read an array. First argument is length and the second is a pointer to where it should be stored in memory. In other words the byte size for the array element depends on the type of pointer.

There are also strings, which are stored as plain text. CvString use one byte for each character while CvWString use 2 bytes for each character.

I think that's pretty much it. Since we have access to the savegame generating functions, we can modify the savegame pretty much as we like, including adding tags for you to hook on to. In fact we can change the format completely and save as xml if we feel like it. The tradeoff from doing that would be slower saving and bigger files.

I don't think it will be possible to make a savegame tool, which fits all mods because the savegame is just a bunch of bytes. The meaning of each byte is hardcoded in the DLL file using functions, which are often modified in all mods with a custom DLL.

EDIT: the format is actually also depending on xml files. It stores ints like unit is of UnitType 4 and then it requires looking in the xml file what type 4 is. Also in some cases there is an array of length (length of xml file).
 
Last edited:
Hi.
Inspired by sullla's ongoing ai survivor autoplay tournament, I have barricaded myself behind mountains in the ocean and entered debug mode (ctrl-z) to watch the ai fight it out amongst themselves.

But I do not get alerted to DoW and place agreements (no horn signals, no alert text on screen).

I know settling a few great spies in each capital would be a way, but I am told that also distorts ai espionage spending.

Is there a better way to get alerts of war and peace?
 
I copied the Destroyer Escort from LoR to HitM and changed the name to Early Destroyer. That works, I then changed SeeInvisible from NONE to INVISIBLE_SUBMARINE, as with the Destroyer. When I created some other units, such information automatically showed up in the Special Abilities box in the Civilopedia. In this case it did not. I closed and restarted the game, still nothing in the Civilopedia. I checked unitinfos again, the change is still there. Any ideas ?
 
I've noticed that if I make another civ a vassal, I suddenly start getting a random "citizens of X city rightfully ask to join" my vassal every few turns. All of my civ's cities are also available to be "liberated" to my vassals in the trade screen. How do I disable this?
 
I'm trying to compile a DLL of the Legends of Revolution source files pasted over the BtS code. For some strange reason it works perfectly fine when I'm compiling a Debug DLL (even playtested a bit), but whenever I try for a Release version, I get a large number of error messages. None of them make any sense however, claiming that e.g.

Code:
CyCityInterface2.cpp(85): error C2039: 'getRevolutionIndex' : is not a member of 'CyCity'

which a quick search in CyCity turns up that yes, getRevolutionIndex is indeed a member of 'CyCity'.

Matter of fact, literally all error messages are from that file CyCityInterface2.cpp, and they all follow the same structure:

Code:
1>CyCityInterface2.cpp(85): error C2039: 'getRevolutionIndex' : is not a member of 'CyCity'
1>          c:\Games\Sid Meier's Civilization 4 Complete\Beyond the Sword\Mods\Knoedelicious 2\CvGameCoreDLL\CyCity.h(20) : see declaration of 'CyCity'
1>CyCityInterface2.cpp(85): error C2065: 'getRevolutionIndex' : undeclared identifier
1>CyCityInterface2.cpp(86): error C2228: left of '.def' must have class/struct/union type

Only 'getRevolutionIndex' is replaced with 'changeRevolutionIndex' or 'changeRevRequestAngerTimer' or
'AI_bestUnitAI' or whatever. Basically it's claiming that all these functions do not exist in CyCity, but that is just plain wrong, they do exist!

What is going on here? Did I miss anything? Why can a debug DLL be compiled without a hitch but the exact same code somehow throws a fit when I'm trying for release? What?
 
Whenever you get really weird compiler errors, particularly regarding not having certain functions in classes when they are in fact there, chances are that you somehow ended up with corrupted or outdated object files. You should try to clean your project, either from the menu or by manually deleting the .o files from the source code (menu is generally preferred).
 
Thanks, that fixed it!
 
I am having trouble getting the animated resources to work. I get a single static animal not the animated version. I even tried adding them to a new mod based on Johny Smith's Stripped mod but still they aren't animated
In CIV4ArtDefines_Bonus.XML I have
Code:
           <BonusArtInfo>
              <Type>ART_DEF_BONUS_LLAMA</Type>
              <fScale>1.0</fScale>
              <fInterfaceScale>1.0</fInterfaceScale>
              <NIF>Art/Terrain/Resources/llama/llama.nif</NIF>
              <KFM></KFM>
              <Button>Art/Interface/Buttons/WorldBuilder/llama.dds</Button>
            <FontButtonIndex>40</FontButtonIndex>
                <FontButtonIndex>124</FontButtonIndex>
           </BonusArtInfo>
        <BonusArtInfo>
            <Type>ART_DEF_BONUS_LION</Type>
            <fScale>0.5</fScale>
            <fInterfaceScale>1.0</fInterfaceScale>
            <NIF>Art/Terrain/Resources/Lion/lioness.nif</NIF>
            <KFM>Art/Terrain/Resources/Lion/Cow.kfm</KFM>
            <SHADERNIF>Art/Terrain/Resources/Lion/lioness_FX.nif</SHADERNIF>
            <Button>Art/Interface/Buttons/WorldBuilder/cavelion.dds</Button>
            <FontButtonIndex>40</FontButtonIndex>
            <!--FontButtonIndex>102</FontButtonIndex-->
        </BonusArtInfo>

Any one know what I am doing wrong?
 
Question: anywhere in xml files I can adjust how much fail-gold is produced when Wonder can no longer be build?
Also fail gold adjustments when missionary can't be build?

Thank You!
Yes, in Assets/XML/GlobalDefines.xml:
Code:
    <Define>
       <DefineName>MAXED_UNIT_GOLD_PERCENT</DefineName>
       <iDefineIntVal>50</iDefineIntVal>
   </Define>
   <Define>
       <DefineName>MAXED_BUILDING_GOLD_PERCENT</DefineName>
       <iDefineIntVal>50</iDefineIntVal>
   </Define>
   <Define>
       <DefineName>MAXED_PROJECT_GOLD_PERCENT</DefineName>
       <iDefineIntVal>50</iDefineIntVal>
   </Define>
It's percent of the building cost refunded in gold.
 
I have a question too:

A couple of pedia entries depend on the current world (map) size. For example the civic effect "+X happiness in Y largest cities" or the wonder effect "Provides X of Y resource" scale with map size. When you open the civilopedia from the main menu, there obviously is no current map size, so the pedia apparently displays some kind of default value.

In my mod this default value seemingly broke at some point. When I go into pedia from main menu, I get a Python exception triggered by a C++ exception whenever one of these entries is about to be displayed. I don't think I ever changed anything related to how civic/building texts are generated or how map sizes are loaded. I'm a bit confused how this works in general because everything relies on GC.getMap().getWorldSize(), without a special case for the pedia without a ongoing game. So from the looks of it this shouldn't even work in the base game?

No idea how to go about fixing this except setting some default map size myself. Any ideas or insights that could help me?

Edit: I found out that when entering the pedia from the main menu, GC.getMap().getWorldSize() returns -1. That explains why I get an error, but not why it works in the base game.
 
Last edited:
Another question, is there a way to check at runtime whether the game is running the Russian translation or the normal international EFIGS version? I'd like to guard better against reading the first language entry from XML and expecting English, even though it is Russian in the Russian version for inexplicable reasons (couldn't have anything but Russian first I guess).
 
Another question, is there a way to check at runtime whether the game is running the Russian translation or the normal international EFIGS version? I'd like to guard better against reading the first language entry from XML and expecting English, even though it is Russian in the Russian version for inexplicable reasons (couldn't have anything but Russian first I guess).
I'm not sure, but a wild guess would be something like
PHP:
if (localText.getText("TXT_KEY_LANGUAGE_0", ()) != "Russian in Russian"):
There might be a better way, but I do not really know the Russian version and don't have it on my computer, which makes it somewhat tricky to come up with something I know will work. There might also be a different string, which would work better. This is a hint on how to maybe make a solution, not a solution in itself.

EDIT:
maybe something like:
PHP:
if (gc.getGame().getCurrentLanguage() != 0 or localText.getText("TXT_KEY_LANGUAGE_0", ()) == "English"):
That should be true if selected language is not the first or if the first language calls itself "English".
 
Last edited:
Oh so you're suggesting to take a known text key and check if it actually contains the expected English text as first language? That's a great idea. I will try it, thanks.
 
Anyone knows how to make a unit give a free promotion when attached to an other one?
For example I create a Fart Frog (oops.... :lol: ) Dart Frog, set the <LeaderPromotion> to PROMOTION_POISON_ARROWS. The pedia text displays what happens when attached to a unit but there is no icon to attach it to any unit. :confused:
Any ideas?
 
I think you separately need to set the XML field that enables the unit to attach to other units, probably <bWarlord> or something like that. The modiki knows more.
 
I think you separately need to set the XML field that enables the unit to attach to other units, probably <bWarlord> or something like that. The modiki knows more.
No, it doesn't.
My quick tests show that this feature ONLY WORKS WITH the PROMOTION_LEADER. Which is strange since in Colonialism it works fine AFAIK.
 
Back
Top Bottom