Terrain Features Creating Buildings when city founding

Lib.Spi't

Overlord of the Wasteland
Joined
Feb 12, 2009
Messages
3,708
Location
UK
Hi everyone

I have been trying to make a python code that will make a specific building found in a city when it is founded on a specific terrain feature. With no success.

I am working in the Fury Road Mod For a Fallout edition and this is what I want to do.

I have made a new terrain feature, Vault. I would like it so that when a city is founded on it it creates the building 'sealed vault'. Also I would like it so that if a city is founded anywhere else it begins with a building 'village'.

I understand elements like using the building_classes and such but just when I think I am grasping some of the ideas around python I just can't seem to make it stick.

If anyone could help me with finding the write python 'def' elements to use, as well as what file to place it in etc. it would be a great help. I already have a python code that stops certain civs from founding on terrain that does not have a vault.

Any help that can be offered would be appreaciated
 
Post what you have (the working bit) and we'll be able to get the rest working, also. :king: I don't foresee any issues in any case.
Spoiler :
Basically you hack into the onCityBuilt callup in the CvEventManager module.

Firstly you get the CyPlot object of the city plot with CyCity.plot() and use that with CyPlot.getFeatureType(). If the FeatureType return value matches the vault feature - which you can check against the XML tag with CyGlobalContext.getInfoTypeForString() - then you use CyCity.setNumRealBuilding() to set the number of Closed Vault buildings to 1 (one).

If the first check (above) is negative (using a branched conditional statement) then you instead add one instance of the the Village building instead. All this could be coded in an array of different ways, buts it should be pretty straight forward.

Also, what is the XML tag you're using for the vault feature? "FEATURE_VAULT"? Are you sure that there is nothing in the XML entry that makes the feature disappear when a city is founded on top of it? And nothing is blocking a city being founded on top of it?

What are the XML tags for the associated buildings, then?
 
Code:
def cannotFoundCity(self,argsList):
      iPlayer, iPlotX, iPlotY = argsList
      pPlayer = self.gc.getPlayer(iPlayer)
      if pPlayer.getCivilizationType() == self.gc.getInfoTypeForString("CIVILIZATION_GUILDSTEEL"):
         pPlot = self.gc.getMap().plot(iPlotX, iPlotY)
         if pPlot.getFeatureType() == self.gc.getInfoTypeForString("FEATURE_VAULT"): return false
         return true
      if pPlayer.getCivilizationType() == self.gc.getInfoTypeForString("CIVILIZATION_AUSTRALIA"):
         pPlot = self.gc.getMap().plot(iPlotX, iPlotY)
         if pPlot.getFeatureType() == self.gc.getInfoTypeForString("FEATURE_VAULT"): return false
         return true
      if pPlayer.getCivilizationType() == self.gc.getInfoTypeForString("CIVILIZATION_NEWHOLY"):
         pPlot = self.gc.getMap().plot(iPlotX, iPlotY)
         if pPlot.getFeatureType() == self.gc.getInfoTypeForString("FEATURE_VAULT"): return false
         return true
      return false

Ok here is the code that makes it possible to only found on a 'Vault' feature.
it's in the gameutils.py file.

I haven't been able to write a code for the elements you have shown me basically when I start adding it in it doesn't like it and won't run, this is probably because I haven't made a complete piece of python code but I wanted to check if it matters that the onCityBuilt is already being used for another feature, is it possible to add it underneath this one to be able to implement my piece of code?

def onCityBuilt(self, argsList):
if CyCity.plot() == CyPlot.getFeatureType(CyGlobalContext.getInfoTypeForString("FEATURE_VAULT"))
CyCity.setNumRealBuilding("BUILDINGCLASS_VAULT") = 1 return true
return false

This is my attempt at beginning to put together the elements you have told me, I am certain that it is wrong but not sure what the right way to do it is. Like I said I begin to grasp the idea of python by looking at other examples but when it comes time to make something new I don't know what the right and wrong way to do it is.

FEATURE_VAULT (the terrain feature I am founding on)
BUILDING_VAULT (what I want built if a FEATURE_VAULT is present)
BUILDING_VILLAGE (what I want built if the FEATURE_VAULT is not present)

I have made sure that you can found on a 'vault' square, I think it is getting rid of the vault feature when it founds the city, I am not sure if this will be a problem or not because if it registers the feature and adds the building before it gets rid of the feature I think this is fine. if however it gets rid of the feature before placing the building I can see why this would be a problem.

Anyway thank you for taking the time to look at my problem, you may regret it before long hehe :-P cheers
 
No self. before gc.
Even if the first code snippet worked, the game would directly be finished. Because if you then don't start on a vault, you would not be able to build directly a city, and if only have units and can't build a city, then you are dead and the game is over.

The second part would also not work, because it has to be CyGlobalContext(), and you are also creating a new city instance free out of the air, without any connection to the found city. Alsothe plot would not have a feature, because features are destroyed when you build a city on it.

