New building suggestion

PsiCorps

FF: Babylon 5 mod team
Joined
Dec 30, 2007
Messages
1,425
Location
Britain
Hi guys
I've been considering a couple of new buildings and one of them doesn't fit the normal parameters of buildings. It is similar to another building you've already added to the FF+ mod but it is different enough that I don't know exactly what code is needed.

So.... here's the building.

Terraforming Station
Increases Max Population of the planet by one.
Can ONLY be built on a size 1 planet.

As you can see, it's similar to the Habitation Module and the Moon Base but it's the code for only allowing it to be built on a size 1 planet that is the issue.

Is this building suggestion possible?
 
It is possible.

The planet size restriction would be checked in Python. This shouldn't be a problem since the function that it would be added to is already called to check if a building can be built anyway. Even if you added a tag to the XML that was stored in the DLL's data for the building the check for it would be in this Python - it would just check the building's property instead of comparing the ID number. You can see this in the checks for requiring rings or a moon, which used to check specific buildings but had the data added as a tag in the XML so now the Python uses that property instead of checking for specific buildings.

The planet size check would go in the cannotConstruct function in FinalFrontierGameUtils.py. To make things work for the AI it needs to be in two parts. First, before the loop over the planets in the system, like right around where it checks for moons and rings, you'd add a check to see if the building it is checking is the building in question and if so check if the currently selected planet is the allowed size and if it isn't set "bNotHere = True". Then inside the loop (which is only run for the AI, allowing it switch the current build planet in order to build the specific building it most wants to build if necessary) it needs to do a similar check and if it is not the right size do a "continue" (like the rings and moon checks are doing). That is all it takes.

For a slight speed improvement it could get the ID for this specific building in the __init__ function just once instead of getting it from the DLL (via gc.getInfoTypeForString("BUILDING_WHATEVER")) every time the function is called.

If you want more detail (like, say, the actual Python code) I can post it for you.
 
Try adding these bits of code to FinalFrontierGameUtils.py...

Get the type index, substituting your building's type for "BUILDING_WHATEVER", in the __init__ function which should make it look like this (this is the entire function, if you haven't added anything to it):
Code:
	def __init__(self): 
		self.dBuildingBonuses = {	gc.getInfoTypeForString("BUILDING_FARM") : gc.getInfoTypeForString("BONUS_WHEAT"),
									gc.getInfoTypeForString("BUILDING_RANCH") : gc.getInfoTypeForString("BONUS_COW"),
									gc.getInfoTypeForString("BUILDING_HARBOR") : gc.getInfoTypeForString("BONUS_FISH"),
									gc.getInfoTypeForString("BUILDING_PLANTATION") : gc.getInfoTypeForString("BONUS_SPICES"),
									gc.getInfoTypeForString("BUILDING_WINERY") : gc.getInfoTypeForString("BONUS_WINE"),
									gc.getInfoTypeForString("BUILDING_COTTONMILL") : gc.getInfoTypeForString("BONUS_COTTON")}
		[B]self.iSmallPlanetBldg = gc.getInfoTypeForString("BUILDING_WHATEVER")[/B]

Note: if you want to allow for a building that can have unique versions, you can't predefine the building type like this. If you want to do this, I can give you the code for it. It would involve specifying a building class instead of the type in the code above and then looking up the civ specific building for the player trying to build things down near where it is used to do the comparison.

Add two small pieces of code to the cannotConstruct function.
First, right after the first check for rings:
Code:
...			
		if (pBuildingInfo.isRings()) and (not pPlanet.isRings()):
			bNotHere = true

		[B]if (eBuilding == self.iSmallPlanetBldg) and (pPlanet.getPlanetSize() != CvSolarSystem.iPlanetSizeSmall):
			bNotHere == true[/B]
		
		if (eBuilding in self.dBuildingBonuses):
...

Second, again right after a check for rings, this time inside the loop over all the planets in the system:
Code:
...						
					if (pBuildingInfo.isRings()) and (not pLoopPlanet.isRings()):
						continue
						
					[B]if (eBuilding == self.iSmallPlanetBldg) and (pLoopPlanet.getPlanetSize() != CvSolarSystem.iPlanetSizeSmall):
						continue[/B]
						
					if (pLoopPlanet.isHasBuilding(eBuilding)):
...

That should be it. Make sure you check your indentation so it matches the surrounding code and that sort of thing.

