Need Help With a Bit of Tricky Python

MaxAstro

Spiral Knight
Joined
Dec 18, 2007
Messages
645
I am trying to implement the Necrototem as an actual, randomly generated wilderness feature. However, the Necrototem code currently has a bit of a glitch in it: The fear code will occasionally send the frightened unit to another tile adjacent to the totem, defeating the point of that bit of code.

Can anyone take a look at this code and tell me how to make pPlot2 always be a clear plot that is not adjacent to any IMPROVEMENT_NECROTOTEM? I can do a bit of python, but this one has me stumped...

Code:
def atRangeNecrototem(pCaster, pPlot):
    if pCaster.isImmuneToFear() == False:
        pPlot2 = findClearPlot(-1, pCaster.plot())
        if pPlot2 != -1:
            pCaster.setXY(pPlot2.getX(), pPlot2.getY(), false, true, true)
            CyInterface().addMessage(pCaster.getOwner(),True,25,CyTranslator().getText("TXT_KEY_MESSAGE_NECROTOTEM", ()),'',1,'Art/Interface/Buttons/Improvements/Necrototem.dds',ColorTypes(8),pPlot2.getX(),pPlot2.getY(),True,True)
 
You could try an assert that the difference between the X-Coordinate of the new plot and of the Totem, plus the difference of the Y-Coordinates add up to at least 2, but without being 1 each. Slightly convoluted for handling the corner piece, but it'd do it. Doesn't seem that getDistance is exposed to Python or I'd say just use that and insist on a value of at least 2.
 
You could try an assert that the difference between the X-Coordinate of the new plot and of the Totem, plus the difference of the Y-Coordinates add up to at least 2, but without being 1 each. Slightly convoluted for handling the corner piece, but it'd do it. Doesn't seem that getDistance is exposed to Python or I'd say just use that and insist on a value of at least 2.

One thing to be careful of - should the unit cross over water? It may happen if the totem is on a coast and a unit lands....
 
So I can tell from the replies that the problem is more complicated than I thought it to be, and also that I don't know as much about python as I thought (impressive, considering I didn't think I knew very much). XD

I had to look up how assert statements work (shows you how much I know), and I'm afraid I still can't quite wrap my head around how to do it. So I might just have to mark the problem down as out of my league for now...

I had an idea for an alternate way to achieve the effect (having any unit guarding a Necrototem temporarily gain the Fear promotion, and have it start the game with a unit on top of it), but to do that I need to figure out what causes barbarians to guard certain features and not others. I noticed when I changed the Letum Frigus into a unit spawner that barbs wouldn't guard it like they do ruins, dens, and barrows; can anyone point me to why?
 
Code:
def atRangeNecrototem(pCaster, pPlot):
	if pCaster.isImmuneToFear() == False:
		iX = pCaster.getX()
		iY = pCaster.getY()
		pBestPlot = -1
		iBestPlot = 0
		for iiX in range(iX-1, iX+2, 1):
			for iiY in range(iY-1, iY+2, 1):
				pLoopPlot = CyMap().plot(iiX,iiY)
				if pLoopPlot.isNone() == False:
					if pCaster.canMoveOrAttackInto(pLoopPlot, False):
						if abs(pLoopPlot.getX() - pPlot.getX() > 1) or abs(pLoopPlot.getY() - pPlot.getY() > 1):
							iRnd = CyGame().getSorenRandNum(500, "Necrototem")
							if iRnd > iBestPlot:
								iBestPlot = iRnd
								pBestPlot = pLoopPlot
		if pBestPlot != -1:
			pCaster.setXY(pBestPlot.getX(), pBestPlot.getY(), false, true, true)
			CyInterface().addMessage(pCaster.getOwner(),True,25,CyTranslator().getText("TXT_KEY_MESSAGE_NECROTOTEM", ()),'',1,'Art/Interface/Buttons/Improvements/Necrototem.dds',ColorTypes(7),pBestPlot.getX(),pBestPlot.getY(),True,True)
 
edit: arg! Kael beat me to it! I was going to suggest that you use a version of the "getBestPlot" functions that already exist in many mods. I use them a lot!
 
