[SDK] Programming the AI to Perform a Unit Action

Modding certain Python files will make it impossible to play a multiplayer game effectively because whenever they are called you will get OOS errors. Anything using custom script data, for instance, will do this.

Script data? You mean the following code is guaranteed to cause OOS?
Does Final Frontier not work in multiplayer?

Code:
	def onUnitBuildImprovement(self, argsList):
		'Unit begins enacting a Build (building an Improvement or Route)'
		pUnit, iBuild, bFinished = argsList
		
		iBuildFortID = CvUtil.findInfoTypeNum(gc.getBuildInfo,gc.getNumBuildInfos(),'BUILD_FORT')
		iBuildFungalTowerID = CvUtil.findInfoTypeNum(gc.getBuildInfo,gc.getNumBuildInfos(),'BUILD_FUNGAL_TOWER')
		iBuildKelpID = CvUtil.findInfoTypeNum(gc.getBuildInfo,gc.getNumBuildInfos(),'BUILD_KELP_FARM')
		iWindmillSea = gc.getInfoTypeForString('IMPROVEMENT_WINDMILL_SEA')
		iMiningPlatform = gc.getInfoTypeForString('IMPROVEMENT_MINING_PLATFORM')
		iTidalHarness = gc.getInfoTypeForString('IMPROVEMENT_TIDAL_HARNESS')

		if (iBuild == iBuildKelpID):
			pPlot = pUnit.plot()
			if pPlot.getImprovementType() == iWindmillSea:
				pUnit.setScriptData("BuildingKelpOnMill")
			elif pPlot.getImprovementType() == iMiningPlatform:
				pUnit.setScriptData("BuildingKelpOnMine")
			elif pPlot.getImprovementType() == iTidalHarness:
				pUnit.setScriptData("BuildingKelpOnTidal")	
		elif (iBuild == iBuildFortID):
			pUnit.setScriptData("BuildingFort")
		elif (iBuild == iBuildFungalTowerID):
			pUnit.setScriptData("BuildingFungalTower")

	def onImprovementBuilt(self, argsList):
...
		elif iImprovement == gc.getInfoTypeForString('IMPROVEMENT_KELP_FARM'):
			pPlot.setFeatureType(gc.getInfoTypeForString('FEATURE_KELP'),0)
			for iUnitLoop in range(pPlot.getNumUnits()):
				pUnit = pPlot.getUnit(iUnitLoop)				
				if (pUnit.getScriptData() == "BuildingKelpOnMill"):
					pPlot.setImprovementType(iWindmillSea)
					pUnit.setScriptData("")
				elif (pUnit.getScriptData() == "BuildingKelpOnMine"):
					pPlot.setImprovementType(iMiningPlatform)
					pUnit.setScriptData("")
				elif (pUnit.getScriptData() == "BuildingKelpOnTidal"):
					pPlot.setImprovementType(iTidalHarness)
					pUnit.setScriptData("")
				else:
					pPlot.setImprovementType(-1)
					pUnit.setScriptData("")
 
Script data? You mean the following code is guaranteed to cause OOS?
Does Final Frontier not work in multiplayer?

Code:
    def onUnitBuildImprovement(self, argsList):
        'Unit begins enacting a Build (building an Improvement or Route)'
        pUnit, iBuild, bFinished = argsList
 
        iBuildFortID = CvUtil.findInfoTypeNum(gc.getBuildInfo,gc.getNumBuildInfos(),'BUILD_FORT')
        iBuildFungalTowerID = CvUtil.findInfoTypeNum(gc.getBuildInfo,gc.getNumBuildInfos(),'BUILD_FUNGAL_TOWER')
        iBuildKelpID = CvUtil.findInfoTypeNum(gc.getBuildInfo,gc.getNumBuildInfos(),'BUILD_KELP_FARM')
        iWindmillSea = gc.getInfoTypeForString('IMPROVEMENT_WINDMILL_SEA')
        iMiningPlatform = gc.getInfoTypeForString('IMPROVEMENT_MINING_PLATFORM')
        iTidalHarness = gc.getInfoTypeForString('IMPROVEMENT_TIDAL_HARNESS')
 
        if (iBuild == iBuildKelpID):
            pPlot = pUnit.plot()
            if pPlot.getImprovementType() == iWindmillSea:
                pUnit.setScriptData("BuildingKelpOnMill")
            elif pPlot.getImprovementType() == iMiningPlatform:
                pUnit.setScriptData("BuildingKelpOnMine")
            elif pPlot.getImprovementType() == iTidalHarness:
                pUnit.setScriptData("BuildingKelpOnTidal")    
        elif (iBuild == iBuildFortID):
            pUnit.setScriptData("BuildingFort")
        elif (iBuild == iBuildFungalTowerID):
            pUnit.setScriptData("BuildingFungalTower")
 
    def onImprovementBuilt(self, argsList):
...
        elif iImprovement == gc.getInfoTypeForString('IMPROVEMENT_KELP_FARM'):
            pPlot.setFeatureType(gc.getInfoTypeForString('FEATURE_KELP'),0)
            for iUnitLoop in range(pPlot.getNumUnits()):
                pUnit = pPlot.getUnit(iUnitLoop)                
                if (pUnit.getScriptData() == "BuildingKelpOnMill"):
                    pPlot.setImprovementType(iWindmillSea)
                    pUnit.setScriptData("")
                elif (pUnit.getScriptData() == "BuildingKelpOnMine"):
                    pPlot.setImprovementType(iMiningPlatform)
                    pUnit.setScriptData("")
                elif (pUnit.getScriptData() == "BuildingKelpOnTidal"):
                    pPlot.setImprovementType(iTidalHarness)
                    pUnit.setScriptData("")
                else:
                    pPlot.setImprovementType(-1)
                    pUnit.setScriptData("")

I don't know. Never played Final Frontier in multiplayer. I was referring to something like that used in Desert War, which dumps the script through pickle into player 0's save log...

Code:
 def setupScriptData( self ):
  """Initialise the global script data dictionary for usage."""
  scriptDict = { 'bKasserinePass': False,
     'bMarethLine': False,
     'bOperationBarbarossa': False,
     'bMiddleEast': False,
     'bStalingrad': False,
     'bParisLiberated': False,
     'bEnglandFallen': False,
     'bCapTimerOn': False,
     'bEndCapTimer': False,
     'bVictoryNextTurn': False,
     'bVictoryAchieved': False,
     'iExtraUnitCost': 0,
     'iParisLiberation': -1,
     'iEnglandFalls': -1,
     'iCapTimer': 0,
     'iVictoryTimer': 9,
     'tCapturedObjectivesList': []
    }
  gc.getPlayer(0).setScriptData( pickle.dumps(scriptDict) )

...which I was told would require an SDK change to make it multiplayer compatible. Obviously, not all custom Python causes OOS. Perhaps Final Frontier's SDK has been adjusted?
 
Really? Interesting. Then I suspect it uses a script already coded into the SDK, which is multiplayer compatible, not a special one like in Desert War.

On that note, could you direct me to the place where starbases automatically receive free culture/influence in the tiles surrounding them? I presume this is in Python since it is obviously not in C++.
 
Here's the method updateStarbaseCulture in CvFinalFrontierEvents.py (it's in a section labeled "Starbase Stuff").

Code:
	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)
 
Storing stuff in Script Data does not inherintly cause OOS errors. SDTookKit stores its data in Script Data and there are tons of mods that use it and work just fine in MP games.
 
Top Bottom