So, a start from the beginning:
First, the plot must have a feature after foundin the city.
So change in CvGameUtils.py:
PHP:
	def citiesDestroyFeatures(self,argsList):
		iX, iY= argsList
		return True

to:
PHP:
	def citiesDestroyFeatures(self,argsList):
		iX, iY= argsList
		return False

and then in the CvEventManager:
PHP:
	def onCityBuilt(self, argsList):
		'City Built'
		city = argsList[0]###this is the city
###new code start
		pPlot = CyMap().plot(city.getX(),city.getY())
		###the above code gets the X and Y coordinates from the given city
		###and get you the plot via creating a new map instance (not reall
		###new, there can only be one map instance in the game
		if pPlot.getFeatureType() == gc.getInfoTypeForString("FEATURE_VAULT"):
                        ###the left part gets the feature from the plot (presented as number
                        ###the right part gets the number for the feature from the XML
                        ###(first mentioned feature = 1, second mentioned feature = 2, and so on)
                        ###the if clause compares them to see if the plot has the feature
                        ###you asked for
                        iBuilding = gc.getInfoTypeForString("BUILDING_VAULT")
                        ###the above line gets you the number of the building out of the XML
                        city.setNumRealBuilding(iBuilding,1)
                        ###the city is still the same as above. Has to be, you want the
                        ###building to be in the city
                        ###the function sets the number of the building into the city
                        ###the second parameter is how many buidlings
                        ###confusing, but it is possible to have more than one instance of
                        ###the same building in a city, that's why you have to say how many
                        ###and that's it :D
###new code end                        
                        
		if (city.getOwner() == gc.getGame().getActivePlayer()):
			self.__eventEditCityNameBegin(city, False)	
		CvUtil.pyPrint('City Built Event: %s' %(city.getName()))
 
hey the J thanks for your input, yeah I know what you mean about the code, it currently means that you can't start a new game hehe, so my current objective is to create a scenario in which the map is pre-made eventually my hope is that I will be able to use a custom map script to give the civs the vault that they need so that the computer will found their cities on a vault or perhaps make the game start with a settler again and place the 3 start locations near a vault feature, but I will tackle that further down the road. :-)

how would I make it build the village on any other type of tile I can almost see what the code needs to do but again I just can't think what the right thing would be,
it needs like an 'otherwise build village' statement in the code but I am not sure if that would be some kind of a true or false return or if it would simply be a case of

iBuilding = gc.getInfoTypeForString("BUILDING_VILLAGE")
city.setNumRealBuilding(iBuilding,1)

that followed by the if statement you provided

again top marks for the help guys you are kings among men :-)

EDIT

Code:
def onCityBuilt(self, argsList):
      city = argsList[0]
      pPlot = CyMap().plot(city.getX(),city.getY())
      if pPlot.getFeatureType() == self.gc.getInfoTypeForString("FEATURE_VAULT"):
        iBuilding = self.gc.getInfoTypeForString("BUILDING_VAULT")
        city.setNumRealBuilding(iBuilding,1)
      if not pPlot.getFeatureType() == self.gc.getInfoTypeForString("FEATURE_VAULT"):
        iBuilding = self.gc.getInfoTypeForString("BUILDING_VILLAGE")
        city.setNumRealBuilding(iBuilding,1)

ok I think it is all working now thank you very much guys your help is invaluable! Putting self.gc seems to make it all work I can only imagine that this is because I am working in a furyroad file rather than a 'main game' file. What ever the reason it seems to make it work so....hehe

Thanks very much guys :-)
 
My suggestion:
Code:
	def onCityBuilt(self, argsList):
		city = argsList[0]
[B]		if city.plot().getFeatureType() == gc.getInfoTypeForString("FEATURE_VAULT"):
        		iBuilding = gc.getInfoTypeForString("BUILDING_VAULT")
		else:
			iBuilding = gc.getInfoTypeForString("BUILDING_VILLAGE")
		city.setNumRealBuilding(iBuilding, 1)[/B]
and
Code:
	def cannotFoundCity(self,argsList):
		iPlayer, iPlotX, iPlotY = argsList
[B]		if gc.getMap().plot(iPlotX, iPlotY).getFeatureType() == gc.getInfoTypeForString("FEATURE_VAULT"):
			eCiv = gc.getPlayer(iPlayer).getCivilizationType()
			return ( eCiv == gc.getInfoTypeForString("CIVILIZATION_GUILDSTEEL") 
			         or eCiv == gc.getInfoTypeForString("CIVILIZATION_AUSTRALIA")
			         or eCiv == gc.getInfoTypeForString("CIVILIZATION_NEWHOLY") )[/B]
		return False
Also, I suggest learning some actual Python before going forward with further Python based features. You'll be saving time, in the long run. You could take a look at my tutorial for this.
 
(Note the addition to the previous post.)
 
Back
Top Bottom