How do the Unique Improvements work?

It's in CvPlot.cpp in the source.

Spoiler :
Code:
void CvPlot::doImprovementUpgrade()
{
	if (getImprovementType() != NO_IMPROVEMENT)
	{
		ImprovementTypes eImprovementUpdrade = (ImprovementTypes)GC.getImprovementInfo(getImprovementType()).getImprovementUpgrade();
		if (eImprovementUpdrade != NO_IMPROVEMENT)
		{
			if (isBeingWorked() || GC.getImprovementInfo(eImprovementUpdrade).isOutsideBorders())
			{

//FfH: Modified by Kael 05/12/2008
//				changeUpgradeProgress(GET_PLAYER(getOwnerINLINE()).getImprovementUpgradeRate());
                if (isOwned())
                {
                    if (GC.getImprovementInfo(eImprovementUpdrade).getPrereqCivilization() == NO_CIVILIZATION ||
                      GC.getImprovementInfo(eImprovementUpdrade).getPrereqCivilization() == GET_PLAYER(getOwnerINLINE()).getCivilizationType())
                    {
                        changeUpgradeProgress(GET_PLAYER(getOwnerINLINE()).getImprovementUpgradeRate());
                    }
                    if (GC.getImprovementInfo(getImprovementType()).getPrereqCivilization() != NO_CIVILIZATION &&
                      GC.getImprovementInfo(getImprovementType()).getPrereqCivilization() != GET_PLAYER(getOwnerINLINE()).getCivilizationType())
                    {
                        setImprovementType((ImprovementTypes)GC.getImprovementInfo(getImprovementType()).getImprovementPillage());
                    }
                }
                else
                {
                    if (GC.getImprovementInfo(eImprovementUpdrade).getPrereqCivilization() == NO_CIVILIZATION)
                    {
                        changeUpgradeProgress(1);
                    }
                }
//FfH: End Modify

				if (getUpgradeProgress() >= GC.getGameINLINE().getImprovementUpgradeTime(getImprovementType()))
				{
					setImprovementType(eImprovementUpdrade);
				}
			}
		}
	}
}
 
Mailbox's answer would be for the Enclave, an upgrade to a Town which is unique to the Kuriotates. You could have also been inquiring about the commonly deemed "Unique Features" which are in fact "World Improvements." Those are handled elsewhere if that is what you were asking about instead.
 
Mailbox's answer would be for the Enclave, an upgrade to a Town which is unique to the Kuriotates. You could have also been inquiring about the commonly deemed "Unique Features" which are in fact "World Improvements." Those are handled elsewhere if that is what you were asking about instead.

Yeah, that's what I meant.
 
Those ones rely on the tag:

<bUnique>1</bUnique>

In ImprovementInfos. The chance of them being placed at the start of the game is set in GlobalDefinesAlt:

<DefineName>IMPROVEMENT_UNIQUE_CHANCE</DefineName>
<iDefineIntVal>30</iDefineIntVal>


Then in the SDK everyting is handled in CvMapGenerator.cpp with a new function:

Code:
void CvMapGenerator::addUniqueImprovements()
{
	if (gDLL->getPythonIFace()->pythonAddGoodies() && !gDLL->getPythonIFace()->pythonUsingDefaultImpl())
	{
		return;
	}

    bool bValid = true;
	CvPlot* pAdjacentPlot;
	CvPlot* pPlot;
	CvPlot* pBestPlot = NULL;
    int iBestValue = 0;
    int iValue = 0;
    int iChance = GC.getDefineINT("IMPROVEMENT_UNIQUE_CHANCE") + GC.getWorldInfo(GC.getMapINLINE().getWorldSize()).getUniqueFeatureChance();
/*************************************************************************************************/
/**	FeatureGalore						09/27/08									Xienwolf	**/
/**																								**/
/**																								**/
/*************************************************************************************************/
    if (GC.getGameINLINE().isOption(GAMEOPTION_ALL_UNIQUE_FEATURES))
        iChance = 100;
/*************************************************************************************************/
/**	FeatureGalore								END												**/
/*************************************************************************************************/
    for (int iI = 0; iI < GC.getNumImprovementInfos(); iI++)
    {
        if (GC.getImprovementInfo((ImprovementTypes)iI).isUnique())
        {
            iBestValue = 0;
            pBestPlot = NULL;
			if (GC.getGameINLINE().getSorenRandNum(100, "Unique Improvements") < iChance)
			{
                for (int iJ = 0; iJ < GC.getMapINLINE().numPlotsINLINE(); iJ++)
                {
                    pPlot = GC.getMapINLINE().plotByIndexINLINE(iJ);
                    if (pPlot->getBonusType(NO_TEAM) == NO_BONUS)
                    {
                        if (pPlot->getImprovementType() == NO_IMPROVEMENT)
                        {
                            bValid = true;
                            for (int iJ = 0; iJ < NUM_DIRECTION_TYPES; ++iJ)
                            {
                                pAdjacentPlot = plotDirection(pPlot->getX_INLINE(), pPlot->getY_INLINE(), ((DirectionTypes)iJ));
                                if (pAdjacentPlot != NULL)
                                {
                                    if (pAdjacentPlot->getImprovementType() != NO_IMPROVEMENT)
                                    {
                                        bValid = false;
                                    }
                                }
                            }
                        }
                    }
                    if (bValid)
                    {
                        if (pPlot->getImprovementType() == NO_IMPROVEMENT)
                        {
/*************************************************************************************************/
/**	Xienwolf Tweak							10/01/08											**/
/**																								**/
/**					Prevents Unique Features from overwriting each other						**/
/*************************************************************************************************/
/**								---- Start Original Code ----									**
                            if (pPlot->canHaveImprovement((ImprovementTypes)iI))
/**								----  End Original Code  ----									**/
		                    if (pPlot->canHaveImprovement((ImprovementTypes)iI) && pPlot->getImprovementType() == NO_IMPROVEMENT)
/*************************************************************************************************/
/**	Tweak									END													**/
/*************************************************************************************************/
                            {
                                if (pPlot->getBonusType(NO_TEAM) == NO_BONUS)
                                {
                                    iValue = GC.getGameINLINE().getSorenRandNum(10000, "Unique Improvements");
                                    if (iValue > iBestValue)
                                    {
                                        iBestValue = iValue;
                                        pBestPlot = pPlot;
                                    }
                                }
                            }
                        }
                    }
                }
                if (pBestPlot != NULL)
                {
                    pBestPlot->setImprovementType((ImprovementTypes)iI);
                    pBestPlot->setFeatureType(NO_FEATURE);
                }
			}
        }
    }
}

(ignore my personal changes in there, too lazy to find my copy of the base code)

This function is called earlier in the same .cpp by:

Code:
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: Added by Kael 10/04/2008
    if (!GC.getGameINLINE().isOption(GAMEOPTION_NO_UNIQUE_IMPROVEMENTS))
    {
        addUniqueImprovements();
    }
    if (!GC.getGameINLINE().isOption(GAMEOPTION_NO_LAIRS))
    {
        addImprovements();
    }
//FfH: End Add

	// Call for Python to make map modifications after it's been generated
	afterGeneration();
}
 
Back
Top Bottom