• Civilization 7 has been announced. For more info please check the forum here .

Final Frontier - Starbase problems

PsiCorps

FF: Babylon 5 mod team
Joined
Dec 30, 2007
Messages
1,425
Location
Britain
As part of the B5 mod we have introduced a new Starbase that replaces the standard starbase I for the Earth Alliance. I've gone through Python and looked at everything to do with the construction of a Starbase by a construction unit.
First, this is what the standard Starbase construction Python code looks like in CVFinalFrontierEvents.py
Spoiler :
Code:
def onUnitBuildImprovement(self, argsList):
		'Unit begins enacting a Build (building an Improvement or Route)'
		pUnit, iBuild, bFinished = argsList
		
		iBuildStarbaseID = CvUtil.findInfoTypeNum(gc.getBuildInfo,gc.getNumBuildInfos(),'BUILD_STARBASE')
		
		# Starbase WAS built
		if (iBuild == iBuildStarbaseID):
			pUnit.setScriptData("BuildingStarbase")

	def onImprovementBuilt(self, argsList):
		'Improvement Built'
		iImprovement, iX, iY = argsList
		
		iImprovementStarbaseID = CvUtil.findInfoTypeNum(gc.getImprovementInfo,gc.getNumImprovementInfos(),'IMPROVEMENT_STARBASE')
		iUnitConstructShipID = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_CONSTRUCT_SHIP')
		
		# Starbase finished
		if (iImprovement == iImprovementStarbaseID):
			
			pPlot = CyMap().plot(iX, iY)
			pPlot.setImprovementType(-1)
			
			# Look for Construction Ship on this plot
			for iUnitLoop in range(pPlot.getNumUnits()):
				pUnit = pPlot.getUnit(iUnitLoop)
				
				if (pUnit.getScriptData() == "BuildingStarbase"):
					self.doMakeStarbase(pUnit.getOwner(), iX, iY)
					self.aiKillTimerData = [3, pUnit.getOwner(), pUnit.getID()]
#					pUnit.kill(true, -1)
	
	def doMakeStarbase(self, iPlayer, iX, iY):
		
		pPlayer = gc.getPlayer(iPlayer)
		pPlot = CyMap().plot(iX, iY)
		
		# Create Starbase Unit
		iUnitStarbaseID = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_STARBASE_I')
		pPlayer.initUnit(iUnitStarbaseID, iX, iY, UnitAITypes.UNITAI_ATTACK, DirectionTypes.NO_DIRECTION)
		
		self.updateStarbaseCulture(iPlayer, iX, iY)
		
	def updateStarbaseCulture(self, iPlayer, iX, iY):
		
		# Create culture around unit
		for iXLoop in range(iX-2, iX+3):
			for iYLoop in range(iY-2, iY+3):
				
				iActiveX = iXLoop
				iActiveY = iYLoop
				
				if (iActiveX < 0):
					iActiveX = CyMap().getGridWidth() + iActiveX
				if (iActiveY < 0):
					iActiveY = CyMap().getGridHeight() + iActiveY
				
				pLoopPlot = CyMap().plot(iActiveX, iActiveY)
