View Full Version : Python code to delete cities/units or convert to another civ when a unit is killed


DireAussie
Nov 29, 2005, 02:40 AM
I wrote this code for someone else's mod

If you wanted to implement a leader unit and have all of the civ killed off when that leader is killed then this is the code for you :)

Put this in your CvEventManager class. Be sure to put in a "self.ignoreKill = false" entry in the init function of your CvEventManager class.

In the below code, units and cities are converted to barbarian when a maceman is killed. Currently no experience or promotions are carried over during unit conversion, but this could be added in.

def onUnitKilled(self, argsList):

#when inside the loop, calling loopUnit.kill(true, player.getID()) will then call this onUnitKilled method, then we get infinite loop. So avoid this by not calling the function when killing units inside the loop
if (self.ignoreKill == false):

self.parent.onUnitKilled(self, argsList)

unitInfo = []

#get info from args given to us
unit, iAttacker = argsList

#get player from unit
player = gc.getPlayer(unit.getOwner())

#get the attacking player (dont really need it for this)
attacker = gc.getPlayer(iAttacker)

if (unit.getUnitType() == gc.getInfoTypeForString("UNIT_MACEMAN") and player.getID() != gc.getBARBARIAN_PLAYER()):
#loop through and store all info about the player's units
(loopUnit, iter) = player.firstUnit(false)


self.ignoreKill = true #ignore onUnitKilled event while in loop
while (loopUnit):

if ( not loopUnit.isNone()):
#store unit info
unitInfo.append((loopUnit.getUnitType(),loopUnit.g etX(), loopUnit.getY()) )

#kill unit
loopUnit.kill(true, player.getID())

(loopUnit, iter) = player.nextUnit(iter, false)
CvUtil.pyPrint("did unitloop")

self.ignoreKill = false

#player.killUnits() #this seems to crash the game

#now loop through all cities and convert to barbarian
(loopCity, iter) = player.firstCity(false)

while(loopCity):
if ( not loopCity.isNone()):
#do conversion
gc.getPlayer(gc.getBARBARIAN_PLAYER()).acquireCity (loopCity, false, false)

(loopCity, iter) = player.nextCity(iter, false)
CvUtil.pyPrint("did cityloop")

#now create new units for barbarian

self.ignoreKill = true #not tested but creating a unit on the same square as an enemy unit might kill the other unit

for id, xpos, ypos in unitInfo:
#NOTE- not fully tested - what if player is allied with someone and unit in an ally's city and then a barbarian unit is created?

#CvUtil.pyPrint("creating unit as follows: id %d, xpos %d, ypos %d" % (id, xpos, ypos))
#unitTypeNum = CvUtil.findInfoTypeNum(gc.getUnitInfo, gc.getNumUnitInfos(), "UNIT_MACEMAN")

gc.getPlayer(gc.getBARBARIAN_PLAYER()).initUnit(id , xpos, ypos, UnitAITypes.NO_UNITAI)
CvUtil.pyPrint("did barbunitloop")

self.ignoreKill = false

Shqype
Nov 29, 2005, 07:50 AM
Very useful! Good work.

Weasel Op
Nov 29, 2005, 10:55 AM
So this is a regicide mod?

The Great Apple
Nov 29, 2005, 01:41 PM
So this is a regicide mod?
Looks like it - when the king (or the maceman) dies, all your cities turn to barbarian cities - sounds cool to me!

Except the AI probably wouldn't protect his king so well...


EDIT: Just out of interest, how important is the API for coding in python - am I right in thinking that it is absolutely vital? I've just started playing with it, and I've constantly got the API open!

EDIT 2: And how would you go about carrying over promotions. I think I can work out experience, but I can't see any way of storing the promotion data before killing the unit.

EDIT 3: Oh, and the Rebellion mod by Trip (http://forums.civfanatics.com/showthread.php?t=137898), has some code to avoid unit clashes on foreign cities/units - you may want to check it out.

DireAussie
Nov 29, 2005, 03:49 PM
EDIT: Just out of interest, how important is the API for coding in python - am I right in thinking that it is absolutely vital? I've just started playing with it, and I've constantly got the API open!


For sure! The PyHelpers file is pretty much useless, but its good for learning how to do certain things. I always access the functions provided through CvPythonExtensions. I used pydocs (thanks to the civ4wiki for instructions) to make a web page out of it:

http://www.users.on.net/~dfidge/CvPythonExtensions.zip

EDIT 2: And how would you go about carrying over promotions. I think I can work out experience, but I can't see any way of storing the promotion data before killing the unit.

have a look at the file: civ4\assets\python\pyWB\CvWBDesc.py and search for "promotion".

regicide

I'm not familiar with that term - was this the name of a mod in civ 3 or something?

Weasel Op
Nov 29, 2005, 03:50 PM
I'm not familiar with that term - was this the name of a mod in civ 3 or something?
It's a game option in C3C. It literally means "ruler-killing."

Weasel Op
Nov 29, 2005, 10:09 PM
btw if you put this in a py file and attach it, this could go in completed mods.

LittleRedPoint
Dec 17, 2005, 05:07 AM
This post is not important. I could not delete this.

LittleRedPoint
Dec 17, 2005, 08:20 AM
:D I already found answer to my quetion. To get sertain units like great general as a combat result you just have to mod Snaitf's "Unit Allegence mode" code.

Other stuff are only conditions - so now it is possible to make event to combat that you have chance to get some units what you like

Snaitf is genius!!! :D He made good option!

zulu9812
Jun 18, 2006, 12:37 PM
How could the code in the opening post be modified so that the remaining cities are split 50/50 between going barbarian and joing the regiciding civ?

Primax
Aug 01, 2006, 08:45 PM
If you want it more like regicide in civ3 you could use the following:


def onUnitKilled(self, argsList):
'Unit Killed'
unit, iAttacker = argsList
'determine owner of lost unit'
player = PyPlayer(unit.getOwner())
attacker = PyPlayer(iAttacker)
'check if unit killed was a king'
if unit.getUnitType() == gc.getInfoTypeForString("UNIT_KING"):
'loop through cities and destroy each one'
CityList = player.getCityList()
for City in CityList:
City.GetCy().kill()
if (not self.__LOG_UNITKILLED):
return

CvUtil.pyPrint('Player %d Civilization %s Unit %s was killed by Player %d'
%(player.getID(), player.getCivilizationName(), PyInfo.UnitInfo(unit.getUnitType()).getDescription (), attacker.getID()))

This assumes you have created a unit called King, you could change this to gc.getInfoTypeForString("UNIT_SCOUT") for example.