Quick Modding Questions Thread

Is there some maximum on the amount of bonuses allowed in a game?

I've been unable to load a mod, that crashes while loading the fonts, and have looked through the Alpha Channels (Went over the lines with black, checked that I had the right lines, etc. Have added bonus things to these files a couple times before, so have a general sense of what to do). It is above 64 bonuses at this point, and I vaguely remember reading somewhere about a limit, so was curious if this may be the problem.
 
Yes, afaik there is a limit of 64 bonuses because there are no more "slots" for the bonus icons in the game font files. There's a way around this, though, but I'm not sure where I saw it. Maybe in the tutorial section?
 
Yes, I remember seeing a thread with some posts about that. Am having a lot of trouble finding it, though.

Thanks for the answer.

Another question: I read the display for yields on terrain occurs in the executable rather than any of the files we can change, but is there any way to influence the display? (I'm thinking of modding in some fractional yields, using the "work in 100's, than divide by 100" method, but wouldn't want a bunch of really big icons showing up on the display of the resources.)
 
I remember someone was able to add another yield type and display it in the city screen, maybe that's a good start.
 
Hi

I'm playing RevDCM and I want to make a small change to the ai to address something I see as a weakness in the ai's play. The situation is where the Ethiopians say, have just captured a couple of cities off the French and have made them a vassal. In this situation a human player may well just liberate the captured cities back to the French rather than try and deal with the inevitable revolution problems. This then frees your army to go off and attack someone else. However the computer always stubbornly tries to hold onto them, often resulting in a revolution and a renewed war against someone he has already beaten.

So I want the ai to do a common sense check once it's made someone a vassal, that basically asks 'have I captured any cities'? If so, am I better off liberating those cities to my vassal? So the check could be for example if any of the cities have >75% nationality of the vassal, and are much further away than the average of ai's main cities. If the answer is yes to both, then the Ethiopians would just liberate the cities straight away, rather than get into an endless cycle of revolutions and war.

I think this would improve the ai's standard of play. Would such a check be easy to insert? Can anyone give me any pointers as to what code I would need to insert and where? I presume it would slot somewhere in CvPlayerAI?

For context, after reading some of excellent guides on this website, I can just about create a new dll, but I'm struggling with writing code and working out how to fix the above problem.

Thanks in advance for any advice.
 
I don't believe Asaf's method altered reading over plots with mouseover. If I remember correctly that was a slight bug.
 
I'm playing with the 50 Civ dll and really enjoying it except for one thing. Every city I capture there culture gets wiped out and a nearby civs culture completely overtakes it. There was only enough room for like 2 cities for each civ on this map. So capital cities are all pretty close.

Anyway I'm having to go to war with every civ next to last civ I just took there city just to get some workable tiles.

What I want to know is, is there an option in one of the XML files that controls the amount of culture lost when you conquer a city? I want to change it so maybe you gain like half the culture or so from the conquered city at the end of the rebellion period or just enough to have all the tiles around you workable, if they were to begin with when the original city controlled it.
 
And one more thing really irked me. The diplomacy in this game seems really out of whack which is why I really don't even bother but I've really been trying with this last game since I put on higher difficulty and permanent ally option.

Basically is I've been helping this Civ with everything and anything he asks. Gone to war twice for him and I'm his same religion. I've got 13 positive points and one negative from initial random setting. All I wanted him to do was break his trading with a Civ he doesn't even like. Is -1 with that Civ and yet it's not even an option. It's red and says "I could never betray my close friends!!!" That's ridiculous to me. He's got 1 trade to him besides the open borders and let's this guy march all thru his lands to attack his real closest friend and war ally.
 
Hi

So I want the ai to do a common sense check once it's made someone a vassal, that basically asks 'have I captured any cities'? If so, am I better off liberating those cities to my vassal? So the check could be for example if any of the cities have >75% nationality of the vassal, and are much further away than the average of ai's main cities. If the answer is yes to both, then the Ethiopians would just liberate the cities straight away, rather than get into an endless cycle of revolutions and war.

I think this would improve the ai's standard of play. Would such a check be easy to insert? Can anyone give me any pointers as to what code I would need to insert and where? I presume it would slot somewhere in CvPlayerAI?

For context, after reading some of excellent guides on this website, I can just about create a new dll, but I'm struggling with writing code and working out how to fix the above problem.

Thanks in advance for any advice.
Hi Gorilla,
One of the most difficult parts of SDK modding is finding exactly where to put your new code. I think CvPlayerAI is the right place to start and possibly CvCityAI. Once you find the right place to put your code it should be easy.

My advice would be to first look at the header files of the files you suspect to be the right ones (so look first at CvPlayerAI.h instead of CvPlayerAI.cpp). In the header file you will be able to see the names of the functions in the .cpp file. You can usually guess what a function does from its name, so look for some functions that sound like what you want. Then go check the .cpp file to see if the function does what you suspect.
 
Freshwater lakes are all lakes under a certain size, although I can't remember what size.
 
Hi Gorilla,
One of the most difficult parts of SDK modding is finding exactly where to put your new code. I think CvPlayerAI is the right place to start and possibly CvCityAI. Once you find the right place to put your code it should be easy.

My advice would be to first look at the header files of the files you suspect to be the right ones (so look first at CvPlayerAI.h instead of CvPlayerAI.cpp). In the header file you will be able to see the names of the functions in the .cpp file. You can usually guess what a function does from its name, so look for some functions that sound like what you want. Then go check the .cpp file to see if the function does what you suspect.

Thanks Red Key, it's encouraging that you think the code will be easy!

I think that the best place for the code will be where the computer evaluates what trade options it is considering for that turn. That way this 'common sense' check will be done each turn and will still work if the AI captures a city off a third party which would be more appropriate to liberate to its vassal.

Having looked through the source files, I can find two references to trade city in CvPlayerAI and CvPlayer respectively

Spoiler :
case TRADE_CITIES:
pCity = GET_PLAYER(ePlayer).getCity(pNode->m_data.m_iData);
if (pCity != NULL)
{
iValue += AI_cityTradeVal(pCity);
}
break;


Spoiler :
case TRADE_CITIES:
{
CvCity* pCity = NULL;
if (bOffer)
{
pCity = GET_PLAYER(eOtherPlayer).getCity(zTradeData.m_iData);
}
else
{
pCity = getCity(zTradeData.m_iData);
}
if (NULL != pCity)
{
if (pCity->getLiberationPlayer(false) == eOtherPlayer)
{
szString.Format(L"%s (%s)", pCity->getName().GetCString(), gDLL->getText("TXT_KEY_LIBERATE_CITY").GetCString());
}
else
{
szString = gDLL->getText("TXT_KEY_CITY_OF", pCity->getNameKey());
}
}
}
break;


The other file using liberate city is CvCity, which has the following code:

Spoiler :
void CvCity::liberate(bool bConquest)
{
CvPlot* pPlot = plot();
PlayerTypes ePlayer = getLiberationPlayer(bConquest);
PlayerTypes eOwner = getOwnerINLINE();

if (NO_PLAYER != ePlayer)
{
int iOldOwnerCulture = getCultureTimes100(eOwner);
int iOldMasterLand = 0;
int iOldVassalLand = 0;
if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isVassal(GET_PLAYER(eOwner).getTeam()))
{
iOldMasterLand = GET_TEAM(GET_PLAYER(eOwner).getTeam()).getTotalLand();
iOldVassalLand = GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getTotalLand(false);
}

CvWString szBuffer = gDLL->getText("TXT_KEY_MISC_CITY_LIBERATED", getNameKey(), GET_PLAYER(eOwner).getNameKey(), GET_PLAYER(ePlayer).getCivilizationAdjectiveKey());
for (int iI = 0; iI < MAX_PLAYERS; ++iI)
{
if (GET_PLAYER((PlayerTypes)iI).isAlive())
{
if (isRevealed(GET_PLAYER((PlayerTypes)iI).getTeam(), false))
{
gDLL->getInterfaceIFace()->addMessage(((PlayerTypes)iI), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_REVOLTEND", MESSAGE_TYPE_MAJOR_EVENT, ARTFILEMGR.getInterfaceArtInfo("WORLDBUILDER_CITY_EDIT")->getPath(), (ColorTypes)GC.getInfoTypeForString("COLOR_HIGHLIGHT_TEXT"), getX_INLINE(), getY_INLINE(), true, true);
}
}
}
GC.getGameINLINE().addReplayMessage(REPLAY_MESSAGE_MAJOR_EVENT, eOwner, szBuffer, getX_INLINE(), getY_INLINE(), (ColorTypes)GC.getInfoTypeForString("COLOR_HIGHLIGHT_TEXT"));

GET_PLAYER(ePlayer).acquireCity(this, false, true, true);
GET_PLAYER(ePlayer).AI_changeMemoryCount(eOwner, MEMORY_LIBERATED_CITIES, 1);

if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isVassal(GET_PLAYER(eOwner).getTeam()))
{
int iNewMasterLand = GET_TEAM(GET_PLAYER(eOwner).getTeam()).getTotalLand();
int iNewVassalLand = GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getTotalLand(false);

GET_TEAM(GET_PLAYER(ePlayer).getTeam()).setMasterPower(GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getMasterPower() + iNewMasterLand - iOldMasterLand);
GET_TEAM(GET_PLAYER(ePlayer).getTeam()).setVassalPower(GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getVassalPower() + iNewVassalLand - iOldVassalLand);
}

if (NULL != pPlot)
{
CvCity* pCity = pPlot->getPlotCity();
if (NULL != pCity)
{
pCity->setCultureTimes100(ePlayer, pCity->getCultureTimes100(ePlayer) + iOldOwnerCulture / 2, true, true);
}

if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isAVassal())
{
for (int i = 0; i < GC.getDefineINT("COLONY_NUM_FREE_DEFENDERS"); ++i)
{
pCity->initConscriptedUnit();
}
}
}
}
}

