Seeking Possible Collaboration for Scenario(s)!

This code seems to do nothing!!! The idea is that tile (12,12) is triggered if a unit is on it at the start of a turn and it causes any units or improvements on tile (13,13) to be removed.

Code:
	def onBeginGameTurn(self, argsList):
		'Called at the beginning of the end of each turn'
		iGameTurn = argsList[0]

		iOrthusTurn = 75
		if not CyGame().isUnitClassMaxedOut(gc.getInfoTypeForString('UNITCLASS_ORTHUS'), 0):
			if not CyGame().isOption(gc.getInfoTypeForString('GAMEOPTION_NO_ORTHUS')):
				bOrthus = False
				if CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_QUICK'):
					if iGameTurn >= iOrthusTurn / 3 * 2:
						bOrthus = True
				if CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_NORMAL'):
					if iGameTurn >= iOrthusTurn:
						bOrthus = True
				if CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_EPIC'):
					if iGameTurn >= iOrthusTurn * 3 / 2:
						bOrthus = True
				if CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_MARATHON'):
					if iGameTurn >= iOrthusTurn * 3:
						bOrthus = True
				if bOrthus:
					iUnit = gc.getInfoTypeForString('UNIT_ORTHUS')
					cf.addUnit(iUnit)
					cf.addPopup(CyTranslator().getText("TXT_KEY_POPUP_ORTHUS_CREATION",()), str(gc.getUnitInfo(iUnit).getImage()))



	#MY CODE STARTS HERE!#

        pPlot = CyMap().plot(12,12)
        if (pPlot.getNumUnits() > 0):
		pPlot = CyMap().plot(13,13)
		if gc.getImprovementInfo(pPlot.getImprovementType()).isPermanent() == False:
				if pPlot.isWater() == False:
						pPlot.setImprovementType(-1)
						pPlot.setFeatureType(-1, -1)
						pPlot.setBonusType(-1)
						pPlot.setPlotType(PlotTypes.PLOT_OCEAN, True, True)
						for i in range(pPlot.getNumUnits()):
								pUnit = pPlot.getUnit(i)
								if not pUnit.isHasPromotion(gc.getInfoTypeForString('PROMOTION_WATER_WALKING')):
										if not pUnit.isHasPromotion(gc.getInfoTypeForString('PROMOTION_FLYING')):
												pUnit.kill(False, PlayerTypes.NO_PLAYER)

										

		if not CyGame().isOption(gc.getInfoTypeForString('GAMEOPTION_NO_PLOT_COUNTER')):
			cf.doHellTerrain()

		if CyGame().getWBMapScript():
			sf.doTurn()

In Notepad++ my code isn't indented the same length as def onBeginGame but when I pasted here, it is. Can anyone work out what's going wrong with this code please???
 
[..]
In Notepad++ my code isn't indented the same length as def onBeginGame but when I pasted here, it is. Can anyone work out what's going wrong with this code please??

all i can suggest is to manually re-indent the code again and not mixing tabs and spaces for indenting
 
MagisterCultuum fixed the code up! (Thank you heaps MC!) If a unit is in the trigger tile (12,12) at the start of a turn, then the target tile (13,13) has all non-flying and non-water walking units killed and the target tile (13,13) is turned into a water tile. However, this can remove a unique improvement at the current time (on the target tile). To get around problems transforming a land tile to a water tile, flying/water walking units are moved off the tile and moved back onto it.