#				pPlotLoop = CyMap().plot(iXLoop, iYLoop)
#				printd("Setting Player %d as the owner of %d, %d" %(iPlayer, iXLoop, iYLoop))
				# Don't override culture that's already here
				if (pLoopPlot.getOwner() == -1):
					pLoopPlot.setOwnerNoUnitCheck(iPlayer)
		
	def updateAllStarbases(self):
		
		# Update Starbase culture
		iUnitStarbaseID = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_STARBASE_I')
		iUnitStarbaseIID = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_STARBASE_II')
		iUnitStarbaseIIID = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_STARBASE_III')
		iUnitMissileI = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_MISSILE_I')
		iUnitMissileII = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_MISSILE_II')
		iUnitMissileIII = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_MISSILE_III')
		
		# List made to preserve culture of units built first
		aaiStarbaseList = []
		
		for iPlayerLoop in range(gc.getMAX_CIV_PLAYERS()):
			pPlayer = gc.getPlayer(iPlayerLoop)
			pTeam = gc.getTeam(pPlayer.getTeam())
			pyPlayer = PyPlayer(iPlayerLoop)
			
			iUnitToCreate = -1
			aiPossibleUnitList = [iUnitMissileI, iUnitMissileII, iUnitMissileIII]
			
			for iUnitLoop in aiPossibleUnitList:
				
				pUnitInfo = gc.getUnitInfo(iUnitLoop)
				iNeededTech = pUnitInfo.getPrereqAndTech()
				
				if (pTeam.isHasTech(iNeededTech)):
					iUnitToCreate = iUnitLoop
			
			apUnitList = pyPlayer.getUnitList()
			for pUnitLoop in apUnitList:
				if (pUnitLoop.getUnitType() == iUnitStarbaseID or pUnitLoop.getUnitType() == iUnitStarbaseIID or pUnitLoop.getUnitType() == iUnitStarbaseIIID):
					aaiStarbaseList.append([pUnitLoop.getGameTurnCreated(), iPlayerLoop, pUnitLoop.getX(), pUnitLoop.getY()])
					
					# Need appropriate tech to create Missile
					if (iUnitToCreate != -1):
						# Need appropriate turn to create
						iTurnCreated = pUnitLoop.getGameTurnCreated()
						iCurrentTurn = CyGame().getGameTurn()
						
						if (iTurnCreated != iCurrentTurn):
							iTurnsSinceCreation = iCurrentTurn - iTurnCreated
							# Produce Missile every 15 turns
							if (iTurnsSinceCreation % 15 == 0):
								print "UnitID: %d, X: %d, Y: %d" %(iUnitToCreate, pUnitLoop.getX(), pUnitLoop.getY())
								pUnit = pPlayer.initUnit(iUnitToCreate, pUnitLoop.getX(), pUnitLoop.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.NO_DIRECTION)
								# Load Missile onto Starbase... the C++ doesn't like this but it can deal :)
								pUnit.setTransportUnit(pUnitLoop)
		
#		printd("\n\nXXX: There are %d Starbases on the map" %(len(aaiStarbaseList)))
#		printd(aaiStarbaseList)
			
		if (len(aaiStarbaseList) > 0):
			
			# Make order such that units built first get culture preference
			aaiStarbaseList.sort()
#			aaiStarbaseList.reverse()
			
			for iStarbaseLoop in range(len(aaiStarbaseList)):
				self.updateStarbaseCulture(aaiStarbaseList[iStarbaseLoop][1], aaiStarbaseList[iStarbaseLoop][2], aaiStarbaseList[iStarbaseLoop][3])
		
	def canBuildStarbase(self, pPlot, iOffset=0):
		
		# Starbase restriction
		iBuildStarbase = CvUtil.findInfoTypeNum(gc.getBuildInfo,gc.getNumBuildInfos(),'BUILD_STARBASE')
		
		# Can't build on a Solar System
		iFeatureIDSolarSystem = CvUtil.findInfoTypeNum(gc.getFeatureInfo,gc.getNumFeatureInfos(),'FEATURE_SOLAR_SYSTEM')
		if (pPlot.getFeatureType() == iFeatureIDSolarSystem):
			return 0
		
		# Can't build on top of another Starbase
		iUnitStarbaseI = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_STARBASE_I')
		iUnitStarbaseII = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_STARBASE_II')
		iUnitStarbaseIII = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_STARBASE_III')
		
		iNumUnits = iOffset # Offset so that Interface can disable button
		
		# Loop through all units on the plot
		for iUnitLoop in range(pPlot.getNumUnits()):
			pUnit = pPlot.getUnit(iUnitLoop)
			
			# Can't build on top of another Starbase
			if (pUnit.getUnitType() == iUnitStarbaseI or pUnit.getUnitType() == iUnitStarbaseII or pUnit.getUnitType() == iUnitStarbaseIII):
				return 0
			
			# if there are any Construction Ships already building a Starbase then disallow more	
			if (pUnit.getBuildType() == iBuildStarbase):
				iNumUnits += 1
				if (iNumUnits > 1):	# Account for the one unit actually performing the mission
					return 0
		
		return 1

So far so good.

