[PYTHON MODCOMP] zActions

Zebra 9

Emperor
Joined
May 17, 2006
Messages
1,554
Location
Middle of Cyberspace
This allows any person who has a knowledge of Civ Python to add new actions that can range from ranged bombardment to planting forests.

Limitations include units that use all of their moves don't end their turn and there is no AI.:(

I have included a sample that allows any worker (including fast workers) to plant forests and gives seige units the ability to bombard a 2 plot range damaging any enemy unit on the targeted plot.

Some of the code I copied from the spellDemo MOD COMP Thingy.

Usage Tutorial;)
Spoiler Usage :
The first step in adding an action using zActions is desiding what the action will be called, what it will do, when it will be able to be preformed, and what units can use it.
Once you have all the information above we need to convert it into python in the form of functions. Now because zActions requires you to create 6 functions I have created a system by which we can list all 6, and some other information, in one spot. The code for this goes in zActionsActions.py, so example code is blow:
Code:
zActionInfos.addZAction	(
		"Bombard City",						## Name
		"art/interface/buttons/actions/bombard.dds",		## Button
		getDistRangeFuncSquare(2),				## Plots it can hit
		canBombard,						## Tells if the action can be done
		canEverBombard,						## Tells if it can do action now
		canBombardOnPlot,					## Tells if action can be done on plot
		shouldBombard,						## Tells if action is recommended
		bombard,						## Does Action
		2							## Range
		)
Now the line that reads "Rand Bombard" tells python that the action is to be called Rand Bombard[/] (I couldn't think of anything else).
Now the line that reads "art/interface/buttons/actions/bombard.dds" tells python what button to use for the action.
Now the line that reads getDistRangeFuncSquare(2) tells python how to find the plots that can be bombarded, this code tells python that the most distant plot can not be more than 2 plots away from the active unit.
Now the line that reads canBombard tells python if the action can be preformed, it calls a function in zActionsFuncs.py.
Now the line that reads canEverBombard tells python if the active unit can preform the action, it calls a function in zActionsFuncs.py.
Now the line that reads canBombardOnPlot tells python if the action can be preform on a certain plot, it calls a function in zActionsFuncs.py.
Now the line that reads shouldBombard tells python if the action is recommended, it calls a function in zActionsFuncs.py.
Now the line that reads bombard tells python how to do the action, it calls a function in zActionsFuncs.py.

Next we need to create the nessicary functions in zActionsFuncs.py. First we will make the function canBombard, it looks like:
Code:
def canBombard(unit, action):
	if unit.getMoves() == unit.baseMoves() * 60:
		return False
	return True
Then we need to make canEverBombard, this function looks like:
Code:
def canEverBombard(unit, action):
	plot = unit.plot()
	if unit.getUnitCombatType() == gc.getInfoTypeForString("UNITCOMBAT_SIEGE"):
		return True
	return False
Next let's create canBombardOnPlot:
Code:
def canBombardOnPlot(unit, plot, action):
	if plot.getNumDefenders(-1) > 0:
		if plot.getBestDefender(-1, unit.getOwner(), unit, True, True, True).isNone() == False:
			return True
	return False
We will next make shouldBombard, it looks like:
Code:
def shouldBombard(unit, action):
	return False
Lastly, but most important, we will make bombard, it looks like:
Code:
def bombard(unit, plot, action):
	yUnit = plot.getBestDefender(-1, unit.getOwner(), unit, True, True, True)

	rand = CyGame().getSorenRandNum(90, 'Zebra9') + 10

	dmg = yUnit.getDamage()
	yUnit.setDamage(dmg + rand, -1)

	unit.setMoves(unit.getMoves() + 60)
	unit.setMadeAttack(True)
All of the arguments for the functions are pretty much self explanitory, but so you know action is an instance of the action that is currently being worked with. Now because zActions require a more in depth knowledge I havn't gone indepth explaining how everything works. This is just supposed to show the basic steps and give some information on how zActions works.


Download Here
Enjoy:cool:
 
Most of these stuff is "triggerable" via xml
There exists an early mod called something like "Plant Forest Mod"
Also the terraforming mod is triggered via xml, only the events are handled via python.
 
This bears a STONG resemblence to the SpellDemo mod including an identical comment on line 1416 of your CVMainInterface.py that says "for some reason if I put this all on 1 line it gives me a MemoryError or an "unidentifiable c++ exception". Not nice to use someone else's work without giving them credit. :(

Roger Bacon
 
Oh, I forgot to mention that bI did copy some of the spell demo code over. Sorry about that.

This can't be done with XML or Python until Zebra. However, the lack of AI is a major put off to me.
Weel AI could be implementedx by going through an AI's units at the bginning of their turn.
 
I'd like to see a python script that would allow artillery bombardment (or aircraft bombing missions) to have a user-defined percentage to randomly destroy a building in the attacked city.

Something that could be used as a stand-alone, or compatable with those of us who use Dale's Ranged Bombardment.


Think you could do something like that? :)
 