Code:
	def onBeginGameTurn(self, argsList):
		'Called at the beginning of the end of each turn'
		iGameTurn = argsList[0]

		iOrthusTurn = 75
		if not CyGame().isUnitClassMaxedOut(gc.getInfoTypeForString('UNITCLASS_ORTHUS'), 0):
			if not CyGame().isOption(gc.getInfoTypeForString('GAMEOPTION_NO_ORTHUS')):
				bOrthus = False
				if CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_QUICK'):
					if iGameTurn >= iOrthusTurn / 3 * 2:
						bOrthus = True
				if CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_NORMAL'):
					if iGameTurn >= iOrthusTurn:
						bOrthus = True
				if CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_EPIC'):
					if iGameTurn >= iOrthusTurn * 3 / 2:
						bOrthus = True
				if CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_MARATHON'):
					if iGameTurn >= iOrthusTurn * 3:
						bOrthus = True
				if bOrthus:
					iUnit = gc.getInfoTypeForString('UNIT_ORTHUS')
					cf.addUnit(iUnit)
					cf.addPopup(CyTranslator().getText("TXT_KEY_POPUP_ORTHUS_CREATION",()), str(gc.getUnitInfo(iUnit).getImage()))


		#MY CODE STARTS HERE!#
		if CyMap().plot([COLOR="Red"]12,12[/COLOR]).getNumUnits() > 0:
				pPlot = CyMap().plot([COLOR="Red"]13,13[/COLOR])
			#if not gc.getImprovementInfo(pPlot.getImprovementType()).isPermanent():
				if not pPlot.isWater():
					iWW = gc.getInfoTypeForString('PROMOTION_WATER_WALKING')
					iF = gc.getInfoTypeForString('PROMOTION_FLYING')
					pPlotTemp = cf.findClearPlot(-1, pPlot)
					for i in range(pPlot.getNumUnits()):
						pUnit = pPlot.getUnit(i)
						if not (pUnit.isHasPromotion(iWW) or pUnit.isHasPromotion(iF)):
								pUnit.kill(False, PlayerTypes.NO_PLAYER)
						else:
							pUnit.setXY(pPlotTemp.getX(), pPlotTemp.getY(), False, True, True)
					pPlot.setImprovementType(-1)
					pPlot.setFeatureType(-1, -1)
					pPlot.setBonusType(-1)
					pPlot.setPlotType(PlotTypes.PLOT_OCEAN, True, True)
					for i in range(pPlotTemp.getNumUnits()):
						pUnit = pPlotTemp.getUnit(i)
						pUnit.setXY([COLOR="Red"]13, 13[/COLOR], False, True, True)		
		
					
		if not CyGame().isOption(gc.getInfoTypeForString('GAMEOPTION_NO_PLOT_COUNTER')):
			cf.doHellTerrain()

		if CyGame().getWBMapScript():
			sf.doTurn()


Note to self - can the warningpost function mentioned in this post http://forums.civfanatics.com/showpost.php?p=5826059&postcount=3 do the trigger as a one time only action?
 
This code creates a popup text with a picture on a particular game turn.


Step 1:

The code is added to CvEventManager.py. Make sure it is in the section called def onBeginGameTurn. I suggest placing it in the same spot I have in this example.

Code:
	def onBeginGameTurn(self, argsList):
		'Called at the beginning of the end of each turn'
		iGameTurn = argsList[0]

		iOrthusTurn = 75
		if not CyGame().isUnitClassMaxedOut(gc.getInfoTypeForString('UNITCLASS_ORTHUS'), 0):
			if not CyGame().isOption(gc.getInfoTypeForString('GAMEOPTION_NO_ORTHUS')):
				bOrthus = False
				if CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_QUICK'):
					if iGameTurn >= iOrthusTurn / 3 * 2:
						bOrthus = True
				if CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_NORMAL'):
					if iGameTurn >= iOrthusTurn:
						bOrthus = True
				if CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_EPIC'):
					if iGameTurn >= iOrthusTurn * 3 / 2:
						bOrthus = True
				if CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_MARATHON'):
					if iGameTurn >= iOrthusTurn * 3:
						bOrthus = True
				if bOrthus:
					bvalid=true
					for i in range (CyMap().numPlots()):
						pPlot = CyMap().plotByIndex(i)
						iPlot = -1
						if pPlot.getImprovementType()==gc.getInfoTypeForString('IMPROVEMENT_GOBLIN_FORT'):														
							bPlayer = gc.getPlayer(gc.getBARBARIAN_PLAYER())
							if not pPlot.isVisibleOtherUnit(gc.getBARBARIAN_PLAYER()):
								bPlayer.initUnit(gc.getInfoTypeForString('UNIT_ORTHUS'), pPlot.getX(), pPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)
								bvalid=false
								break
					if bvalid:				
						iUnit = gc.getInfoTypeForString('UNIT_ORTHUS')
						cf.addUnit(iUnit)
						if( CyGame().getAIAutoPlay(CyGame().getActivePlayer()) == 0 ) :
							cf.addPopup(CyTranslator().getText("TXT_KEY_POPUP_ORTHUS_CREATION",()), str(gc.getUnitInfo(iUnit).getImage()))

		#Text with Picture code#
		iTextPictureTurn = [COLOR="Red"]5[/COLOR]
		bTextPicture = False
		if CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_QUICK'):
			if iGameTurn == iTextPictureTurn / 3 * 2:
				bTextPicture = True
		if CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_NORMAL'):
			if iGameTurn == iTextPictureTurn:
				bTextPicture = True
		if CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_EPIC'):
			if iGameTurn == iTextPictureTurn * 3 / 2:
				bTextPicture = True
		if CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_MARATHON'):
			if iGameTurn == iTextPictureTurn * 3:
				bTextPicture = True
				
		if bTextPicture:
			cf.addPopup('[COLOR="Red"]I am Vampire, hear me roar![/COLOR]','[COLOR="Red"]art/interface/popups/Alexis.dds[/COLOR]')
		
		#This example uses the Alexis picture which is inside the large art file#
		#Text with Picture code ends here#