PlayerTypes CvCity::getLiberationPlayer(bool bConquest) const
{
if (isCapital())
{
return NO_PLAYER;
}

for (int iPlayer = 0; iPlayer < MAX_CIV_PLAYERS; ++iPlayer)
{
CvPlayer& kLoopPlayer = GET_PLAYER((PlayerTypes)iPlayer);
if (kLoopPlayer.isAlive() && kLoopPlayer.getParent() == getOwnerINLINE())
{
CvCity* pLoopCapital = kLoopPlayer.getCapitalCity();
if (NULL != pLoopCapital)
{
if (pLoopCapital->area() == area())
{
return (PlayerTypes)iPlayer;
}
}
}
}

CvPlayer& kOwner = GET_PLAYER(getOwnerINLINE());
if (kOwner.canSplitEmpire() && kOwner.canSplitArea(area()->getID()))
{
PlayerTypes ePlayer = GET_PLAYER(getOwnerINLINE()).getSplitEmpirePlayer(area()->getID());

if (NO_PLAYER != ePlayer)
{
if (GET_PLAYER(ePlayer).isAlive())
{
return ePlayer;
}
}
}

PlayerTypes eBestPlayer = NO_PLAYER;
int iBestValue = 0;

int iTotalCultureTimes100 = countTotalCultureTimes100();

for (int iPlayer = 0; iPlayer < MAX_CIV_PLAYERS; ++iPlayer)
{
CvPlayer& kLoopPlayer = GET_PLAYER((PlayerTypes)iPlayer);

if (kLoopPlayer.isAlive())
{
if (kLoopPlayer.canReceiveTradeCity())
{
CvCity* pCapital = kLoopPlayer.getCapitalCity();
if (NULL != pCapital)
{
int iCapitalDistance = ::plotDistance(getX_INLINE(), getY_INLINE(), pCapital->getX_INLINE(), pCapital->getY_INLINE());
if (area() != pCapital->area())
{
iCapitalDistance *= 2;
}

int iCultureTimes100 = getCultureTimes100((PlayerTypes)iPlayer);

if (bConquest)
{
if (iPlayer == getOriginalOwner())
{
iCultureTimes100 *= 3;
iCultureTimes100 /= 2;
}
}

if (GET_PLAYER((PlayerTypes)iPlayer).getTeam() == getTeam()
|| GET_TEAM(GET_PLAYER((PlayerTypes)iPlayer).getTeam()).isVassal(getTeam())
|| GET_TEAM(getTeam()).isVassal(GET_PLAYER((PlayerTypes)iPlayer).getTeam()))
{
iCultureTimes100 *= 2;
iCultureTimes100 = (iCultureTimes100 + iTotalCultureTimes100) / 2;
}

int iValue = std::max(100, iCultureTimes100) / std::max(1, iCapitalDistance);

if (iValue > iBestValue)
{
iBestValue = iValue;
eBestPlayer = (PlayerTypes)iPlayer;
}
}
}
}
}

if (NO_PLAYER != eBestPlayer)
{
if (getOwnerINLINE() == eBestPlayer)
{
return NO_PLAYER;
}

for (int iPlot = 0; iPlot < NUM_CITY_PLOTS; ++iPlot)
{
CvPlot* pLoopPlot = ::plotCity(getX_INLINE(), getY_INLINE(), iPlot);

if (NULL != pLoopPlot)
{
if (pLoopPlot->isVisibleEnemyUnit(eBestPlayer))
{
return NO_PLAYER;
}
}
}
}

return eBestPlayer;
}