And this is what my version now looks like to try and build the Orion Starbase
Spoiler :
Code:
def onUnitBuildImprovement(self, argsList):
		'Unit begins enacting a Build (building an Improvement or Route)'
		pUnit, iBuild, bFinished = argsList
		
		iBuildStarbaseID = CvUtil.findInfoTypeNum(gc.getBuildInfo,gc.getNumBuildInfos(),'BUILD_STARBASE')
		iBuildOrionStarbaseD = CvUtil.findInfoTypeNum(gc.getBuildInfo,gc.getNumBuildInfos(),'BUILD_ORION_STARBASE')
		
		# Starbase WAS built
		if (iBuild == iBuildStarbaseID):
			pUnit.setScriptData("BuildingStarbase")

	def onImprovementBuilt(self, argsList):
		'Improvement Built'
		iImprovement, iX, iY = argsList
		
		iImprovementStarbaseID = CvUtil.findInfoTypeNum(gc.getImprovementInfo,gc.getNumImprovementInfos(),'IMPROVEMENT_STARBASE')
		iImprovementOrionStarbaseD = CvUtil.findInfoTypeNum(gc.getImprovementInfo,gc.getNumImprovementInfos(),'IMPROVEMENT_ORION_STARBASE')
		iUnitConstructShipID = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_CONSTRUCT_SHIP')
		
		# Starbase finished
		if (iImprovement() == iImprovementStarbaseID or iImprovement() == iImprovementOrionStarbaseD):
			pPlot = CyMap().plot(iX, iY)
			pPlot.setImprovementType(-1)
			
			# Look for Construction Ship on this plot
			for iUnitLoop in range(pPlot.getNumUnits()):
				pUnit = pPlot.getUnit(iUnitLoop)
				
				if (pUnit.getScriptData() == "BuildingStarbase"):
					self.doMakeStarbase(pUnit.getOwner(), iX, iY)
					self.aiKillTimerData = [3, pUnit.getOwner(), pUnit.getID()]
#					pUnit.kill(true, -1)
	
	def doMakeStarbase(self, iPlayer, iX, iY):
		
		pPlayer = gc.getPlayer(iPlayer)
		pPlot = CyMap().plot(iX, iY)
		
		# Create Starbase Unit
		iUnitStarbaseID = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_STARBASE_I')
		iUnitOrionStarbaseD = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_ORION_STARBASE')
		pPlayer.initUnit(iUnitStarbaseID, iX, iY, UnitAITypes.UNITAI_ATTACK, DirectionTypes.NO_DIRECTION)
		pPlayer.initUnit(iUnitOrionStarbaseD, iX, iY, UnitAITypes.UNITAI_ATTACK, DirectionTypes.NO_DIRECTION)
		
		self.updateStarbaseCulture(iPlayer, iX, iY)
		
	def updateStarbaseCulture(self, iPlayer, iX, iY):
		
		# Create culture around unit
		for iXLoop in range(iX-2, iX+3):
			for iYLoop in range(iY-2, iY+3):
				
				iActiveX = iXLoop
				iActiveY = iYLoop
				
				if (iActiveX < 0):
					iActiveX = CyMap().getGridWidth() + iActiveX
				if (iActiveY < 0):
					iActiveY = CyMap().getGridHeight() + iActiveY
				
				pLoopPlot = CyMap().plot(iActiveX, iActiveY)
#				pPlotLoop = CyMap().plot(iXLoop, iYLoop)
#				printd("Setting Player %d as the owner of %d, %d" %(iPlayer, iXLoop, iYLoop))
				# Don't override culture that's already here
				if (pLoopPlot.getOwner() == -1):
					pLoopPlot.setOwnerNoUnitCheck(iPlayer)
		
	def updateAllStarbases(self):
		
		# Update Starbase culture
		iUnitStarbaseID = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_STARBASE_I')
		iUnitOrionStarbaseD = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_ORION_STARBASE')
		iUnitStarbaseIID = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_STARBASE_II')
		iUnitStarbaseIIID = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_STARBASE_III')
		iUnitMissileI = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_MISSILE_I')
		iUnitMissileII = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_MISSILE_II')
		iUnitMissileIII = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_MISSILE_III')
		
		# List made to preserve culture of units built first
		aaiStarbaseList = []
		
		for iPlayerLoop in range(gc.getMAX_CIV_PLAYERS()):
			pPlayer = gc.getPlayer(iPlayerLoop)
			pTeam = gc.getTeam(pPlayer.getTeam())
			pyPlayer = PyPlayer(iPlayerLoop)
			
			iUnitToCreate = -1
			aiPossibleUnitList = [iUnitMissileI, iUnitMissileII, iUnitMissileIII]
			
			for iUnitLoop in aiPossibleUnitList:
				
				pUnitInfo = gc.getUnitInfo(iUnitLoop)
				iNeededTech = pUnitInfo.getPrereqAndTech()
				
				if (pTeam.isHasTech(iNeededTech)):
					iUnitToCreate = iUnitLoop
			
			apUnitList = pyPlayer.getUnitList()
			for pUnitLoop in apUnitList:
				if (pUnitLoop.getUnitType() == iUnitStarbaseID or pUnitLoop.getUnitType() == iUnitOrionStarbaseD or pUnitLoop.getUnitType() == iUnitStarbaseIID or pUnitLoop.getUnitType() == iUnitStarbaseIIID):
					aaiStarbaseList.append([pUnitLoop.getGameTurnCreated(), iPlayerLoop, pUnitLoop.getX(), pUnitLoop.getY()])
					
					# Need appropriate tech to create Missile
					if (iUnitToCreate != -1):
						# Need appropriate turn to create
						iTurnCreated = pUnitLoop.getGameTurnCreated()
						iCurrentTurn = CyGame().getGameTurn()
						
						if (iTurnCreated != iCurrentTurn):
							iTurnsSinceCreation = iCurrentTurn - iTurnCreated
							# Produce Missile every 15 turns
							if (iTurnsSinceCreation % 15 == 0):
								print "UnitID: %d, X: %d, Y: %d" %(iUnitToCreate, pUnitLoop.getX(), pUnitLoop.getY())
								pUnit = pPlayer.initUnit(iUnitToCreate, pUnitLoop.getX(), pUnitLoop.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.NO_DIRECTION)
								# Load Missile onto Starbase... the C++ doesn't like this but it can deal :)
								pUnit.setTransportUnit(pUnitLoop)
		