Step 2:


You can either use the art already included or add your own whatever.dds artwork (as long as it is in the art folder of FFH2). I suggest creating the folder: art/interface/newpopups. Put the whatever.dds file into this folder. The command line to access this file becomes: cf.addPopup(CyTranslator().getText("TXT_KEY_POPUP_DEFEATED_CALABIM",()),'art/interface/newpopups/whatever.dds')



Help Part 2! How can I add text only popups?
 
Kael's tutorial on how to make popups that allow multiple choices and it remembers your choice. Down the page it also has an alternative method of doing a popup text + picture.

http://forums.civfanatics.com/showthread.php?t=183126 Snarko made the point that (in the second section of code) pPlayer = gc.getPlayer(iData) should be pPlayer = gc.getPlayer(iData1) since iData1 is where all the information was saved to.
Also the iPlayerNum Kael uses is redundant code since the "for" loop cycles through all players for iPlayer in range(gc.getMAX_PLAYERS()):

NOTES TO SELF:
- Used in ScenarioFunctions.py
- if gc.getGame().getScenarioCounter() == 20:
- gc.getGame().changeScenarioCounter(-20)
- the integer in the changeScenarioCounter seems to be the amount added to the score
- I can't find where the ScenarioCounter is set initially (to zero presumably)
- gc = CyGlobalContext
- Kael's tutorial says they are called CyGame - what is the difference between CyGame and CyGlobalContext?
<Snarko>: One calls CyGame(). The other calls a function of CyGlobalContext which returns CyGame(). The result is about as identical as they can be without being exactly the same.
<Snarko>: [CyGame is] defined in the DLL and is an interface to CvGame, which is where the stuff really happens.
<Snarko>: CyGame is a class in the DLL. It is also exposed to python, so that you can call it in python.
<Snarko>: It doesn't actually do anything though. All it does is pass on the information to CvGame, which is the "real" Game class that actually does stuff.
- CvGame is C++ code in the SDK.

- Snarko's help:
- pPlayer = gc.getPlayer(iData1) sets pPlayer to point to the player object with ID iData1.
- If you aren't doing anything on the player then you don't need that stuff.
 
This code creates a multiple choice menu without a picture on a particular game turn. The options in this example add (or subtract if a negative number is used) from a counter that will be saved with the game. Fewer or more options can be added to the menu (it needs fewer/more lines on both files - see comments).

The code needs to be added to 2 files - CvEventManager.py and CvScreensInterface.py. Text in red writing is what you change for your own words and number values.

Thanks to all who helped with this code - Snarko, anw, Jheral. :)


Step 1:

The code is added to CvEventManager.py. Make sure it is in the section called def onBeginGameTurn. I suggest placing it in the same spot I have in this example.