Awesome! Thanks for the help, Kael, really glad I don't have to change the mechanic as I am a fan of it. :)
 
Bump with a new question, so I don't have to start a thread (I assume this is a python question, as I can't find it anywhere in the XML). What determines which improvements the barbarians will guard? I originally assumed it was any improvement that spawns units, but it obviously isn't. Can anyone tell me how to change this settings or make the barbs guard a specific improvement? EDIT: Also, the updated necrototem code provided by Kael seems to have an odd glitch. Suppose the picture below is the area around the Necrototem, with the totem being N. XXX ONX OOX If you step on any of the plots labeled X, the effect works fine. However, if you step on a plot labeled O, the effect does not trigger at all (no message, unit is not bumped). EDIT2: And now for some reason I can't put multiple lines in this post? *sigh* Today is not my day.
 
There is some SDK code that controls barbs stopping on goodie huts. The is some python code in gameunit.py (i think, i dont have the code handy) that stops barb units on barrows and such.
 
Bump with a new question, so I don't have to start a thread (I assume this is a python question, as I can't find it anywhere in the XML). What determines which improvements the barbarians will guard? I originally assumed it was any improvement that spawns units, but it obviously isn't. Can anyone tell me how to change this settings or make the barbs guard a specific improvement?
Code:
def AI_unitUpdate(self,argsList):

		if pUnit.getOwner() == gc.getBARBARIAN_PLAYER():
			pPlot = pUnit.plot()
			if pPlot.getImprovementType() == gc.getInfoTypeForString('IMPROVEMENT_BARROW') or pPlot.getImprovementType() == gc.getInfoTypeForString('IMPROVEMENT_RUINS') or pPlot.getImprovementType() == gc.getInfoTypeForString('IMPROVEMENT_HELLFIRE') or pPlot.getImprovementType() == gc.getInfoTypeForString('IMPROVEMENT_BEAR_DEN') or pPlot.getImprovementType() == gc.getInfoTypeForString('IMPROVEMENT_LION_DEN'):
				if pPlot.getNumUnits() == 1:
					return 1

Just add a clause to the above if statement. Note that this only makes the last barbarian unit not leave the plot.
 
Also, the updated necrototem code provided by Kael seems to have an odd glitch. Suppose the picture below is the area around the Necrototem, with the totem being N.
Code:
XXX   
ONX   
OOX
If you step on any of the plots labeled X, the effect works fine. However, if you step on a plot labeled O, the effect does not trigger at all (no message, unit is not bumped).

I'd use cyPlotDistance instead; it should work at the wrap-around points (if any), and it's easier not to mess up the parens issue that Kael did in his sample code above.

Code:
def atRangeNecrototem(pCaster, pPlot):
	if pCaster.isImmuneToFear() == False:
		iX = pCaster.getX()
		iY = pCaster.getY()
		pBestPlot = -1
		iBestPlot = 0
		for iiX in range(iX-1, iX+2, 1):
			for iiY in range(iY-1, iY+2, 1):
				pLoopPlot = CyMap().plot(iiX,iiY)
				if pLoopPlot.isNone() == False:
					if pCaster.canMoveOrAttackInto(pLoopPlot, False):
[B]						if (cyPlotDistance(pLoopPlot.getX(), pLoopPlot.getY(), pPlot.getX(), pPlot.getY()) >1):[/B]
							iRnd = CyGame().getSorenRandNum(500, "Necrototem")
							if iRnd > iBestPlot:
								iBestPlot = iRnd
								pBestPlot = pLoopPlot
		if pBestPlot != -1:
			pCaster.setXY(pBestPlot.getX(), pBestPlot.getY(), false, true, true)
			CyInterface().addMessage(pCaster.getOwner(),True,25,CyTranslator().getText("TXT_KEY_MESSAGE_NECROTOTEM", ()),'',1,'Art/Interface/Buttons/Improvements/Necrototem.dds',ColorTypes(7),pBestPlot.getX(),pBestPlot.getY(),True,True)
 
Thanks a million, xanaqui! That is exactly what I was looking for in both cases, you are a life saver. ^_^
 
Back
Top Bottom