As you can see there is not a lot to it, so there is not a lot that could go wrong. The "CvSolarSystem.iPlanetSizeSmall" is a value that is defined for this planet size so you don't have to remember if small is size 0 or size 1, which I tend to forget - it is actually 0, by the way. Speaking of which, I have assumed that by "size 1 planet" you meant one that has a starting population limit of 1 (which is, technically, a size 0 planet by the definitions used in the code).
 
Try adding these bits of code to FinalFrontierGameUtils.py...

Get the type index, substituting your building's type for "BUILDING_WHATEVER", in the __init__ function which should make it look like this (this is the entire function, if you haven't added anything to it):
Code:
	def __init__(self): 
		self.dBuildingBonuses = {	gc.getInfoTypeForString("BUILDING_FARM") : gc.getInfoTypeForString("BONUS_WHEAT"),
									gc.getInfoTypeForString("BUILDING_RANCH") : gc.getInfoTypeForString("BONUS_COW"),
									gc.getInfoTypeForString("BUILDING_HARBOR") : gc.getInfoTypeForString("BONUS_FISH"),
									gc.getInfoTypeForString("BUILDING_PLANTATION") : gc.getInfoTypeForString("BONUS_SPICES"),
									gc.getInfoTypeForString("BUILDING_WINERY") : gc.getInfoTypeForString("BONUS_WINE"),
									gc.getInfoTypeForString("BUILDING_COTTONMILL") : gc.getInfoTypeForString("BONUS_COTTON")}
		[B]self.iSmallPlanetBldg = gc.getInfoTypeForString("BUILDING_WHATEVER")[/B]

Note: if you want to allow for a building that can have unique versions, you can't predefine the building type like this. If you want to do this, I can give you the code for it. It would involve specifying a building class instead of the type in the code above and then looking up the civ specific building for the player trying to build things down near where it is used to do the comparison.

Add two small pieces of code to the cannotConstruct function.
First, right after the first check for rings:
Code:
...			
		if (pBuildingInfo.isRings()) and (not pPlanet.isRings()):
			bNotHere = true

		[B]if (eBuilding == self.iSmallPlanetBldg) and (pPlanet.getPlanetSize() != CvSolarSystem.iPlanetSizeSmall):
			bNotHere == true[/B]
		
		if (eBuilding in self.dBuildingBonuses):
...

Second, again right after a check for rings, this time inside the loop over all the planets in the system:
Code:
...						
					if (pBuildingInfo.isRings()) and (not pLoopPlanet.isRings()):
						continue
						
					[B]if (eBuilding == self.iSmallPlanetBldg) and (pLoopPlanet.getPlanetSize() != CvSolarSystem.iPlanetSizeSmall):
						continue[/B]
						
					if (pLoopPlanet.isHasBuilding(eBuilding)):
...

That should be it. Make sure you check your indentation so it matches the surrounding code and that sort of thing.

As you can see there is not a lot to it, so there is not a lot that could go wrong. The "CvSolarSystem.iPlanetSizeSmall" is a value that is defined for this planet size so you don't have to remember if small is size 0 or size 1, which I tend to forget - it is actually 0, by the way. Speaking of which, I have assumed that by "size 1 planet" you meant one that has a starting population limit of 1 (which is, technically, a size 0 planet by the definitions used in the code).

Thank you God-Emperor, all the code has been added and I'm currently testing it all. Should I encounter any problems I'll let you know but for now it all seems to be fine.
 
Thank you God-Emperor, all the code has been added and I'm currently testing it all. Should I encounter any problems I'll let you know but for now it all seems to be fine.

Well, I knew it was too good to be true. A recent playtest where I was finally able to get to actually build the terraforming station has revealed that it can be built on all worlds not just those that are only size 1.

Any suggestions?
 
Oops. I see a typo in the first piece of code for the cannotConstruct function.

Code:
		if (eBuilding == self.iSmallPlanetBldg) and (pPlanet.getPlanetSize() != CvSolarSystem.iPlanetSizeSmall):
			bNotHere [B][COLOR="DarkRed"]==[/COLOR][/B] true

The "==" on the second line should be just "=", like "bNotHere = true".
 
Oops. I see a typo in the first piece of code for the cannotConstruct function.

Code:
		if (eBuilding == self.iSmallPlanetBldg) and (pPlanet.getPlanetSize() != CvSolarSystem.iPlanetSizeSmall):
			bNotHere [B][COLOR="DarkRed"]==[/COLOR][/B] true

The "==" on the second line should be just "=", like "bNotHere = true".

Thanks for the fix G-E I'll implement it tonight when I get in from work and test it.
 
Top Bottom