Code:
	def onBeginGameTurn(self, argsList):
		'Called at the beginning of the end of each turn'
		iGameTurn = argsList[0]

		iOrthusTurn = 75
		if not CyGame().isUnitClassMaxedOut(gc.getInfoTypeForString('UNITCLASS_ORTHUS'), 0):
			if not CyGame().isOption(gc.getInfoTypeForString('GAMEOPTION_NO_ORTHUS')):
				bOrthus = False
				if CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_QUICK'):
					if iGameTurn >= iOrthusTurn / 3 * 2:
						bOrthus = True
				if CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_NORMAL'):
					if iGameTurn >= iOrthusTurn:
						bOrthus = True
				if CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_EPIC'):
					if iGameTurn >= iOrthusTurn * 3 / 2:
						bOrthus = True
				if CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_MARATHON'):
					if iGameTurn >= iOrthusTurn * 3:
						bOrthus = True
				if bOrthus:
					bvalid=true
					for i in range (CyMap().numPlots()):
						pPlot = CyMap().plotByIndex(i)
						iPlot = -1
						if pPlot.getImprovementType()==gc.getInfoTypeForString('IMPROVEMENT_GOBLIN_FORT'):														
							bPlayer = gc.getPlayer(gc.getBARBARIAN_PLAYER())
							if not pPlot.isVisibleOtherUnit(gc.getBARBARIAN_PLAYER()):
								bPlayer.initUnit(gc.getInfoTypeForString('UNIT_ORTHUS'), pPlot.getX(), pPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)
								bvalid=false
								break
					if bvalid:				
						iUnit = gc.getInfoTypeForString('UNIT_ORTHUS')
						cf.addUnit(iUnit)
						if( CyGame().getAIAutoPlay(CyGame().getActivePlayer()) == 0 ) :
							cf.addPopup(CyTranslator().getText("TXT_KEY_POPUP_ORTHUS_CREATION",()), str(gc.getUnitInfo(iUnit).getImage()))
		
		
		#Example menu#
		iExampleMenuTurn = [COLOR="Red"]3[/COLOR]
		bExampleMenu = False
		if CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_QUICK'):
			if iGameTurn == iExampleMenuTurn / 3 * 2:
				bExampleMenu = True
		if CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_NORMAL'):
			if iGameTurn == iExampleMenuTurn:
				bExampleMenu = True
		if CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_EPIC'):
			if iGameTurn == iExampleMenuTurn * 3 / 2:
				bExampleMenu = True
		if CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_MARATHON'):
			if iGameTurn == iExampleMenuTurn * 3:
				bExampleMenu = True				
				
		if bExampleMenu:
			for iPlayer in range(gc.getMAX_PLAYERS()):
				player = gc.getPlayer(iPlayer)
				if player.isAlive():					
					if player.isHuman():
						popupInfo = CyPopupInfo()
						popupInfo.setButtonPopupType(ButtonPopupTypes.BUTTONPOPUP_PYTHON)
						popupInfo.setText('[COLOR="Red"]This is the menu.  Choose one option:[/COLOR]')
						popupInfo.setData1(iPlayer)
						popupInfo.setOnClickedPythonCallback("ExampleCounterCallBack")
						#Copy a line/s below to add a button/s or delete a line/s below to remove a button/s.#
						popupInfo.addPythonButton('[COLOR="Red"]Add 3 points to the example counter[/COLOR]', "")
						popupInfo.addPythonButton('[COLOR="Red"]Add 7 points to the example counter[/COLOR]', "")
						popupInfo.addPythonButton('[COLOR="Red"]Add 11 points to the example counter[/COLOR]', "")
						popupInfo.addPythonButton('[COLOR="Red"]Add 13 points to the example counter[/COLOR]', "")
						popupInfo.addPythonButton('[COLOR="Red"]Add 17 points to the example counter[/COLOR]', "")
						popupInfo.addPopup(iPlayer)
		#End of Example Menu#
													
							
		if not CyGame().isOption(gc.getInfoTypeForString('GAMEOPTION_NO_PLOT_COUNTER')):
			cf.doHellTerrain()

		if CyGame().getWBMapScript():
			sf.doTurn()


Step 2:

The code is added to CvScreensInterface.py. I suggest placing it somewhere with the other menu codes. Therefore, I suggest placing it just before the line def reassignPlayer(argsList):