#		printd("\n\nXXX: There are %d Starbases on the map" %(len(aaiStarbaseList)))
#		printd(aaiStarbaseList)
			
		if (len(aaiStarbaseList) > 0):
			
			# Make order such that units built first get culture preference
			aaiStarbaseList.sort()
#			aaiStarbaseList.reverse()
			
			for iStarbaseLoop in range(len(aaiStarbaseList)):
				self.updateStarbaseCulture(aaiStarbaseList[iStarbaseLoop][1], aaiStarbaseList[iStarbaseLoop][2], aaiStarbaseList[iStarbaseLoop][3])
		
	def canBuildStarbase(self, pPlot, iOffset=0):
		
		# Starbase restriction
		iBuildStarbase = CvUtil.findInfoTypeNum(gc.getBuildInfo,gc.getNumBuildInfos(),'BUILD_STARBASE')
		iBuildOrionStarbase = CvUtil.findInfoTypeNum(gc.getBuildInfo,gc.getNumBuildInfos(),'BUILD_ORION_STARBASE')
		
		# Can't build on a Solar System
		iFeatureIDSolarSystem = CvUtil.findInfoTypeNum(gc.getFeatureInfo,gc.getNumFeatureInfos(),'FEATURE_SOLAR_SYSTEM')
		if (pPlot.getFeatureType() == iFeatureIDSolarSystem):
			return 0
		
		# Can't build on top of another Starbase
		iUnitStarbaseI = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_STARBASE_I',)
		iUnitOrionStarbase = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_ORION_STARBASE',)
		iUnitStarbaseII = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_STARBASE_II')
		iUnitStarbaseIII = CvUtil.findInfoTypeNum(gc.getUnitInfo,gc.getNumUnitInfos(),'UNIT_STARBASE_III')
		
		iNumUnits = iOffset # Offset so that Interface can disable button
		
		# Loop through all units on the plot
		for iUnitLoop in range(pPlot.getNumUnits()):
			pUnit = pPlot.getUnit(iUnitLoop)
			
			# Can't build on top of another Starbase
			if (pUnit.getUnitType() == iUnitStarbaseI or pUnit.getUnitType()== iUnitOrionStarbase or pUnit.getUnitType() == iUnitStarbaseII or pUnit.getUnitType() == iUnitStarbaseIII):
				return 0
			
			# if there are any Construction Ships already building a Starbase then disallow more	
			if (pUnit.getBuildType() == iBuildStarbase or pUnit.getBuildType()== iBuildOrionStarbase):
				iNumUnits += 1
				if (iNumUnits > 1):	# Account for the one unit actually performing the mission
					return 0
		
		return 1

I'm fairly sure some of it is correct but but i can't figure out from looking at other bits of Python exactly which parts are right and which are wrong. Is there a program i can download that will at least show me where the problem is? (or better yet, fix the problem).
Alternatively, can someone have a look at what i've done and tell me what my errors are, i'm trying to learn this stuff and i'm a patient man but i also know my limitations and at the moment i'm limited to copying other lines of python so it at least looks like it should work.:lol:

Thanks in advance
 
are you sure the doMakeStarbase is correct?
because you have there
Code:
pPlayer.initUnit(iUnitStarbaseID, iX, iY, UnitAITypes.UNITAI_ATTACK, DirectionTypes.NO_DIRECTION)
pPlayer.initUnit(iUnitOrionStarbaseD, iX, iY, UnitAITypes.UNITAI_ATTACK, DirectionTypes.NO_DIRECTION)
 
Top Bottom