cfkane
May 12, 2008, 12:01 PM
I'm having trouble figuring out how it was programmed; I was hoping to something similar in one of my own mods. How can I create an improvement generated at the start of the game, by the computer, that only occurs once on the map?
MagisterCultuum
May 12, 2008, 12:45 PM
To make it only occur once set <bUnique> to 1
Setting <bPermanent> to 1 may be a good idea too.
I'm not really sure what determines if an improvement will be placed, but it seems that any improvement I add will be randomly placed on the terrains found in <TerrainMakesValids>
Kael
May 12, 2008, 01:21 PM
The real work is all done in CVMapGenerator.cpp. First an addition to CvMapGenerator::addGameElements() where the bolded part is the only part that applies to adding unique improvements:
void CvMapGenerator::addGameElements()
{
addRivers();
gDLL->logMemState("CvMapGen after add rivers");
addLakes();
gDLL->logMemState("CvMapGen after add lakes");
addFeatures();
gDLL->logMemState("CvMapGen after add features");
addBonuses();
gDLL->logMemState("CvMapGen after add bonuses");
addGoodies();
gDLL->logMemState("CvMapGen after add goodies");
//FfH Improvements: Added by Kael 08/07/2007
if (!GC.getGameINLINE().isOption(GAMEOPTION_NO_LAIRS) )
{
addImprovements();
}
if (!GC.getGameINLINE().isOption(GAMEOPTION_NO_UNIQUE _IMPROVEMENTS))
{
addUniqueImprovements();
}
if (GC.getGameINLINE().isOption(GAMEOPTION_BARBARIAN_ WORLD))
{
for (int iI = 0; iI < MAX_PLAYERS; iI++)
{
if (GET_PLAYER((PlayerTypes)iI).isAlive() && iI != BARBARIAN_PLAYER)
{
GC.getGameINLINE().foundBarbarianCity();
}
}
}
//FfH: End Add
// Call for Python to make map modifications after it's been generated
afterGeneration();
}
Then the addition of the addUniqueImprovements() function that it calls:
void CvMapGenerator::addUniqueImprovements()
{
CvPlot* pPlot;
int iBestValue = 0;
int iValue = 0;
int iChance = GC.getDefineINT("IMPROVEMENT_UNIQUE_CHANCE") + GC.getWorldInfo(GC.getMapINLINE().getWorldSize()). getUniqueFeatureChance();
CvPlot* pBestPlot = NULL;
for (int iI = 0; iI < GC.getNumImprovementInfos(); iI++)
{
if (GC.getImprovementInfo((ImprovementTypes)iI).isUni que())
{
iBestValue = 0;
pBestPlot = NULL;
if (GC.getGameINLINE().getMapRandNum(100, "Unique Improvements") < iChance)
{
for (int iJ = 0; iJ < GC.getMapINLINE().numPlotsINLINE(); iJ++)
{
pPlot = GC.getMapINLINE().plotByIndexINLINE(iJ);
FAssert(pPlot != NULL);
if (pPlot->canHaveImprovement((ImprovementTypes)iI))
{
if (pPlot->getBonusType(NO_TEAM) == NO_BONUS)
{
iValue = GC.getGameINLINE().getMapRandNum(10000, "Unique Improvements");
if (iValue > iBestValue)
{
iBestValue = iValue;
pBestPlot = pPlot;
}
}
}
}
if (pBestPlot != NULL)
{
pBestPlot->setImprovementType((ImprovementTypes)iI);
if (GC.getImprovementInfo((ImprovementTypes)iI).getSp awnUnitType() != NO_UNIT)
{
if (!GC.getGameINLINE().isOption(GAMEOPTION_NO_BARBAR IANS))
{
GET_PLAYER(BARBARIAN_PLAYER).initUnit(((UnitTypes) GC.getImprovementInfo((ImprovementTypes)iI).getSpa wnUnitType()), pBestPlot->getX(), pBestPlot->getY());
}
}
}
}
}
}
}
Basically it goes through each of the unique improvements, and if it finds one it has a chance equal to the IMPROVEMENT_UNIQUE_CHANCE definition of spawning that unique improvement somewhere on the map.
Incidently you wouldnt need the last part of that function that spawns defined units on unique features unless you want barb units to start on them as we have in FfH.
Hopefully that helps.
cfkane
May 12, 2008, 05:06 PM
That helps some, but I'm still having a bit of trouble reading python script. I may be doing a mod that out of my skill level right now.
Vehem
May 12, 2008, 06:03 PM
That helps some, but I'm still having a bit of trouble reading python script.
I'm not surprised - that's C++ :D
(it's handled in the DLL)
---
That aside - there are probably simple ways to implement the same thing in Python - it's just not as neat. Rough method;
1. Define some improvements in XML and make sure they're unbuildable.
2. Add code to "OnGameStart" in Python to find a valid place to put the improvements and then create one;
pPlot.setImprovementType(gc.getInfoTypeForString(' IMPROVEMENT_GRAND_CANYON'))
The code for the first part very much depends on where you want the improvements to appear...