• 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

I tried to add a new game speed in the XML file "CIV4GameSpeedInfo". But when I load the mod and attempt to start a new game, only the standard game speed options are displayed (marathon, epic, standard, quick). Is there anywhere else in the XML I need to make an edit to allow the new option to be selectable? The XML for the new speed ("Unclesam") that I added is:

<Civ4GameSpeedInfo xmlns="x-schema:CIV4GameInfoSchema.xml">
<GameSpeedInfos>
<GameSpeedInfo>
<Type>GAMESPEED_UNCLESAM</Type>
<Description>TXT_KEY_GAMESPEED_UNCLESAM</Description>
<Help>TXT_KEY_GAMESPEED_NORMAL_HELP</Help>
<iGrowthPercent>100</iGrowthPercent>
.......
</GameTurnInfo>
</GameTurnInfos>
</GameSpeedInfo>

EDIT: Never mind, I found a previous thread explaining that CIV4CultureLevelInfo must be modified as well. Thanks!
 
Last edited:
Is there a way to make a certain civ more or less likely to appear in the game (i.e when all civs are random)?
A mod could be programmed to vary the likelihood of the different result possibilities. But it would probably require DLL coding. I could do it but I've already got 5k projects going. The other way, of course, would be to select the AI players by hand during game setup, or to limit the number of players so severely that you get pretty much the same selection every time.
 
Is there a way to make a certain civ more or less likely to appear in the game (i.e when all civs are random)?
You could try duplicating the CivilizationInfo (Civ4CivilizationInfos.xml) of those civs that should appear more frequently. E.g. <Type>CIVILIZATION_AMERICA2</Type> and everything else just copy-pasted.
 
You could try duplicating the CivilizationInfo (Civ4CivilizationInfos.xml) of those civs that should appear more frequently. E.g. <Type>CIVILIZATION_AMERICA2</Type> and everything else just copy-pasted.
...but then there is also a chance for a civ to appear twice in the same game.
 
...but then there is also a chance for a civ to appear twice in the same game.
:cringe: There's always a catch.
I've tried it now because I still had some hope that the game would not pick multiple Americas to avoid clashing DefaultPlayerColors, but, no, I do get multiple Americas, and they're given different colors. Duplicating leaders doesn't seem to help either; i.e. doesn't make a civ more likely to be selected.
 
A mod could be programmed to vary the likelihood of the different result possibilities. But it would probably require DLL coding. I could do it but I've already got 5k projects going. The other way, of course, would be to select the AI players by hand during game setup, or to limit the number of players so severely that you get pretty much the same selection every time.
I started looking around for a DLL solution and it looks like the game EXE is calling CvGame::addPlayer() where one of the arguments is which civ the player in question is. In other words it looks like the decision is done inside the exe, which is near impossible to mod. If you have an idea on how to move the decision to the DLL, then do tell.
 
Hello everybrother.
How can resources be traded that are produced by a cooperation? I couldn´t find any blog.
Thx for your help.
 
I started looking around for a DLL solution and it looks like the game EXE is calling CvGame::addPlayer() where one of the arguments is which civ the player in question is. In other words it looks like the decision is done inside the exe, which is near impossible to mod. If you have an idea on how to move the decision to the DLL, then do tell.
Ah... if that's where it's taking place then yeah... that's going to be a little tough. I would have hoped, if I were trying to go about this mod, that when the selection is left to randomization, that the selection process could be found in the DLL. You might be able to force it by some kind of scatter and rearrange the indexes method but that's probably still going to be something the EXE will balk at.

@firaxis: Isn't it high time you released the CivIV EXE to a fully open source licencing??? Surely the agreement with Gamebryo has a limited term...
 
@firaxis: Isn't it high time you released the CivIV EXE to a fully open source licencing??? Surely the agreement with Gamebryo has a limited term...
Sadly @firaxis haven't been online since 2008. If we are to encourage them to do something like this, we have to do it in another way. I fully support it because not only would it allow us to mod the exe, it would also allow us to use a modern compiler, 64 bit (C2C could use more memory if I recall correctly) and allow bugfixes. I found a bug in the colonization exe where in some cases peace proposals send by the dll will vanish in the exe unless you are at peace already (no idea if this affects BTS too, but most likely it does). Most likely just a flipped bool, but without the source, it is quite hard to fix.