Code:
#My Example Counter Menu#
def ExampleCounterCallBack(argsList):
	iButtonId = argsList[0]
	iData1 = argsList[1]
	iData2 = argsList[2]
	iData3 = argsList[3]
	iData4 = argsList[4]
	szText = argsList[5]
	bOption1 = argsList[6]
	bOption2 = argsList[7]

	#iButttonId 0 is the first menu button so having 0 to 4 is for 5 menu choices.  If you have 4 menu choices then remove the last 2 lines of this section.  If you add another choice then copy the 2 lines of code (and make it [I]if iButtonId == 5:[/I] ). #
	if iButtonId == 0:
		CyGlobalContext().getGame().changeScenarioCounter([COLOR="Red"]3[/COLOR])
	if iButtonId == 1:
		CyGlobalContext().getGame().changeScenarioCounter([COLOR="Red"]7[/COLOR])
	if iButtonId == 2:
		CyGlobalContext().getGame().changeScenarioCounter([COLOR="Red"]11[/COLOR])
	if iButtonId == 3:
		CyGlobalContext().getGame().changeScenarioCounter([COLOR="Red"]13[/COLOR])
	if iButtonId == 4:
		CyGlobalContext().getGame().changeScenarioCounter([COLOR="Red"]17[/COLOR])
		
	#This section below can be added to for it to do something if the counter is a certain value (otherwise it does nothing).  The counter can be 10 if, for example, the counter was already equal to 7 and you chose the first menu choice which adds 3 to the counter (making the total equal to 10).#
	if CyGlobalContext().getGame().getScenarioCounter() == [COLOR="Red"]3[/COLOR]:
				
	if CyGlobalContext().getGame().getScenarioCounter() == [COLOR="Red"]7[/COLOR]:
		
	if CyGlobalContext().getGame().getScenarioCounter() == [COLOR="Red"]10[/COLOR]:
 
Notes to self on creating savable variables in python. This would allow me to check if any unit has entered a particular tile yet. So in the flames code in this thread, instead of causing flames every time a unit enters the tile, it could be made to only happen the first time (the game would save a variable that remembers the action has been triggered).

http://pastebin.com/q3CY6zSB in SdToolKit.py

anw:
- in the file you want to use some variables put "import SdToolKit" and then when you want to use them use "SdToolKit.sdGetGlobal("MyUniqueName", xxx)" and "SdToolKit.sdSetGlobal("MyUniqueName", "xxx", newValue)" where MyUniqueName is your unique name, xxx is a name of variable and newValue is new value




