Can Python bring back terrain-transforming (a la Civ2's Engineer)?

Herostratus

Grim Harbinger of Things to Come
Joined
Jul 24, 2009
Messages
116
I am inspired--by the fact that this "Planetbuster" modcomp uses Python to transform any land square in the bomb's radius to water--to question whether this might mean a unit with a similar build order might be possible.

Specifically, my goal is to integrate into my mod a futuristic unit that can transform any land terrain that lacks hills or peaks into coast.

I do not know nearly enough about Python to realize this goal :sad: ...anybody have any ideas? Is there an existing mod I should borrow from?
 
Doable.

Look at the link you provided, in post #3 The_J gives a link to the Eden-Project, another source of inspiration...

One trick is to create a fake improvement to be built by workers, then when it appears you use the function onImprovementBuilt in CvEventManager.py to replace it with the intended python code.

Your workers would probably die in the process!... :o
 
Ah, interesting idea. I think I perceive the value of your "fake improvement" suggestion.

So here is my working Python code to implement that. The "fake improvement" in question is called DESERT_X_PLAINS (for proof-of-concept purposes, my initial attempt will be just to give a worker a build order that can transform desert to plains). I'm sure it will be immediately obvious how much of a Python noob I am :lol:

Code:
	def onImprovementBuilt(self, argsList):
		'Improvement Built'
		iImprovement, iX, iY = argsList
		if (not self.__LOG_IMPROVEMENT):
			return
		if iImprovementType == gc.getInfoTypeForString("IMPROVEMENT_DESERT_X_PLAINS"):
			iPlotX = iImprovement.getX()
			iPlotY = iImprovement.getY()

						pPlot = CyMap().plot(iPlotX, iPlotY)
						if (( pPlot.isDesert()==true  ):
							pPlot.setPlotType(PlotTypes.PLOT_LAND, True, True)
 						pPlot.setTerrainType(gc.getInfoTypeForString( "TERRAIN_PLAINS" ), 1, 1)

In what ways will this not work? I welcome merciless corrections. This is literally my first attempt at doing anything remotely original in Python...hence its Frankenstein's-monster appearance. :crazyeye:
 
So I guess you want to learn? ;)

I suppose you have enabled Python exceptions on. You can't seriously test Python code without it.

If you want, I will tell you a first advice though as it seems to me that your code won't even be read:
Spoiler :
Code:
		if (not self.__LOG_IMPROVEMENT):
			return
I might be wrong but if the default settings is still self.__LOG_IMPROVEMENT =0, then the return applies and the function is terminated. Your code should be put before that part.
 
I am happy to "learn" or simply "have the correct code spoonfed to me"... either way :)

Right now the code (including your correction) is apparently doing nothing, but I thought of another problem: the fake-improvement method will make the fake improvement visible in the Pedia, which I'd like to avoid.

What about using this approach?: http://forums.civfanatics.com/showthread.php?t=331001
Might it be possible to simulate more traditional build orders by integrating a several-turns-long delay of some kind?
 
I thought of the Python action button too but it's more complicated. I did it once for a mod and it works fine but perhaps not for here as it is more for instant action things.

Plus I've never got around to learn the AI teaching part. Without that, the AI will never use your action buttons. The fake improvement on the other side is used by the AI, I see it in my mod.

To not display the fake improvement, is it not possible to use the tag in xml 'bGraphicalOnly'? Worth a try.

For the improvement, you know that you can specify a value for the time needed, etc.

Do you happen to have BUG installed in your mod?

Otherwise, the Python popups should start to appear and give you indications on what's wrong. You are not far from it, really.
 
bGraphicalOnly does not suppress the improvement from appearing in the Pedia (or at least not my version of the Pedia, which IIRC is Sevopedia).

Good point about the AI, although if the improvement is truly "fake"--in that it grants no bonus--will the AI still use it? In other words, is the AI smart enough to know that building that fake-improvement would trigger a beneficial event... or does the AI just build fake improvements because it can?

Anyway, I have the XML part of it all figured out...the time to build the improvement, etc. It looks like one possible problem with the Python might be this part:

Code:
if iImprovementType == gc.getInfoTypeForString("IMPROVEMENT_DESERT_X_PLAINS"):