The question is how do we encourage them to provide the source?
 
Firaxis seems to be pretty active on Reddit.
 
Sadly @firaxis haven't been online since 2008. If we are to encourage them to do something like this, we have to do it in another way. I fully support it because not only would it allow us to mod the exe, it would also allow us to use a modern compiler, 64 bit (C2C could use more memory if I recall correctly) and allow bugfixes. I found a bug in the colonization exe where in some cases peace proposals send by the dll will vanish in the exe unless you are at peace already (no idea if this affects BTS too, but most likely it does). Most likely just a flipped bool, but without the source, it is quite hard to fix.

The question is how do we encourage them to provide the source?
The first part of answering that question is to figure out WHO can make such a decision to provide the source! I mentioned Gamebryo because from all the chatter on the forums here, best I can tell is that the main hangup that may never allow it is the Gamebryo graphic engine contract. If someone were to identify the true decision-making authority in this case, we might have a shot at approaching that person or persons to see if we can't get a FULL release, even if only to a limited group of us here under a carefully consider contract perhaps. hell... we might be able to make a evolved Civ IV game they can release and profit from if they play their cards right. Civ 5-6 went in such a different game design theory direction that there was so much potential still left on the table here. An upgrade to THIS core game engine would be hugely popular.

And yeah, C2C could certainly use a 64 bit expansion and may require it to pull off everything we really want to do.
 
I started looking around for a DLL solution and it looks like the game EXE is calling CvGame::addPlayer() where one of the arguments is which civ the player in question is. In other words it looks like the decision is done inside the exe, which is near impossible to mod. If you have an idea on how to move the decision to the DLL, then do tell.