EDIT: Maybe define TileEntered = 0 at the onGameStart section. The problem is that it won't be remembered with saving-loading.
Another option might be to create a unique unit when the tile is entered and then kill the unit but the game will remember that it has been created (similar to Orthus' code) and I can use whether the unit has been created or not to tell me whether a unit has entered the tile or not.
Another option is using getScriptData and setScriptData which anw/greyfox reckon can store data. "<anw>: make a spell available for all units that would just get the scriptdata from the plot the unit is standing on, increment it by 1 and save it again to that plot and make a message that would just say the number"
Code:
		pPlot = CyMap().plot(10,5)
		if (pPlot.getNumUnits() > 0):
				if TileEntered == 0:
						TileEntered = 1
						#First flame#
						pPlot = CyMap().plot(8,5)
						if (pPlot.getFeatureType() == gc.getInfoTypeForString('FEATURE_FOREST') or pPlot.getFeatureType() == gc.getInfoTypeForString('FEATURE_JUNGLE')):
								pPlot.setFeatureType(gc.getInfoTypeForString('FEATURE_FLAMES'), 0)	
						#Second flame#
						pPlot = CyMap().plot(9,5)
						if (pPlot.getFeatureType() == gc.getInfoTypeForString('FEATURE_FOREST') or pPlot.getFeatureType() == gc.getInfoTypeForString('FEATURE_JUNGLE')):
								pPlot.setFeatureType(gc.getInfoTypeForString('FEATURE_FLAMES'), 0)	
						#Third flame#
						pPlot = CyMap().plot(11,5)
						if (pPlot.getFeatureType() == gc.getInfoTypeForString('FEATURE_FOREST') or pPlot.getFeatureType() == gc.getInfoTypeForString('FEATURE_JUNGLE')):
								pPlot.setFeatureType(gc.getInfoTypeForString('FEATURE_FLAMES'), 0)	
						#Fourth flame#
						pPlot = CyMap().plot(12,5)
						if (pPlot.getFeatureType() == gc.getInfoTypeForString('FEATURE_FOREST') or pPlot.getFeatureType() == gc.getInfoTypeForString('FEATURE_JUNGLE')):
								pPlot.setFeatureType(gc.getInfoTypeForString('FEATURE_FLAMES'), 0)
 
Notes to self on creating savable variables in python. This would allow me to check if any unit has entered a particular tile yet. So in the flames code in this thread, instead of causing flames every time a unit enters the tile, it could be made to only happen the first time (the game would save a variable that remembers the action has been triggered).

http://pastebin.com/q3CY6zSB in SdToolKit.py

anw:
- in the file you want to use some variables put "import SdToolKit" and then when you want to use them use "SdToolKit.sdGetGlobal("MyUniqueName", xxx)" and "SdToolKit.sdSetGlobal("MyUniqueName", "xxx", newValue)" where MyUniqueName is your unique name, xxx is a name of variable and newValue is new value

If you're using MNAI as a base you can also use SdToolKitCustom. It has some additional methods; while SdToolKit stores all data in the game scriptdata (IIRC), SdToolKitCustom allows storing data in scriptdata of other objects, such as players:
Code:
# from Revolutions.py
if( [B]SdToolKitCustom.sdObjectExists( 'BarbarianCiv', pPlayer )[/B] and not RevInstances.BarbarianCivInst == None ) :
	if( self.LOG_DEBUG ) : CvUtil.pyPrint("  Revolt - Setting new rebel player as barb civ since motherland is")
	RevInstances.BarbarianCivInst.setupSavedData( pRevPlayer.getID(), bSetupComplete = 1 )
if( pPlayer.isMinorCiv() ) :
	if( self.LOG_DEBUG ) : CvUtil.pyPrint("  Revolt - Setting new rebel player as minor civ since motherland is")
	pRevTeam.setIsMinorCiv( True, False )
	if( [B]SdToolKitCustom.sdObjectExists( 'BarbarianCiv', game )[/B] ) :
		# If motherland is on always minor list, put rebel on as well
		alwaysMinorList = [B]SdToolKitCustom.sdObjectGetVal( "BarbarianCiv", game, "AlwaysMinorList" )[/B]
		if( not alwaysMinorList == None and pPlayer.getID() in alwaysMinorList ) :
			alwaysMinorList.append(pRevPlayer.getID())
			[B]SdToolKitCustom.sdObjectSetVal( "BarbarianCiv", game, "AlwaysMinorList", alwaysMinorList )[/B]
Spreading data over more than one object can improve performance.
 
Note to self: create code to make a city invincible (e.g. units attacked inside the city have damage reduced to 0).

I think it would be better to make the city impassable for enemy units. It's probably easier (but maybe slower); this way there is also a chance the AI understands it.
 
The code for making a city's plot impassible under certain circumstances can easily be borrowed from my modmod. This would however requiring activating the def unitCannotMoveInto(self,argsList): callback, which can slow the game significantly.

If you specifically want a certain plot (whether it contains a city or not) to be impassible to either all human players or all AI players, or both, then there is a far more efficient solution which does not seem to slow the game down at all. You simply use pPlot.setMoveDisabledHuman(True), pPlot.setMoveDisabledAI(True), or both.

There is not however such an efficient means to make it impassible only to specific players. There could be issues where the city becomes impassible to units belonging to the same owner. You would still be able to train units there, but once they leave the city's tile they could not return.

If you specifically want to make the units in a city heal completely after combat, I suppose you could place that code in CvEventManager.py's def onCombatResult(self, argsList):. You could check to see is the unit was on the city's plot, and then heal it completely. You could also make a unit immortal after it loses in combat but before it actually dies.
 
Basically I'm planning a scenario of the Bannor escaping hell and I'm working on bits of useful code. I want the main city Dis to be invincible to the human player.

So the options for making the city invincible are:
1) make the tile impassible to human (prevents you attacking it?)
2) don't let units die in the tile
3) give a huge defensive bonus to the city which can't be reduced by artillery
4) surround Dis by fire which the Bannor cannot pass but give infernal fire resistance
5) make units in Dis heal completely after combat before they die

Option 1) using the command p.plotSetmovedisabledhuman(True) seems the best way then?






