Ok, yes, all the problems I ran into were Civcraft: SC related. So, this should work for Civ4, although I haven't
really tested it in a normal Civ4 environment.
Under Civ4, any unit can be upgraded to any other unit if there exists a "path" of upgrades. Thus, a warrior can in one turn upgrade to a Mech Infantry, because there exists a path...
Warrior->Spearman->Pikeman->Rifleman->Infantry->Mech Inf.
Typically, the disadvantage to this is that it costs a ton of money. But perhaps you want to make it even tougher, by forcing the player to only be able to upgrade a few rungs up the ladder at a time.
Code:
bool CvUnit::upgradeAvailable(UnitTypes eFromUnit, UnitClassTypes eToUnitClass, int iCount) const
{
UnitTypes eLoopUnit;
int iI;
[b]/* Modifed by Gerikes to disable recursive upgrade*/[/b]
[b]//[/b]if (iCount > GC.getNumUnitClassInfos())
[b]if (iCount > 0)[/b]
[b]/* End Modifed by Gerikes to disable recursive upgrade*/[/b]
{
return false;
}
if (GC.getUnitInfo(eFromUnit).getUpgradeUnitClass(eToUnitClass))
{
return true;
}
for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
{
if (GC.getUnitInfo(eFromUnit).getUpgradeUnitClass(iI))
{
eLoopUnit = ((UnitTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(iI)));
if (eLoopUnit != NO_UNIT)
{
if (upgradeAvailable(eLoopUnit, eToUnitClass, (iCount + 1))) [b]// Recursive call[/b]
{
return true;
}
}
}
}
return false;
}
This function is a
recursive function. That means that during the course of running through the code, the function will actually call
itself. This is important to realize for what we're doing.
When the function is first called, the eFromUnit value (say, UNIT_WARRIOR) and the eToUnitClass value (say, UNITCLASS_SAM_INFANTRY) are passed in, along with the number for iCount (by default, 0). In the first run, there is a check to see if the unit can upgrade to the unitclass only by checking it's upgrades. This would return true if eToUnitClass were, say, a Spearman or Axeman. But it's not, so it's false.
What happens next is that big for-loop mess will check every single unitclass that the warrior CAN upgrade to all by itself. It will then, for each one, call the function upgradeAvailable AGAIN, only this time using the new eFromUnit (say, a Spearman), the same eToUnitClass, and an incremented count.
If you're not familar with recursive functions, the next sentence may not make sense, but trust me on it. For every "hop" on the upgrade path the unit has to make to get to it's destination, iCount will increase. Thus, by checking what iCount is at the beginning of each function, you can control how far you're willing to search the "path" of upgrades.
By changing that first if-block, I'm changing how far I'm allowing the recursive function to dive. In this case, where I check iCount for 0, it will allow through the first pass, checking all of the Warriors "direct" upgrades. But, during the recursive calls, while trying to check all the upgrades from the spearman, axeman, etc., iCount will be incremented to one, which is greater than zero, so it will fail, and return false.
The moral of this story, is that you can control the depth of how far you can "search" the tree to upgrade. Rather than making it a magic number, you can make it a define:
Code:
[b]/* Modifed by Gerikes to change recursive upgrade max depth*/[/b]
[b]//[/b]if (iCount > GC.getNumUnitClassInfos())
[b]if (iCount >= GC.getDefineINT("MAX_UPGRADE_DEPTH"))[/b]
[b]/* End Modifed by Gerikes to change recursive upgrade max depth*/[/b]
Now, you can set a variable in the XML to define how far an upgrade can go. Note I changed the ">" to a ">=". Now, a value of 0 will disable upgrades, a value of 1 will allow upgrades of depth 1, a value of 5 will allow upgrades up to depth 5.