This seems to be doing the mechanics of the liberation and working out who you can liberate to, rather than whether the ai actually wants to liberate in the first place.

I'm struggling to understand the trade mechanics. Just because a computer can trade something, does that mean that it will? Also, the fact that there is no 'liberate city' bit under the trade city section in CvPlayerAI, does this mean that currently the computer would never consider liberating a city?

Thanks again for any help.

Gorilla
 
In the DLL, the function plotByIndexINLINE returns the plot at a certain index. How would one go about doing the opposite- given a plot, get its index?
 
In the DLL, the function plotByIndexINLINE returns the plot at a certain index. How would one go about doing the opposite- given a plot, get its index?

Given a plot you can call getX_INLINE and getY_INLINE. This is in CvPlot.cpp. I think that is what you want.
 
I'm aware of that but that doesn't give me the index. The index is the location of the plot in the array of plots in the CvMap class.
 
In the CIV4WorldInfo.xml file there are a couple lines that seem to relate to city maintenance costs. I tried searching for information on the site/forums but was unable to find an exact explanation of what each modifies. Any help would be appreciated. The two lines are:

<iDistanceMaintenancePercent>
<iNumCitiesMaintenancePercent>
 
In the CIV4WorldInfo.xml file there are a couple lines that seem to relate to city maintenance costs. I tried searching for information on the site/forums but was unable to find an exact explanation of what each modifies. Any help would be appreciated. The two lines are:

<iDistanceMaintenancePercent>
<iNumCitiesMaintenancePercent>


These are both multiplying factors that change the amount of maintenance you pay in each city. If you look in worldinfo.xml, you will find another set of tags with the same name, which vary depending on the size of the map. These are multiplied together for each city.

So for example if you had iNumCitiesMaintenancePercent = 100% on each (note that all the values in world info are less than this - I'm just using this number for demonstration), then you would get

100% * 100% = 1gp per city in each city. So your maintenance varies depending on how many cities you have

1 city = 1gp (total 1)
2 cities = 2gp in each city (total 4)
3 cities = 3gp in each city (total 9)
etc.

As you can see it goes up quite quickly if you have 100% on each! Note that it also varies slightly depending on the size of the city (the value of the maintenance in any given city will double by the time you reach size 18).

Distance maintenance is similar except that instead of the number of cities it is obviously driven by the distance from capital (or forbidden palace if that's closer). Distance maintenance is also affected by the size of the city, although the effect is slightly stronger here (doubles by 9).
 
A number of questions I have about Civ 4 modding.

1. Is it possible to put a maximum limit on how much experience units can gain from combat? (Such that for example a unit can gain up to 50 points, but no more)

2. Is it possible to make resources in Civ4 quantitative? (like how it is in Civ5). Such that a resource would have 3 or 10 or 100 of it in one tile, and they'd be used per unit or something, as opposed to having 1 resource provide for your entire nation no matter how big you are. (I understand this likely requires SDK modding, and that's fine, just wondering if its possible.)

3. Is it possible to change golden ages so that a GA gives a % boost to gold and hammer production as opposed to adding 1 to existing tiles?

4. Is it possible to add additional "yield types"? so, other than food, gold, and hammers, getting a new type of yield into the game.


Thanks for any feedback.
 
Back
Top Bottom