Ideas to be coded:
Spoiler :

  1. Disease siege defence:
    Triggered by an event ("One of your scientists has suggested that we fight off our enemies by throwing our diseased dead at them.") If the player chooses yes then +2 unhealthiness in the city. If an enemy siege unit (to replicate a proper long term siege) is adjacent to that city then all units that tile are given the diseased promotion every turn. It also adds to the CC in the Bannor escaping hell scenario.​
  2. Counter of how many living(?) units have been killed. Might be useful for my pawns of the gods game (for Arawn's VC).
  3. Determine what percentage of tiles are forested (inc. ancient forests). Have something printed on screen permanently to show the %. It needs to show up permanently (in the same way it does in the Balseraphs scenario that Kael made) because the gods won't be playing the game - only the AI and maybe human will be.
  4. First unit or specific unit to move into a tile causes mountains or forests to rise up around them.
  5. Specific unit moves into a tile and all mountains adjacent are removed
    Maybe use getUnitInfo or getUnitType to determine what type of unit is on the tile​
    Maybe make a list of all units in the tile each turn and then if list.count(particular unit) is >0 then trigger the tile​
  6. A particular barbarian unit is only able to move around in certain tiles - e.g. a barbarian fawn only able to move +/-1 up and down, left and right around the tomb of Sucellus.
 
This code gives any unit on a particular tile the HELD promotion. It is placed in the file CvEventManager.py under onBeginGameTurn.

Code:
	def onBeginGameTurn(self, argsList):
		'Called at the beginning of the end of each turn'
		iGameTurn = argsList[0]

		iOrthusTurn = 75
		if not CyGame().isUnitClassMaxedOut(gc.getInfoTypeForString('UNITCLASS_ORTHUS'), 0):
			if not CyGame().isOption(gc.getInfoTypeForString('GAMEOPTION_NO_ORTHUS')):
				bOrthus = False
				if CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_QUICK'):
					if iGameTurn >= iOrthusTurn / 3 * 2:
						bOrthus = True
				elif CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_NORMAL'):
					if iGameTurn >= iOrthusTurn:
						bOrthus = True
				elif CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_EPIC'):
					if iGameTurn >= iOrthusTurn * 3 / 2:
						bOrthus = True
				elif CyGame().getGameSpeedType() == gc.getInfoTypeForString('GAMESPEED_MARATHON'):
					if iGameTurn >= iOrthusTurn * 3:
						bOrthus = True
				if bOrthus:
					bValid=True
					for i in range (CyMap().numPlots()):
						pPlot = CyMap().plotByIndex(i)
						iPlot = -1
						if pPlot.getImprovementType()==gc.getInfoTypeForString('IMPROVEMENT_GOBLIN_FORT'):
							bPlayer = gc.getPlayer(gc.getBARBARIAN_PLAYER())
							if not pPlot.isVisibleOtherUnit(gc.getBARBARIAN_PLAYER()):
								bPlayer.initUnit(gc.getInfoTypeForString('UNIT_ORTHUS'), pPlot.getX(), pPlot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)
								bValid=False
								break
					if bValid:
						iUnit = gc.getInfoTypeForString('UNIT_ORTHUS')
						cf.addUnit(iUnit)
						if( CyGame().getAIAutoPlay(CyGame().getActivePlayer()) == 0 ) :
							cf.addPopup(CyTranslator().getText("TXT_KEY_POPUP_ORTHUS_CREATION",()), str(gc.getUnitInfo(iUnit).getImage()))
							
		
		#NEW CODE STARTS HERE
		#This code should give all units in tile([COLOR="Red"]10[/COLOR],[COLOR="Red"]10[/COLOR]) the HELD promotion so that they can't move anywhere.
		pPlot = CyMap().plot([COLOR="Red"]10[/COLOR],[COLOR="Red"]10[/COLOR])
		for i in range(pPlot.getNumUnits()):
			pUnit = pPlot.getUnit(i)
			pUnit.setHasPromotion(gc.getInfoTypeForString('PROMOTION_[COLOR="Red"]HELD[/COLOR]'), True)
		#NEW CODE ENDS HERE

			
		if not CyGame().isOption(gc.getInfoTypeForString('GAMEOPTION_NO_PLOT_COUNTER')):
			cf.doHellTerrain()

		if CyGame().getWBMapScript():
			sf.doTurn()

# FfH Card Game: begin
		cs.doTurn()
# FfH Card Game: end

#		if( CyGame().getAIAutoPlay(self) == 0 ) :
		if( game.getAIAutoPlay(game.getActivePlayer()) == 0 ) :
			CvTopCivs.CvTopCivs().turnChecker(iGameTurn)
 
What if you just put a very strong Held unit on the tile? Four heroic defense 2, strong, heavy, C5, Drill 4, CG3, stigmata, fear, cannibalize, magic resistant, fire/air/cold resistant, mutated demon crossbowmen on a hill surrounded by rivers should be almost impossible to break. I wonder if even a juiced-up Yvain supported by a crown of brilliance+crush dwarven druid could do it.
 
Top Bottom