Yes that would be possible. I will see if I put that as an example script in the tut I will release this week (I'll post it for you as soon as possible).
 
Yes that would be possible. I will see if I put that as an example script in the tut I will release this week (I'll post it for you as soon as possible).

Sweet... thank you! I could never understand why Firaxis left destroying buildings via bombardment out of the game. It's a great way to cripple an enemy city.

I look forward to seeing your tutorial. :goodjob:
 
In the file zActionsActions.py put the below code:
Code:
zActionInfos.addZAction	(
		"Rand Bombard",						## Name
		"art/interface/buttons/actions/bombard.dds",		## Button
		getDistRangeFuncSquare(2),				## Plots it can hit
		canRandBombard,						## Tells if the action can be done
		canEverRandBombard,					## Tells if it can do action now
		canRandBombardOnPlot,					## Tells if action can be done on plot
		shouldRandBombard,					## Tells if action is recommended
		doRandBombard,						## Does Action
		2							## Range
		)
This tells python what to use to preform the action as well as give it some infomation about the action. Some thing you should know is that if you change the 2s to a different number it will change the range to that number. So if you set it to 3, any unit trying to preform the action will have a square around them that is 7 plots wide by 7 plots high (3 plots to it's left, right, back, and front, along with the plot it is standing on). Next put this code in the file titled zActionsFuncs.py:
Code:
def canEverRandBombard(unit, action):
	plot = unit.plot()
	if unit.getUnitCombatType() == gc.getInfoTypeForString("UNITCOMBAT_SIEGE") or unit.getDomainType() == gc.getInfoTypeForString("DOMAIN_AIR"):
		return True
	return False

def canRandBombard(unit, action):
	if unit.getMoves() == unit.baseMoves() * 60:
		return False
	return True

def canRandBombardOnPlot(unit, plot, action):
	if plot.getNumDefenders(-1) > 0:
		if plot.getBestDefender(-1, unit.getOwner(), unit, True, True, True).isNone() == False:
			return True
	elif plot.isCity() and (plot.getPlotCity().getNumBuildings() > 0 or plot.getPlotCity().getPopulation() > 1) and gc.getTeam(unit.getTeam()).isAtWar(plot.getPlotCity().getTeam()):
		return True
	return False

def doRandBombard(unit, plot, action):
	hitUnit = CyGame().getSorenRandNum(100, 'Zebra9') + 1
	if plot.getBestDefender(-1, unit.getOwner(), unit, True, True, True).isNone() == False and hitUnit <= 25:
		yUnit = plot.getBestDefender(-1, unit.getOwner(), unit, True, True, True)

		rand = CyGame().getSorenRandNum(90, 'Zebra9') + 10

		dmg = yUnit.getDamage()
		yUnit.setDamage(dmg + rand, -1)

	hitCity = CyGame().getSorenRandNum(100, 'Zebra9') + 1
	if plot.isCity() and gc.getTeam(unit.getTeam()).isAtWar(plot.getPlotCity().getTeam()) and hitCity <= 25:
		if plot.getPlotCity().getNumBuildings() > 0:
			for iBuilding in range(gc.getNumBuildingInfos()):
				if gc.getBuildingInfo(iBuilding).isNukeImmune() or plot.getPlotCity().isHasRealBuilding(iBuilding) == False:
					continue
				if CyGame().getSorenRandNum(100, 'Zebra9') + 1 <= 25:
					plot.getPlotCity().setHasRealBuilding(iBuilding, False)
		if plot.getPlotCity().getPopulation() > 1:
			if CyGame().getSorenRandNum(100, 'Zebra9') + 1 <= 25:
				plot.getPlotCity().setPopulation(plot.getPlotCity().getPopulation() - CyGame().getSorenRandNum(int(plot.getPlotCity().getPopulation() / 2), 'Zebra9'))
	unit.setMoves(unit.getMoves() + 60)
	unit.setMadeAttack(True)
		

def shouldRandBombard(unit, action):
	return False
Now if you copy that code over you should be able to use aircraft and seige units to do major damage to cities and units. Now the draw backs are that the AI has no clue about the action and your aircraft can't be intercepted or shot at by sam infantry or aircraft on air patrol.

This would add a no AI action using zActions. Now I am trying to see if I could hyjack an action (say bombard) from the SDK and add my own little event with it. This would allow a person to bombard a city, the city would suffer the usual damage and it would also lose some buildings or what ever. I'm realy hoping to be able to do this.:goodjob:
 
Nice one Zebra. Have you had any luck getting flying help text for your added ActionButtons?
 
Back
Top Bottom