Automatic unit upgrade

Chrill

Chieftain
Joined
Aug 19, 2002
Messages
26
Location
Sweden
I want a function that works pretty much like the Leonardo Workshop in civ2, that is a building that automatically upgrades "old" units to newer ones (following the unitupgrade chart of course), seems like it should work in python alright. Been looking through the API and this forum but I've come up with a good way to do it... Can anyone assist?
 
Automatic upgrades are problematic, since certain units have multiple upgrade options. Which would it pick?

On the other hand, having the wonder simply reduce the cost to zero works, since you still have to decide to do the upgrade.

Several mods with it :
http://forums.civfanatics.com/downloads.php?do=file&id=11090 (only reduces by 50%, but trivial to make a 100% reduction)

http://forums.civfanatics.com/downloads.php?do=file&id=8439 (A rather weird version that only occasionally provides free upgrades)

http://forums.civfanatics.com/downloads.php?do=file&id=4524 (A collection of wonders from previous civs that aren't in CIV4, Leo here is also only 50% but again that can be changed).
 
Another problem with automatic upgrades is that most people keep their SuperMedic unit weak so that it never gets picked to defend the stack.

I would prefer to see 50% upgrade cost rather than totally free as well. Free is unrealistic and overpowered IMHO.
 
Well the thing is i just want certain units to upgrade not every combatclass, and one time. The easist thing as said is just to automatically provide a building in every city that gives a promotion that gives reduces cost. However I really want to make sure that certain units gets "upgraded" right away skipping the upgradecost thingy, it's just not for the sake of it :)

But i'm i completly wrong to asume that i have to kill the unit, save the stats and then just spawn a new unit with the same stats? Is there perhaps a more simple solution to it?
 
But i'm i completly wrong to asume that i have to kill the unit, save the stats and then just spawn a new unit with the same stats? Is there perhaps a more simple solution to it?

Wow, you can do everything related to upgrades on CyUnit (get the price, check if it's possible), but you can't actually do the upgrade. :( Yes, you'll need to implement CvUnit::upgrade() from the SDK in Python.
 
If you are only using Python, you could use CyUnit.convert(pUnit) to simplify the problem. You still need to create a new unit, but the convert method handles most of the dirty work of giving the new unit the same stats as the old one.
 
I have implemented several special effects using pUnit.convert() and there is one thing to watch out for. The straightforward code to write is to loop some list of units, find units to convert, convert the new unit and then kill the old unit. This is not recommended; you are altering the list you are iterating by adding and subtracting units.

Instead, iterate the unit list and build yourself a local list of units which require conversion. Then after you are done with the iteration, go back and convert/kill the units.

Regarding upgrade costs, it may be obvious, but there is a handy function in CvGameUtils called getUpgradePriceOverride. You can do anything you want here, such as dynamically changing the upgrade cost. I am not sure if you were already using this mechanism but it seems simpler than adding dummy buildings.
 
Thanks for the info concerning pUnit.convert(). Currently I only use it on one unit at a time, but I'll keep that in mind.
 
ok i found a quite easy way to autoupgrade the Settler unit to a Colonist unit (main reason for doing so is that the colonist unit adds buildings when settling, a fact that the AI would never actually bother to upgrade the unit...)

One problem is that I can't seem to get a proper way to replace the newly created unit on the same tile as any previous unit...So i simply set the tile to the capital... If anyone knew a way around this I'd be grateful :)

the code is currently under onTechAcquired in CvEventManager.py

Code:
		pTeam = gc.getTeam(iTeam)
		if pTeam.isHasTech(gc.getInfoTypeForString('TECH_OPTICS')):
			pPlayer = gc.getPlayer(iPlayer)
			plot = pPlayer.getCapitalCity().plot()
			iSettlers = gc.getInfoTypeForString("UNIT_SETTLER")
			iSettlerUnits = pPlayer.getUnitClassCount(iSettlers)
			iNewUnitType = CvUtil.findInfoTypeNum(gc.getUnitInfo, gc.getNumUnitInfos(), 'UNIT_COLONIST')
			# for all units of type X
			for i in range(iSettlerUnits):
				pPlayer.initUnit(iNewUnitType, plot.getX(), plot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.NO_DIRECTION)
				# effect for all units of type X ; kill them off one by one ...
			(loopUnit, iter) = pPlayer.firstUnit(false)
			while (loopUnit):
				if loopUnit.getUnitClassType() == iSettlers:
					loopUnit.kill(false, -1)
				(loopUnit, iter) = pPlayer.nextUnit(iter, false)
 
Here's your function rewritten. Note that I fixed a few other issues in it so replace the whole thing you posted with what I posted.

  • False instead of false
  • getInfoTypeForString instead of CvUtil.findInfoType()
  • UNITCLASS_SETTLER instead of UNIT_SETTLER
Also, this will break if any civilization has a UU replacement for the colonist which you probably won't have.

Code:
		pTeam = gc.getTeam(iTeam)
		if pTeam.isHasTech(gc.getInfoTypeForString('TECH_OPTICS')):
			pPlayer = gc.getPlayer(iPlayer)
			iSettlerClass = gc.getInfoTypeForString("UNITCLASS_SETTLER")
			iNewUnitType = gc.getInfoTypeForString("UNIT_COLONIST")
			iSettlerUnits = pPlayer.getUnitClassCount(iSettlerClass)
			if iSettlerUnits > 0:
				lPlots = []
				(loopUnit, iter) = pPlayer.firstUnit(False)
				# kill off old units but keep track of x,y positions
				while (loopUnit):
					if loopUnit.getUnitClassType() == iSettlerClass:
						lPlots.append((loopUnit.getX(), loopUnit.getY()))
						loopUnit.kill(False, -1)
					(loopUnit, iter) = pPlayer.nextUnit(iter, False)
				# create replacements
				for x, y in lPlots:
					pPlayer.initUnit(iNewUnitType, x, y, UnitAITypes.NO_UNITAI, DirectionTypes.NO_DIRECTION)

Finally, this code gets executed every time a team acquires a new tech. I assume that you only want this to happen the first time the team acquires Optics, right? From that point on, they always build Colonists? If so, change the top to this:

Code:
[s]pTeam = gc.getTeam(iTeam)
if pTeam.isHasTech(gc.getInfoTypeForString('TECH_OPTICS')):[/s]
if iTechType == gc.getInfoTypeForString('TECH_OPTICS'):
	...
 
okay it works now, you just forgot to change iSettlers to iSettlerClass in row 6.

Otherwise seems to work just fine :) aweesooommeeee....
 
Top Bottom