I have been really interested in playing around with culture lately. I find it among other things generally lacking in Vanilla COL, other things being victory conditions. So why not add a cultural victory condition and satisfy two needs at the same time?
In working on this, I figured out how to add an entirely new resource (which I am just going to call a YIELD from now on) via the SDK. What we are doing is essentially creating a new yield after the fashion of Bells and Crosses.
The game treats resources like Bells and Ore in basically the same way - generically called Yields. Because of this, you could use this method to add a new physical resource to the game. But I'm not sure if it would cause other problems, and of course you would have to go through all the trouble to add in the resource to the city management and Europe screens, diplomacy options, etc. So I am not going into that territory at all.
What I have created is simply a new yield that we can use as a metric to measure a phenomenon within the game, like Bells are used for rebel sentiment, crosses are used for immigration and education is used for ... whatever it is used for. (If Colonization were Family Guy, education would be Meg, methinks.) This is how I did it.
Here are the changes I made. You can see what I added as I named everything along the lines of FortuenteCulture to make it easy to find later.
CvEnums.h
The following code starts on line 609:
CyEnumsInterface.cpp
This code starts on line 365:
CvPlayer.h
This starts on line 765.
CvPlayer.cpp
You could do this differently with the same result, but this is how I did it:
There are two things to change in this file, first we need the Yield to do it's thing, so it is added to the turn here starting on line 2049:
Now we actually need the function doFortuenteCulture() to exist. I added it in right below the doCrosses() function which ends on line 8005:
You can see that currently my yield does nothing more than exist. But by adding the XML YIELD_FORTUENTECULTURE to units or buildings we can allow them to produce it. Eventually I want to find the best way to add in the values from doBells() and doCrosses() and the education one (which is in CvCity.cpp IIRC) and put them through a very simple formula to come up with a nice culture value. Whether this happens in doFortuenteCulture(), in Python or through XML I am not sure yet. Ideas are welcome!
After we compile the SDK DLL we now add in the Yield to the XML so we can play with it:
CIV4YieldInfos.xml
And that is basically it. I tested it last night and it all worked for me. I added YIELD_FORTUENTECULTURE as the base metric of culture and the yield produced by the Town Hall profession (statesman) (replacing YIELD_BELLS for both in GobalDefines.xml and CIV4ProfessionInfos.xml). Just as expected, the cultural boundaries of the city grew in a test game without producing any bells.
I am posting this because you can do all kinds of things with this. Me personally I am on a quest to make a better culture rating, but I am interested to see what others might want to use additional Yields for in the game.
In working on this, I figured out how to add an entirely new resource (which I am just going to call a YIELD from now on) via the SDK. What we are doing is essentially creating a new yield after the fashion of Bells and Crosses.
The game treats resources like Bells and Ore in basically the same way - generically called Yields. Because of this, you could use this method to add a new physical resource to the game. But I'm not sure if it would cause other problems, and of course you would have to go through all the trouble to add in the resource to the city management and Europe screens, diplomacy options, etc. So I am not going into that territory at all.
What I have created is simply a new yield that we can use as a metric to measure a phenomenon within the game, like Bells are used for rebel sentiment, crosses are used for immigration and education is used for ... whatever it is used for. (If Colonization were Family Guy, education would be Meg, methinks.) This is how I did it.
Here are the changes I made. You can see what I added as I named everything along the lines of FortuenteCulture to make it easy to find later.
CvEnums.h
Spoiler :
The following code starts on line 609:
Code:
enum DllExport YieldTypes
{
NO_YIELD = -1,
YIELD_FOOD,
YIELD_LUMBER,
YIELD_SILVER,
YIELD_COTTON,
YIELD_FUR,
YIELD_SUGAR,
YIELD_TOBACCO,
YIELD_ORE,
YIELD_CLOTH,
YIELD_COATS,
YIELD_RUM,
YIELD_CIGARS,
YIELD_TOOLS,
YIELD_MUSKETS,
YIELD_HORSES,
YIELD_TRADE_GOODS,
YIELD_HAMMERS,
YIELD_BELLS,
YIELD_CROSSES,
YIELD_EDUCATION,
[B]YIELD_FORTUENTECULTURE,[/B]
#ifdef _USRDLL
NUM_YIELD_TYPES
#endif
};
CyEnumsInterface.cpp
Spoiler :
This code starts on line 365:
Code:
python::enum_<YieldTypes>("YieldTypes")
.value("NO_YIELD", NO_YIELD)
.value("YIELD_FOOD", YIELD_FOOD)
.value("YIELD_LUMBER", YIELD_LUMBER)
.value("YIELD_SILVER", YIELD_SILVER)
.value("YIELD_COTTON", YIELD_COTTON)
.value("YIELD_FUR", YIELD_FUR)
.value("YIELD_SUGAR", YIELD_SUGAR)
.value("YIELD_TOBACCO", YIELD_TOBACCO)
.value("YIELD_ORE", YIELD_ORE)
.value("YIELD_CLOTH", YIELD_CLOTH)
.value("YIELD_COATS", YIELD_COATS)
.value("YIELD_RUM", YIELD_RUM)
.value("YIELD_CIGARS", YIELD_CIGARS)
.value("YIELD_TOOLS", YIELD_TOOLS)
.value("YIELD_MUSKETS", YIELD_MUSKETS)
.value("YIELD_HORSES", YIELD_HORSES)
.value("YIELD_TRADE_GOODS", YIELD_TRADE_GOODS)
.value("YIELD_HAMMERS", YIELD_HAMMERS)
.value("YIELD_BELLS", YIELD_BELLS)
.value("YIELD_CROSSES", YIELD_CROSSES)
.value("YIELD_EDUCATION", YIELD_EDUCATION)
[B].value("YIELD_FORTUENTECULTURE", YIELD_FORTUENTECULTURE)[/B]
.value("NUM_YIELD_TYPES", NUM_YIELD_TYPES)
;
Spoiler :
This starts on line 765.
Code:
void doGold();
void doBells();
void doCrosses();
[B]void doFortuenteCulture();[/B]
void doWarnings();
void doEvents();
void doPrices();
Spoiler :
You could do this differently with the same result, but this is how I did it:
There are two things to change in this file, first we need the Yield to do it's thing, so it is added to the turn here starting on line 2049:
Code:
void CvPlayer::doTurn()
{
PROFILE_FUNC();
CvCity* pLoopCity;
int iLoop;
FAssertMsg(isAlive(), "isAlive is expected to be true");
FAssertMsg(!hasBusyUnit() || GC.getGameINLINE().isMPOption(MPOPTION_SIMULTANEOUS_TURNS) || GC.getGameINLINE().isSimultaneousTeamTurns(), "End of turn with busy units in a sequential-turn game");
gDLL->getEventReporterIFace()->beginPlayerTurn( GC.getGameINLINE().getGameTurn(), getID());
doEra();
doUpdateCacheOnTurn();
GC.getGameINLINE().verifyDeals();
AI_doTurnPre();
AI_assignWorkingPlots();
doGold();
doBells();
doCrosses();
[B]doFortuenteCulture();[/B]
for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
{
pLoopCity->doTurn();
}
verifyCivics();
doPrices();
doEvents();
interceptEuropeUnits();
updateEconomyHistory(GC.getGameINLINE().getGameTurn(), getGold());
updateIndustryHistory(GC.getGameINLINE().getGameTurn(), calculateTotalYield(YIELD_HAMMERS));
updateAgricultureHistory(GC.getGameINLINE().getGameTurn(), calculateTotalYield(YIELD_FOOD));
updatePowerHistory(GC.getGameINLINE().getGameTurn(), getPower());
updateCultureHistory(GC.getGameINLINE().getGameTurn(), countTotalCulture());
expireMessages(); // turn log
m_aszTradeMessages.clear();
gDLL->getInterfaceIFace()->setDirty(CityInfo_DIRTY_BIT, true);
AI_doTurnPost();
gDLL->getEventReporterIFace()->endPlayerTurn( GC.getGameINLINE().getGameTurn(), getID());
FAssert(checkPower(false));
FAssert(checkPopulation());
Now we actually need the function doFortuenteCulture() to exist. I added it in right below the doCrosses() function which ends on line 8005:
Code:
void CvPlayer::doFortuenteCulture()
{
if (getParent() == NO_PLAYER)
{
return;
}
int iFortuenteCultureRate = getYieldRate(YIELD_FORTUENTECULTURE);
}
You can see that currently my yield does nothing more than exist. But by adding the XML YIELD_FORTUENTECULTURE to units or buildings we can allow them to produce it. Eventually I want to find the best way to add in the values from doBells() and doCrosses() and the education one (which is in CvCity.cpp IIRC) and put them through a very simple formula to come up with a nice culture value. Whether this happens in doFortuenteCulture(), in Python or through XML I am not sure yet. Ideas are welcome!
After we compile the SDK DLL we now add in the Yield to the XML so we can play with it:
CIV4YieldInfos.xml
Spoiler :
Add in:
Code:
<YieldInfo>
<Type>YIELD_FORTUENTECULTURE</Type>
<Description>TXT_KEY_YIELD_FORTUENTECULTURE</Description>
<Civilopedia>TXT_KEY_YIELD_FORTUENTECULTURE_PEDIA</Civilopedia>
<bCargo>0</bCargo>
<iBuyPriceLow>0</iBuyPriceLow>
<iBuyPriceHigh>0</iBuyPriceHigh>
<iSellPriceDifference>0</iSellPriceDifference>
<iPriceChangeThreshold>0</iPriceChangeThreshold>
<iPriceCorrectionPercent>0</iPriceCorrectionPercent>
<iNativeBuyPrice>-1</iNativeBuyPrice>
<iNativeSellPrice>-1</iNativeSellPrice>
<iNativeConsumptionPercent>-1</iNativeConsumptionPercent>
<iNativeHappy>0</iNativeHappy>
<iHillsChange>0</iHillsChange>
<iPeakChange>0</iPeakChange>
<iLakeChange>0</iLakeChange>
<iCityChange>0</iCityChange>
<iMinCity>0</iMinCity>
<iAIWeightPercent>100</iAIWeightPercent>
<iAIBaseValue>5</iAIBaseValue>
<iNativeBaseValue>0</iNativeBaseValue>
<iPower>0</iPower>
<iAsset>0</iAsset>
<ColorType>COLOR_YIELD_FOOD</ColorType>
<UnitClass>NONE</UnitClass>
<iTextureIndex>-1</iTextureIndex>
<iWaterTextureIndex>-1</iWaterTextureIndex>
<Icon>,Art/Interface/Buttons/Unit_Resource_Colonization_Atlas.dds,8,16</Icon>
<HighlightIcon>,Art/Interface/Screens/City_Management/Colonization_Yield_Highlight_Icon_Atlas.dds.dds,2,16</HighlightIcon>
<Button>,Art/Interface/Buttons/Unit_Resource_Colonization_Atlas.dds,2,16</Button>
</YieldInfo>
And that is basically it. I tested it last night and it all worked for me. I added YIELD_FORTUENTECULTURE as the base metric of culture and the yield produced by the Town Hall profession (statesman) (replacing YIELD_BELLS for both in GobalDefines.xml and CIV4ProfessionInfos.xml). Just as expected, the cultural boundaries of the city grew in a test game without producing any bells.
I am posting this because you can do all kinds of things with this. Me personally I am on a quest to make a better culture rating, but I am interested to see what others might want to use additional Yields for in the game.