I did a search through the whole EventManager file for anything else that uses either iImprovementType or gc.getInfoTypeForString("IMPROVEMENT ...and I found nothing. Am I trying to use a nonexistent command or something?
 
Don't know about Sevopedia.

You have to give an incentive to the improvement for the AI to build it, like a YieldChange. You delete the improvement by Python before terraforming.

For the code, look at the beginning of the function: iImprovementType is not defined, iImprovement is. But Python should have told you that if you had enabled Python exception popups in the main CivilizationIV.ini file.
 
OK, I changed it to
Code:
	def onImprovementBuilt(self, argsList):
		'Improvement Built'
		iImprovement, iX, iY = argsList[0]
		iImprovementType = argsList[1]
		if iImprovementType == gc.getInfoTypeForString("IMPROVEMENT_DESERT_X_PLAINS"):
			iPlotX = iImprovement.getX()
			iPlotY = iImprovement.getY()
						pPlot = CyMap().plot(iPlotX, iPlotY)
						if (( pPlot.isDesert()==true  ):	
							pPlot.setPlotType(PlotTypes.PLOT_LAND, True, True)	
						pPlot.setTerrainType(gc.getInfoTypeForString( "TERRAIN_PLAINS" ), 1, 1)
		if (not self.__LOG_IMPROVEMENT):	# ends code if no improvement
			return

...and then the Python exception popups gave me what appear to be syntax errors in the lines:

pPlot = CyMap().plot(iPlotX, iPlotY)
if (( pPlot.isDesert()==true ):
..and...
pPlot.setTerrainType(gc.getInfoTypeForString( "TERRAIN_PLAINS" ), 1, 1)

Not sure where to go from here. In-game, the workers build the fake-improvement, but then the fake-improvement just sits there. I did code the improvement to require desert terrain, which (I hypothesize) will mean that the improvement vanishes if the terrain tile can actually be changed to plains by the Python.
 
You don't need to add iImprovementType = argsList[1], your formula can start with if iImprovement ==...

Likewise, you don't need to define iPlotX and iPlotY, you already have iX and iY.

pPlot = CyMap().plot(iX, iY) doesn't need to have a further indentation.

So far, we have:
Code:
	def onImprovementBuilt(self, argsList):
		'Improvement Built'
		iImprovement, iX, iY = argsList

		if(iImprovement==gc.getInfoTypeForString('IMPROVEMENT_DESERT_X_PLAINS')):
			pPlot = CyMap().plot(iX,iY)
			pPlot.setPlotType(PlotTypes.PLOT_LAND, True, True)
 			pPlot.setTerrainType(gc.getInfoTypeForString( "TERRAIN_PLAINS" ), True, True)
			pPlot.setImprovementType(-1)

Maybe pPlot.setPlotType(PlotTypes.PLOT_LAND, True, True) is useless.

To me, pPlot.isDesert is not valid. And you know that your improvement could only be built on Desert, so it is useless to check it one more time.
 
BY ODIN'S BEARD, it works!!! :cool:
Thank you thank you thank you, you king among men you :king:

Now to see if I can do the same thing for hills -> no hills, coast -> desert, and flat lands -> coast!
 
Great! :D

If you have several different improvements, you can define pPlot = CyMap().plot(iX,iY) one level above, at the same indentation than iImprovement, iX, iY = argsList. No need to repeat it each time.

Also, the next one can start with elif instead of if. elif = else if and is appropriate here as it will be each time one improvement type and not another.

Edit: be careful though, if the AI loves your improvements, you will all be flooded soon! :wow:
 
I don't remember the details, but I seem to recall that it has generally worked out that doing too much terraforming causes problems. This is particularly the case with converting land to water, although water to land (and perhaps flattening peaks) might cause a little trouble sometimes. The reason for this is that there is a thing called an area which the game engine uses for a few things. The division of the map into areas is calculated when the map is generated.

If you break an area into parts such that plots in the same area can not be reached by just moving a unit from plot A to plot B due to water having divided the area (or land having divided a water area) it might cause problems with the AI's ability to do some things. I'm not sure, but it may also cause unexpected behavior with those few buildings that give an effect in every city on the same continent. Or something - I don't really remember the details, just that it can cause problems. They may all be minor problems rather than anything that would cause a crash or otherwise break the game, but I'm not sure.

Fall From Heaven 2 has terraforming, but it is only converting land plots into other types of land plots (tundra into plains, and things like that). So do some other mods, like Caveman 2 Cosmos (which might also have the more powerful nukes from a mod component, Advanced Nukes or something like that, which turn the target into a water filled crater by making it a coast plot).

There is a python function to recalculate the areas, but I don't know if it is a good idea to call that after the game is under way. (CyMap().recalculateAreas())

So keep an eye out for weirdness.
 
Good to know. The path setting for units also depends on areas.

Personally, I'm just changing features in my mod, not terrains or plots.
 
Which complete code?... :D All there is in Python is on post #10. The rest is XML, create an improvement, build order, some art eventually (a button).
 
I don't remember the details, but I seem to recall that it has generally worked out that doing too much terraforming causes problems. This is particularly the case with converting land to water, although water to land (and perhaps flattening peaks) might cause a little trouble sometimes. The reason for this is that there is a thing called an area which the game engine uses for a few things. The division of the map into areas is calculated when the map is generated.

If you break an area into parts such that plots in the same area can not be reached by just moving a unit from plot A to plot B due to water having divided the area (or land having divided a water area) it might cause problems with the AI's ability to do some things. I'm not sure, but it may also cause unexpected behavior with those few buildings that give an effect in every city on the same continent. Or something - I don't really remember the details, just that it can cause problems. They may all be minor problems rather than anything that would cause a crash or otherwise break the game, but I'm not sure.

Makes sense. I'm coding the fake-coast-making-improvement so that the AI will (hopefully) never use it. I'm not too concerned as long as I limit my use of it to the occasional one-off canal-extension :D

There is also an aesthetic problem. Anybody who's used the Planetbuster knows that the newly-created coast tiles look wrinkly and ugly; sometimes there are even tiny straight black lines. *shrug*

hey guys, this idea is great - can one of you upload it here - the complete code?

Sure. In my mod I've made it possible to transform tundra to plains, desert to plains, plains to grass, and flatlands (grass, plains, desert, or tundra) into coast. My experimentation suggested that units which function like helicopters cannot perform worker actions, even if the relevant AI attributes are set in UnitInfos. (This would have been the only sensible way I could think of to convert coast to land; in my mod, helis can enter coast tiles, though not ocean.)

This is the relevant XML for the fake-improvements themselves:
Spoiler :
Code:
	<!-- Desert X Plains -->
		<ImprovementInfo>
			<Type>IMPROVEMENT_DESERT_X_PLAINS</Type>
			<Description>TXT_KEY_IMPROVEMENT_DESERT_X_PLAINS</Description>
			<Civilopedia>TXT_KEY_IMPROVEMENT_DESERT_X_PLAINS_PEDIA</Civilopedia>
			<ArtDefineTag>ART_DEF_IMPROVEMENT_LAND_WORKED</ArtDefineTag>
			<YieldChanges>
				<iYieldChange>1</iYieldChange>
				<iYieldChange>1</iYieldChange>
				<iYieldChange>0</iYieldChange>
			</YieldChanges>
			<bActsAsCity>0</bActsAsCity>
			<bHillsMakesValid>0</bHillsMakesValid>
			<bFreshWaterMakesValid>0</bFreshWaterMakesValid>
			<bRiverSideMakesValid>0</bRiverSideMakesValid>
			<bNoFreshWater>0</bNoFreshWater>
			<bRequiresFlatlands>0</bRequiresFlatlands>
			<bRequiresRiverSide>0</bRequiresRiverSide>
			<bRequiresIrrigation>0</bRequiresIrrigation>
			<bCarriesIrrigation>0</bCarriesIrrigation>
			<bRequiresFeature>0</bRequiresFeature>
			<bWater>0</bWater>
			<bGoody>0</bGoody>
			<bPermanent>0</bPermanent>
			<iAdvancedStartCost>-1</iAdvancedStartCost>
			<iAdvancedStartCostIncrease>0</iAdvancedStartCostIncrease>
			<iTilesPerGoody>0</iTilesPerGoody>
			<iGoodyRange>0</iGoodyRange>
			<iFeatureGrowth>0</iFeatureGrowth>
			<iUpgradeTime>0</iUpgradeTime>
			<iAirBombDefense>-1</iAirBombDefense>
			<iDefenseModifier>0</iDefenseModifier>
			<iHappiness>0</iHappiness>
			<iPillageGold>0</iPillageGold>
			<bOutsideBorders>0</bOutsideBorders>
			<TerrainMakesValids>
				<TerrainMakesValid>
					<TerrainType>TERRAIN_DESERT</TerrainType>
					<bMakesValid>1</bMakesValid>
				</TerrainMakesValid>
			</TerrainMakesValids>
			<FeatureMakesValids/>
			<ImprovementPillage/>
			<ImprovementUpgrade/>
			<TechYieldChanges/>
			<RouteYieldChanges/>
			<WorldSoundscapeAudioScript/>
			<bGraphicalOnly>0</bGraphicalOnly>
		</ImprovementInfo>
	<!-- Desert X Plains -->
	<!-- Flat X Coast-->
		<ImprovementInfo>
			<Type>IMPROVEMENT_FLAT_X_COAST</Type>
			<Description>TXT_KEY_IMPROVEMENT_FLAT_X_COAST</Description>
			<Civilopedia>TXT_KEY_IMPROVEMENT_FLAT_X_COAST_PEDIA</Civilopedia>
			<ArtDefineTag>ART_DEF_IMPROVEMENT_LAND_WORKED</ArtDefineTag>
			<YieldChanges/>
			<bActsAsCity>0</bActsAsCity>
			<bHillsMakesValid>0</bHillsMakesValid>
			<bFreshWaterMakesValid>0</bFreshWaterMakesValid>
			<bRiverSideMakesValid>0</bRiverSideMakesValid>
			<bNoFreshWater>0</bNoFreshWater>
			<bRequiresFlatlands>1</bRequiresFlatlands>
			<bRequiresRiverSide>0</bRequiresRiverSide>
			<bRequiresIrrigation>0</bRequiresIrrigation>
			<bCarriesIrrigation>0</bCarriesIrrigation>
			<bRequiresFeature>0</bRequiresFeature>
			<bWater>0</bWater>
			<bGoody>0</bGoody>
			<bPermanent>0</bPermanent>
			<iAdvancedStartCost>-1</iAdvancedStartCost>
			<iAdvancedStartCostIncrease>0</iAdvancedStartCostIncrease>
			<iTilesPerGoody>0</iTilesPerGoody>
			<iGoodyRange>0</iGoodyRange>
			<iFeatureGrowth>0</iFeatureGrowth>
			<iUpgradeTime>0</iUpgradeTime>
			<iAirBombDefense>-1</iAirBombDefense>
			<iDefenseModifier>0</iDefenseModifier>
			<iHappiness>0</iHappiness>
			<iPillageGold>0</iPillageGold>
			<bOutsideBorders>0</bOutsideBorders>
			<TerrainMakesValids>
				<TerrainMakesValid>
					<TerrainType>TERRAIN_GRASS</TerrainType>
					<bMakesValid>1</bMakesValid>
				</TerrainMakesValid>
				<TerrainMakesValid>
					<TerrainType>TERRAIN_PLAINS</TerrainType>
					<bMakesValid>1</bMakesValid>
				</TerrainMakesValid>
				<TerrainMakesValid>
					<TerrainType>TERRAIN_DESERT</TerrainType>
					<bMakesValid>1</bMakesValid>
				</TerrainMakesValid>
				<TerrainMakesValid>
					<TerrainType>TERRAIN_TUNDRA</TerrainType>
					<bMakesValid>1</bMakesValid>
				</TerrainMakesValid>
			</TerrainMakesValids>
			<FeatureMakesValids/>
			<ImprovementPillage/>
			<ImprovementUpgrade/>
			<TechYieldChanges/>
			<RouteYieldChanges/>
			<WorldSoundscapeAudioScript/>
			<bGraphicalOnly>0</bGraphicalOnly>
		</ImprovementInfo>
	<!-- Flat X Coast -->
	<!-- Tundra X Plains-->
		<ImprovementInfo>
			<Type>IMPROVEMENT_TUNDRA_X_PLAINS</Type>
			<Description>TXT_KEY_IMPROVEMENT_TUNDRA_X_PLAINS</Description>
			<Civilopedia>TXT_KEY_IMPROVEMENT_TUNDRA_X_PLAINS_PEDIA</Civilopedia>
			<ArtDefineTag>ART_DEF_IMPROVEMENT_LAND_WORKED</ArtDefineTag>
			<YieldChanges>
				<iYieldChange>0</iYieldChange>
				<iYieldChange>1</iYieldChange>
				<iYieldChange>0</iYieldChange>
			</YieldChanges>
			<bActsAsCity>0</bActsAsCity>
			<bHillsMakesValid>0</bHillsMakesValid>
			<bFreshWaterMakesValid>0</bFreshWaterMakesValid>
			<bRiverSideMakesValid>0</bRiverSideMakesValid>
			<bNoFreshWater>0</bNoFreshWater>
			<bRequiresFlatlands>0</bRequiresFlatlands>
			<bRequiresRiverSide>0</bRequiresRiverSide>
			<bRequiresIrrigation>0</bRequiresIrrigation>
			<bCarriesIrrigation>0</bCarriesIrrigation>
			<bRequiresFeature>0</bRequiresFeature>
			<bWater>0</bWater>
			<bGoody>0</bGoody>
			<bPermanent>0</bPermanent>
			<iAdvancedStartCost>-1</iAdvancedStartCost>
			<iAdvancedStartCostIncrease>0</iAdvancedStartCostIncrease>
			<iTilesPerGoody>0</iTilesPerGoody>
			<iGoodyRange>0</iGoodyRange>
			<iFeatureGrowth>0</iFeatureGrowth>
			<iUpgradeTime>0</iUpgradeTime>
			<iAirBombDefense>-1</iAirBombDefense>
			<iDefenseModifier>0</iDefenseModifier>
			<iHappiness>0</iHappiness>
			<iPillageGold>0</iPillageGold>
			<bOutsideBorders>0</bOutsideBorders>
			<TerrainMakesValids>
				<TerrainMakesValid>
					<TerrainType>TERRAIN_TUNDRA</TerrainType>
					<bMakesValid>1</bMakesValid>
				</TerrainMakesValid>
			</TerrainMakesValids>
			<FeatureMakesValids/>
			<ImprovementPillage/>
			<ImprovementUpgrade/>
			<TechYieldChanges/>
			<RouteYieldChanges/>
			<WorldSoundscapeAudioScript/>
			<bGraphicalOnly>0</bGraphicalOnly>
		</ImprovementInfo>
	<!-- Tundra X Plains -->
	<!-- Plains X Grass-->
		<ImprovementInfo>
			<Type>IMPROVEMENT_PLAINS_X_GRASS</Type>
			<Description>TXT_KEY_IMPROVEMENT_PLAINS_X_GRASS</Description>
			<Civilopedia>TXT_KEY_IMPROVEMENT_PLAINS_X_GRASS_PEDIA</Civilopedia>
			<ArtDefineTag>ART_DEF_IMPROVEMENT_LAND_WORKED</ArtDefineTag>
			<YieldChanges>
				<iYieldChange>1</iYieldChange>
				<iYieldChange>-1</iYieldChange>
				<iYieldChange>0</iYieldChange>
			</YieldChanges>
			<bActsAsCity>0</bActsAsCity>
			<bHillsMakesValid>0</bHillsMakesValid>
			<bFreshWaterMakesValid>0</bFreshWaterMakesValid>
			<bRiverSideMakesValid>0</bRiverSideMakesValid>
			<bNoFreshWater>0</bNoFreshWater>
			<bRequiresFlatlands>0</bRequiresFlatlands>
			<bRequiresRiverSide>0</bRequiresRiverSide>
			<bRequiresIrrigation>0</bRequiresIrrigation>
			<bCarriesIrrigation>0</bCarriesIrrigation>
			<bRequiresFeature>0</bRequiresFeature>
			<bWater>0</bWater>
			<bGoody>0</bGoody>
			<bPermanent>0</bPermanent>
			<iAdvancedStartCost>-1</iAdvancedStartCost>
			<iAdvancedStartCostIncrease>0</iAdvancedStartCostIncrease>
			<iTilesPerGoody>0</iTilesPerGoody>
			<iGoodyRange>0</iGoodyRange>
			<iFeatureGrowth>0</iFeatureGrowth>
			<iUpgradeTime>0</iUpgradeTime>
			<iAirBombDefense>-1</iAirBombDefense>
			<iDefenseModifier>0</iDefenseModifier>
			<iHappiness>0</iHappiness>
			<iPillageGold>0</iPillageGold>
			<bOutsideBorders>0</bOutsideBorders>
			<TerrainMakesValids>
				<TerrainMakesValid>
					<TerrainType>TERRAIN_PLAINS</TerrainType>
					<bMakesValid>1</bMakesValid>
				</TerrainMakesValid>
			</TerrainMakesValids>
			<FeatureMakesValids/>
			<ImprovementPillage/>
			<ImprovementUpgrade/>
			<TechYieldChanges/>
			<RouteYieldChanges/>
			<WorldSoundscapeAudioScript/>
			<bGraphicalOnly>0</bGraphicalOnly>
		</ImprovementInfo>
	<!-- Plains X Grass -->
...and here's the XML that enables the build button for worker units for each of the above fake-improvements (including a couple of non-Firaxis tech prereqs):
Spoiler :
Code:
	<!-- Desert X Plains Build Order -->
		<BuildInfo>
			<Type>BUILD_DESERT_X_PLAINS</Type>
			<Description>TXT_KEY_BUILD_DESERT_X_PLAINS</Description>
			<Help/>
			<PrereqTech>TECH_ECOLOGY</PrereqTech>
			<iTime>2500</iTime>
			<iCost>0</iCost>
			<bKill>0</bKill>
			<ImprovementType>IMPROVEMENT_DESERT_X_PLAINS</ImprovementType>
			<RouteType>NONE</RouteType>
			<EntityEvent>ENTITY_EVENT_BUILD</EntityEvent>
			<FeatureStructs/>
			<HotKey>KB_X</HotKey>
			<bAltDown>0</bAltDown>
			<bShiftDown>0</bShiftDown>
			<bCtrlDown>0</bCtrlDown>
			<iHotKeyPriority>1</iHotKeyPriority>
			<Button>Art/Interface/Buttons/Builds/Xplains.dds</Button>
		</BuildInfo>
	<!-- Desert X Plains Build Order -->
	<!-- Flat X Coast Build Order -->
		<BuildInfo>
			<Type>BUILD_FLAT_X_COAST</Type>
			<Description>TXT_KEY_BUILD_FLAT_X_COAST</Description>
			<Help>TXT_KEY_HELP_BUILD_FLAT_X_COAST</Help>
			<PrereqTech>TECH_CIVIL_ENGINEERING</PrereqTech>
			<iTime>2500</iTime>
			<iCost>0</iCost>
			<bKill>0</bKill>
			<ImprovementType>IMPROVEMENT_FLAT_X_COAST</ImprovementType>
			<RouteType>NONE</RouteType>
			<EntityEvent>ENTITY_EVENT_BUILD</EntityEvent>
			<FeatureStructs/>
			<HotKey>KB_E</HotKey>
			<bAltDown>0</bAltDown>
			<bShiftDown>0</bShiftDown>
			<bCtrlDown>0</bCtrlDown>
			<iHotKeyPriority>1</iHotKeyPriority>
			<Button>Art/Interface/Buttons/Builds/Xcoast.dds</Button>
		</BuildInfo>
	<!-- Flat X Coast Build Order -->
	<!-- Tundra X Plains Build Order -->
		<BuildInfo>
			<Type>BUILD_TUNDRA_X_PLAINS</Type>
			<Description>TXT_KEY_BUILD_TUNDRA_X_PLAINS</Description>
			<Help/>
			<PrereqTech>TECH_TERRAFORMING</PrereqTech>
			<iTime>2500</iTime>
			<iCost>0</iCost>
			<bKill>0</bKill>
			<ImprovementType>IMPROVEMENT_TUNDRA_X_PLAINS</ImprovementType>
			<RouteType>NONE</RouteType>
			<EntityEvent>ENTITY_EVENT_BUILD</EntityEvent>
			<FeatureStructs/>
			<HotKey>KB_X</HotKey>
			<bAltDown>0</bAltDown>
			<bShiftDown>0</bShiftDown>
			<bCtrlDown>0</bCtrlDown>
			<iHotKeyPriority>1</iHotKeyPriority>
			<Button>Art/Interface/Buttons/Builds/Xplains.dds</Button>
		</BuildInfo>
	<!-- Tundra X Plains Build Order -->
	<!-- Plains X Grass Build Order -->
		<BuildInfo>
			<Type>BUILD_PLAINS_X_GRASS</Type>
			<Description>TXT_KEY_BUILD_PLAINS_X_GRASS</Description>
			<Help/>
			<PrereqTech>TECH_TERRAFORMING</PrereqTech>
			<iTime>2500</iTime>
			<iCost>0</iCost>
			<bKill>0</bKill>
			<ImprovementType>IMPROVEMENT_PLAINS_X_GRASS</ImprovementType>
			<RouteType>NONE</RouteType>
			<EntityEvent>ENTITY_EVENT_BUILD</EntityEvent>
			<FeatureStructs/>
			<HotKey>KB_X</HotKey>
			<bAltDown>0</bAltDown>
			<bShiftDown>0</bShiftDown>
			<bCtrlDown>0</bCtrlDown>
			<iHotKeyPriority>1</iHotKeyPriority>
			<Button>Art/Interface/Buttons/Builds/Xgrass.dds</Button>
		</BuildInfo>
	<!-- Plains X Grass Build Order -->
...and this is the Python that exploits those fake-improvements in EventManager.py:
Code:
	def onImprovementBuilt(self, argsList):
		'Improvement Built'
		iImprovement, iX, iY = argsList
		if(iImprovement==gc.getInfoTypeForString('IMPROVEMENT_DESERT_X_PLAINS')):
			pPlot = CyMap().plot(iX,iY)
 			pPlot.setTerrainType(gc.getInfoTypeForString( "TERRAIN_PLAINS" ), True, True)
			pPlot.setImprovementType(-1)
		elif(iImprovement==gc.getInfoTypeForString('IMPROVEMENT_FLAT_X_COAST')):
			pPlot = CyMap().plot(iX,iY)
 			pPlot.setTerrainType(gc.getInfoTypeForString( "TERRAIN_COAST" ), True, True)
			pPlot.setImprovementType(-1)			
		elif(iImprovement==gc.getInfoTypeForString('IMPROVEMENT_PLAINS_X_GRASS')):
			pPlot = CyMap().plot(iX,iY)
 			pPlot.setTerrainType(gc.getInfoTypeForString( "TERRAIN_GRASS" ), True, True)
			pPlot.setImprovementType(-1)
		elif(iImprovement==gc.getInfoTypeForString('IMPROVEMENT_TUNDRA_X_PLAINS')):
			pPlot = CyMap().plot(iX,iY)
 			pPlot.setTerrainType(gc.getInfoTypeForString( "TERRAIN_PLAINS" ), True, True)
			pPlot.setImprovementType(-1)
		if (not self.__LOG_IMPROVEMENT):
			return

Of course, the worker units would also have to be given access to the build orders in UnitInfos.xml ...plus there's the XML TXT tags, one of which is significant for the flatland->coast order:
Code:
	<TEXT>
		<Tag>TXT_KEY_HELP_BUILD_FLAT_X_COAST</Tag>
		<English>[COLOR_WARNING_TEXT]Will consume the unit[COLOR_REVERT]</English>
	</TEXT>
...though if I were in a silly mood I might phrase that as "Will drown the unit" ;)

Additionally, I can't see why it wouldn't be possible to transform peaks into something more useful, so long as the unit doing the transforming has been given the ability to cross impassable terrain in UnitInfos. I elected not to allow this (nor land ice transforming) for reasons of balance.

I had hoped to add a "Flatten Hill" transform command, but this method seems to require a single terrain type on each end of the transaction, and there doesn't seem to be any such thing as TERRAIN_NOHILL. I don't quite understand how the game handles hills, since they are their own terrain type and yet always coexistent with another.
 
As I said recently in the Middle-Earth thread:
Code:
Strictly speaking, peaks and hills are plot types, not terrain types.
I guess they have added them as terrains too so you can edit some of
their properties or some of the promotions linked to them, as you
can't edit plot types in the xml (the other plots being land and ocean
- you see that in scenarios/maps for example).

With Python, you would use
Code:
pPlot.setPlotType(PlotTypes.PLOT_LAND, True, True)

or 

pPlot.setPlotType(PlotTypes.PLOT_PEAK, True, True)

Per memory, in BtS:
PLOT_PEAK = 0
PLOT_HILLS = 1
PLOT_LAND = 2
PLOT_OCEAN = 3
 
Obviously in
Code:
def onImprovementBuilt(self, argsList):

A Peak/Hills code would go after pPlot = CyMap().plot(iX,iY), either replacing the code for terrains or adding it.
 
Back
Top Bottom