It seems in CvGame::init you can set civs/leaders for any player as you like. FfH does this for the "Random [Good|Evil|Neutral] Leader" feature (it's just fake leaders that are replaced in CvGame::init). There may be more FfH-specific code involved, though.
 
best I can tell is that the main hangup that may never allow it is the Gamebryo graphic engine contract. If someone were to identify the true decision-making authority in this case, we might have a shot at approaching that person or persons to see if we can't get a FULL release, even if only to a limited group of us here under a carefully consider contract perhaps.
That would require one person to split the exe into a secret and a public part (more could be better, but technically one is enough). The problem is not the exe setup in itself (it's awesome), but the fact that the exe has code, which belongs in the DLL, such as the diplomacy screen, main menu etc.

Call to power 2 has published source code. It has some interesting conditions, such as demanding verification of purchased game (as in no removal of disc check). There were some issues with graphics and license and somebody ended up rewriting parts of the graphics engine to work with a free library instead of one, which wasn't released.

Actually what I would like the most would likely be something like the graphics engine to be rewritten to something like Unity, in which case we would be able to compile mods for mac and linux. Based on my experience, it is easier to attract good programmers if they can work on a natively in a linux system (no wine). However if rewriting the graphics engine can be avoided, I will go for that.

Maybe we should start a thread about this since it's getting off topic. What we mainly need is to figure out is how to figure out who to contact and how to contact the right people.
 
Maybe we should start a thread about this since it's getting off topic. What we mainly need is to figure out is how to figure out who to contact and how to contact the right people.
If/when you start a thread, send me a notification on it so I can be directed to it please. I'm interested in this. I'd love to see us get an opportunity to potentially upgrade the graphics system as well but I would NOT like to work on/through Linux.
 
There is a list of keywords to use in CvDllTranslator.cpp
PHP:
    aIconMap[L"[ICON_BULLET]"] = std::wstring(1, (wchar)gDLL->getSymbolID(BULLET_CHAR));
    aIconMap[L"[ICON_HAPPY]"] = std::wstring(1, (wchar)gDLL->getSymbolID(HAPPY_CHAR));
    aIconMap[L"[ICON_UNHAPPY]"] = std::wstring(1, (wchar)gDLL->getSymbolID(UNHAPPY_CHAR));
    aIconMap[L"[ICON_HEALTHY]"] = std::wstring(1, (wchar)gDLL->getSymbolID(HEALTHY_CHAR));
    aIconMap[L"[ICON_UNHEALTHY]"] = std::wstring(1, (wchar)gDLL->getSymbolID(UNHEALTHY_CHAR));
    aIconMap[L"[ICON_STRENGTH]"] = std::wstring(1, (wchar)gDLL->getSymbolID(STRENGTH_CHAR));
    aIconMap[L"[ICON_MOVES]"] = std::wstring(1, (wchar)gDLL->getSymbolID(MOVES_CHAR));
    aIconMap[L"[ICON_RELIGION]"] = std::wstring(1, (wchar)gDLL->getSymbolID(RELIGION_CHAR));
    aIconMap[L"[ICON_STAR]"] = std::wstring(1, (wchar)gDLL->getSymbolID(STAR_CHAR));
    aIconMap[L"[ICON_SILVER_STAR]"] = std::wstring(1, (wchar)gDLL->getSymbolID(SILVER_STAR_CHAR));
    aIconMap[L"[ICON_TRADE]"] = std::wstring(1, (wchar)gDLL->getSymbolID(TRADE_CHAR));
    aIconMap[L"[ICON_DEFENSE]"] = std::wstring(1, (wchar)gDLL->getSymbolID(DEFENSE_CHAR));
    aIconMap[L"[ICON_GREATPEOPLE]"] = std::wstring(1, (wchar)gDLL->getSymbolID(GREAT_PEOPLE_CHAR));
    aIconMap[L"[ICON_BAD_GOLD]"] = std::wstring(1, (wchar)gDLL->getSymbolID(BAD_GOLD_CHAR));
    aIconMap[L"[ICON_BAD_FOOD]"] = std::wstring(1, (wchar)gDLL->getSymbolID(BAD_FOOD_CHAR));
    aIconMap[L"[ICON_EATENFOOD]"] = std::wstring(1, (wchar)gDLL->getSymbolID(EATEN_FOOD_CHAR));
    aIconMap[L"[ICON_GOLDENAGE]"] = std::wstring(1, (wchar)gDLL->getSymbolID(GOLDEN_AGE_CHAR));
    aIconMap[L"[ICON_ANGRYPOP]"] = std::wstring(1, (wchar)gDLL->getSymbolID(ANGRY_POP_CHAR));
    aIconMap[L"[ICON_OPENBORDERS]"] = std::wstring(1, (wchar)gDLL->getSymbolID(OPEN_BORDERS_CHAR));
    aIconMap[L"[ICON_DEFENSIVEPACT]"] = std::wstring(1, (wchar)gDLL->getSymbolID(DEFENSIVE_PACT_CHAR));
    aIconMap[L"[ICON_MAP]"] = std::wstring(1, (wchar)gDLL->getSymbolID(MAP_CHAR));
    aIconMap[L"[ICON_OCCUPATION]"] = std::wstring(1, (wchar)gDLL->getSymbolID(OCCUPATION_CHAR));
    aIconMap[L"[ICON_POWER]"] = std::wstring(1, (wchar)gDLL->getSymbolID(POWER_CHAR));

    aIconMap[L"[ICON_GOLD]"] = std::wstring(1, (wchar)GC.getCommerceInfo(COMMERCE_GOLD).getChar());
    aIconMap[L"[ICON_RESEARCH]"] = std::wstring(1, (wchar)GC.getCommerceInfo(COMMERCE_RESEARCH).getChar());
    aIconMap[L"[ICON_CULTURE]"] = std::wstring(1, (wchar)GC.getCommerceInfo(COMMERCE_CULTURE).getChar());
    aIconMap[L"[ICON_ESPIONAGE]"] = std::wstring(1, (wchar)GC.getCommerceInfo(COMMERCE_ESPIONAGE).getChar());

    aIconMap[L"[ICON_FOOD]"] = std::wstring(1, (wchar)GC.getYieldInfo(YIELD_FOOD).getChar());
    aIconMap[L"[ICON_PRODUCTION]"] = std::wstring(1, (wchar)GC.getYieldInfo(YIELD_PRODUCTION).getChar());
    aIconMap[L"[ICON_COMMERCE]"] = std::wstring(1, (wchar)GC.getYieldInfo(YIELD_COMMERCE).getChar());
For instance food is used by adding [ICON_FOOD] to the text. You have likely seen [ICON_BULLET] quite a number of times.

Not all icons are accessible this way. Some use getChar on the info classes, like
PHP:
szTempBuffer = u",%s%d%c" %("+", iYield, gc.getYieldInfo(j).getChar() )
%s is a string, which is the first argument (here always +)
%d is a number, in this case the contents of iYield
%c is something from gamefont when used together with getChar(), in this case the icon for yield j.

This is the approach for
  • CvBonusInfo
  • CvCommerceInfo
  • CvYieldInfo
  • CvReligionInfo
  • CvCorporationInfo


EDIT: I can tell how it works technically as well, but I won't tell it unless somebody asked because it's not needed info unless you want to really do something advanced, like adding getChar to a new info class. Adding it here would likely just cause confusion.
 
There is a list of keywords to use in CvDllTranslator.cpp
PHP:
    aIconMap[L"[ICON_BULLET]"] = std::wstring(1, (wchar)gDLL->getSymbolID(BULLET_CHAR));
    aIconMap[L"[ICON_HAPPY]"] = std::wstring(1, (wchar)gDLL->getSymbolID(HAPPY_CHAR));
    aIconMap[L"[ICON_UNHAPPY]"] = std::wstring(1, (wchar)gDLL->getSymbolID(UNHAPPY_CHAR));
    aIconMap[L"[ICON_HEALTHY]"] = std::wstring(1, (wchar)gDLL->getSymbolID(HEALTHY_CHAR));
    aIconMap[L"[ICON_UNHEALTHY]"] = std::wstring(1, (wchar)gDLL->getSymbolID(UNHEALTHY_CHAR));
    aIconMap[L"[ICON_STRENGTH]"] = std::wstring(1, (wchar)gDLL->getSymbolID(STRENGTH_CHAR));
    aIconMap[L"[ICON_MOVES]"] = std::wstring(1, (wchar)gDLL->getSymbolID(MOVES_CHAR));
    aIconMap[L"[ICON_RELIGION]"] = std::wstring(1, (wchar)gDLL->getSymbolID(RELIGION_CHAR));
    aIconMap[L"[ICON_STAR]"] = std::wstring(1, (wchar)gDLL->getSymbolID(STAR_CHAR));
    aIconMap[L"[ICON_SILVER_STAR]"] = std::wstring(1, (wchar)gDLL->getSymbolID(SILVER_STAR_CHAR));
    aIconMap[L"[ICON_TRADE]"] = std::wstring(1, (wchar)gDLL->getSymbolID(TRADE_CHAR));
    aIconMap[L"[ICON_DEFENSE]"] = std::wstring(1, (wchar)gDLL->getSymbolID(DEFENSE_CHAR));
    aIconMap[L"[ICON_GREATPEOPLE]"] = std::wstring(1, (wchar)gDLL->getSymbolID(GREAT_PEOPLE_CHAR));
    aIconMap[L"[ICON_BAD_GOLD]"] = std::wstring(1, (wchar)gDLL->getSymbolID(BAD_GOLD_CHAR));
    aIconMap[L"[ICON_BAD_FOOD]"] = std::wstring(1, (wchar)gDLL->getSymbolID(BAD_FOOD_CHAR));
    aIconMap[L"[ICON_EATENFOOD]"] = std::wstring(1, (wchar)gDLL->getSymbolID(EATEN_FOOD_CHAR));
    aIconMap[L"[ICON_GOLDENAGE]"] = std::wstring(1, (wchar)gDLL->getSymbolID(GOLDEN_AGE_CHAR));
    aIconMap[L"[ICON_ANGRYPOP]"] = std::wstring(1, (wchar)gDLL->getSymbolID(ANGRY_POP_CHAR));
    aIconMap[L"[ICON_OPENBORDERS]"] = std::wstring(1, (wchar)gDLL->getSymbolID(OPEN_BORDERS_CHAR));
    aIconMap[L"[ICON_DEFENSIVEPACT]"] = std::wstring(1, (wchar)gDLL->getSymbolID(DEFENSIVE_PACT_CHAR));
    aIconMap[L"[ICON_MAP]"] = std::wstring(1, (wchar)gDLL->getSymbolID(MAP_CHAR));
    aIconMap[L"[ICON_OCCUPATION]"] = std::wstring(1, (wchar)gDLL->getSymbolID(OCCUPATION_CHAR));
    aIconMap[L"[ICON_POWER]"] = std::wstring(1, (wchar)gDLL->getSymbolID(POWER_CHAR));

    aIconMap[L"[ICON_GOLD]"] = std::wstring(1, (wchar)GC.getCommerceInfo(COMMERCE_GOLD).getChar());
    aIconMap[L"[ICON_RESEARCH]"] = std::wstring(1, (wchar)GC.getCommerceInfo(COMMERCE_RESEARCH).getChar());
    aIconMap[L"[ICON_CULTURE]"] = std::wstring(1, (wchar)GC.getCommerceInfo(COMMERCE_CULTURE).getChar());
    aIconMap[L"[ICON_ESPIONAGE]"] = std::wstring(1, (wchar)GC.getCommerceInfo(COMMERCE_ESPIONAGE).getChar());

    aIconMap[L"[ICON_FOOD]"] = std::wstring(1, (wchar)GC.getYieldInfo(YIELD_FOOD).getChar());
    aIconMap[L"[ICON_PRODUCTION]"] = std::wstring(1, (wchar)GC.getYieldInfo(YIELD_PRODUCTION).getChar());
    aIconMap[L"[ICON_COMMERCE]"] = std::wstring(1, (wchar)GC.getYieldInfo(YIELD_COMMERCE).getChar());
For instance food is used by adding [ICON_FOOD] to the text. You have likely seen [ICON_BULLET] quite a number of times.

Not all icons are accessible this way. Some use getChar on the info classes, like
PHP:
szTempBuffer = u",%s%d%c" %("+", iYield, gc.getYieldInfo(j).getChar() )
%s is a string, which is the first argument (here always +)
%d is a number, in this case the contents of iYield
%c is something from gamefont when used together with getChar(), in this case the icon for yield j.

This is the approach for
  • CvBonusInfo
  • CvCommerceInfo
  • CvYieldInfo
  • CvReligionInfo
  • CvCorporationInfo


EDIT: I can tell how it works technically as well, but I won't tell it unless somebody asked because it's not needed info unless you want to really do something advanced, like adding getChar to a new info class. Adding it here would likely just cause confusion.
GREAT post! I'd love to keep this post in a reference library. I was hoping that the 'like' feature on the forum would help me to build such a library but I can't see a way to get a list of all MY likes. I can see a list of all the likes on the posts I've made but what about the likes I'VE made? :( Maybe eventually eh? lol

Anyhow... great info! Thanks!
 
GREAT post! I'd love to keep this post in a reference library. I was hoping that the 'like' feature on the forum would help me to build such a library but I can't see a way to get a list of all MY likes. I can see a list of all the likes on the posts I've made but what about the likes I'VE made? :( Maybe eventually eh? lol
I have several times thought about writing a string guide, partly for reference for myself. Most modders are only using the tip of the iceberg because there are so many poorly documented features, if documented at all. There are stuff like text color and size, pedia links, plural (1 ship, 2 ships, where ship is the word written with a singular/plural [ ]) word gender and likely more. The problem is that with this massive amount of options, I can't remember how to use half of them without research even though I used them before. This really calls for a guide. The problem is that writing a proper guide is not a 5 minute job.

And you should post listing your likes in the forum forum. I would like your post to show support. It sounds useful :)
 
Back
Top Bottom