What's the code difference between normal and auto razing? And when onCityLost?

The_J

Say No 2 Net Validations
Administrator
Supporter
Joined
Oct 22, 2008
Messages
42,125
Location
DE/NL/FR
So, I have a small problem, and no real clue where I should look at, so I hope that somebody has maybe an idea or a small hint.

I've been working on a small mod component.
As a part, it includes a victory, for which you have to destroy a civ.
The function to trigger the victory is run after a city has been captured, and looks if the desired civilization is dead or not. In case it's dead, the victory is triggered.
At first, I put the code in Python after onCityAcquired. The result: Interface locks up, and the game partially freezes. The victory is triggered, but I don't get the popup which tells me my victory. Neither I get the regular popup, which asks me if I want to keep or raze the city. My suspicion: The popups (or the lacking answer to one of them or both) somehow interfere with each other, and neither works.
-> I moved the code after onCityAcquiredAndKept and onCityRazed. That works. Besides for auto razing. In that case I get the same behaviour like before, the interface locks up.
Now my suspicion is again, that due to some hack there should be somehow also a popup, but the Firaxians supressed it, and this causes now somehow problems.
It would be good to know if someone could give me an insight into that, or at least an idea where else I could look in the files to see anything regarding that.

And in case this doesn't work: Does anyone know under which circumstances onCityLost is triggered? Because I guess I could move the code else to this part.
 
Since I not the type who bothered to dig into the dll to read when the codes are activated.
Here are the results based on my past trials and errors:

CityRazed:
Activated when city razed manually as well as automatically (1 Population City)
The Downside:
No way to get previous owner, only current owner which is basically the razer, or the player with highest culture in the city.

CityAcquired:
Activated both during conquest as well as during trade (liberation of cities as well as colonies)

CityAcquiredAndKept:
Activated only during conquest. Not activated for Trade.
And somehow iOwner always refer to active player during my trials.

CityLost:
Activated so long as you lost the city due to 1) Conquest 2) Liberation 3) Razing
For 1) Conquest, codes activated for previous owner
2) Liberation, codes activated for liberator
3) Razing, basically the razer since you are the owner.
Thus, for auto razing, actually codes are activated for both the razer and the previous owner, since the previous owner lost the city due to conquest, and the razer lost the city due to razing.

I only bothered to test for 3 methods where a city changes hands normally
1) Conquest
2) Razing
3) Liberation aka Trade

Never bother to test for other methods such as due to python codes or Apolistic Palace
 
Thanks :hatsoff:.
Your observation for the previous owner in the razing function must somehow be wrong, because I use him to check if the conquered civ is dead, and the code works. Or maybe it's a strange occurence, don't know :dunno:.

Guess I could try then after onCityLost. That the code is activated twice shouldn't be a problem, because I have some more checks in place, which should ensure that it's only triggered under the right circumstances.
 
onCityRazed has 3 things to play with.
city => refers to the city obviously
iPlayer => Razer aka city.getOwner()
iOwner => city.findHighestCulture()

Under usual conditions, iOwner will usually be the previous owner as well.
However, let's say Japan built a city.
Now Mongolia takes over it.
Now China declare war on Mongolia and raze the city.
iOwner will refer to Japan rather than Mongolia if Japan's culture is still the highest.
iPlayer will refer to China.
So how do you check if Mongolia is dead?

Actually I did something to check if a player is dead before for my old Aggressive Trait.
What I did was underCityAcquired:
If Complete Kills is on, check if the loser has no city and unit.
Else, Just check if the loser has no city.
Under onUnitKilled:
If Complete Kills is on, check if unit owner has no city and unit.
 
Hmm you are right, forgot about that function.
Since I usually do my codes onCityAcquired, I can usually get Previous Owner without using that function :D

Personally I never use that option either, but no idea whether anyone actually uses that, so just include it for sake of completeness
 
I also could not guess it, but well...better there's more available than less.

So, tested it, the same problem appears when I attach the code to onCityLost.
I'm not sure what to do now.
I could maybe prevent the automatic city razing with attach a code to onCityAcquired, which adds some more population to the city (just for the case this is the last city). I already tried that, but with the whole code attached to onCityAcquired, but like pointed out that doesn't work due to my guessed popup interference. But I guess this will also not work.

Else...check the case that the last city is auto razed, and don't declare anyone the winner, but story that stuff in a global variable and trigger it at the end of the turn. That's a bit messy, don't really like it.
Any better suggestions?
 
Hmm since I never done popups before, no real idea what is messing up.
I will suggest get rid of the popups first, and just display a message "XXX has won" without a pop up window.
Then see if the victory conditions actually triggered correctly in the right situations like auto-razing of last city etc.
If everything works correctly, then lets play around with the popup.

Else maybe you can attach what you have and let me have fun trial and error :D
 
The popup is automatically triggered when you use CyGame().setWinner, so there's no way around that.

And the victory is correctly triggered. When I capture the city, I can see "XY has won a roman conquerers victory" on the screen, but the whole thing doesn't move any further. I don't get a popup, I can't finish the round, I can't move any units, etc.
 
I did a simple test:
Code:
	def onCityAcquired(self, argsList):
		'City Acquired'
		iPreviousOwner,iNewOwner,pCity,bConquest,bTrade = argsList

## Test ##
		pPlayer = gc.getPlayer(iPreviousOwner)
		if pPlayer.getCivilizationType() == gc.getInfoTypeForString("CIVILIZATION_AMERICA"):
			if pPlayer.getNumCities() == 0:
				pPlayer2 = gc.getPlayer(iNewOwner)
				CyGame().setWinner(pPlayer2.getTeam(), gc.getInfoTypeForString("VICTORY_CULTURAL"))
## Test ##

Everything works correctly when America is destroyed :D, so there is no need to try onCityRazed or onCityLost.
If you care about Complete Kills, then additional codes like I mentioned, else this is enough I believe.
However, if this is done before 10th turn, I will get the same situation as you, victory message but no movie etc.
But if this is done after 10th turn, I get the popup message, followed by victory movie etc.

This is due to
Code:
def isVictoryTest(self):
		if ( gc.getGame().getElapsedGameTurns() > 10 ):
			return True
		else:
			return False
in CvGameUtils

This may be your answer.
 
:crazyeye: I must have screwed something.
Did what you said, waited til turn 11, tested it again. No dice, same problem.
Moved the code around, and...nothing. Nothing happens anymore. Moved the code back, and still no effect. Basically nothing custom in the CvEventManager works anymore. Put a print function at various points, nothing.
But the custom victory screen works. The custom utopia project is still there. I can also build it. But it doesn't have an effect anymore.
WTH has happened :crazyeye:?

Could someone please take a look at it (attached)?
Just put the Romans, the Celts and Carthage in the game, and destroy the two latter, then it should trigger a victory for the romans.
Code itself is labeled with "victoriesPlus".
The logic for the additional entries in the victory screen is not final (just saying, in case somebody wants to point that out).
 

Attachments

Hohoho, you did not enable python exceptions :D

The most obvious error is you did not comment away the line "VictoriesPlus start - Utopia", which is why everything else below it won't work.

Shift the codes back to onCityAcquired as I am more familiar with that and did some modifications if you don't mind
 
Oh yeah, since you are using my Internet style of AI projects, I guess you should know about this.
As the system is basically tricking the AI into believing that project is an Internet so AI will build it willingly, the system will not work if AI has not met anyone.
In other words, for maps with many continents and islands, since AI has not met anyone, they will not gain any benefits from Internet, they will not build it.
Since yours is a victory project, I guess this is irrelevant, but for early game projects, this may be an issue.

As for the project help tag, it was first started by Jamie, I just modified it :D
 
Ah, thanks, good to know :hatsoff:. And I'll credit him :yup:.

So, Python exceptions were indeed turned off :crazyeye:! Turned them on, started civ, and they were turned off again :crazyeye:. Removed the writing permissions from the .ini file, now the exceptions work again.

For the code: :dunno: but after onCityAcquired doesn't work, still the same effect. Put the code again after onCityLost, which doesn't cause any problems.
I also tried my work around, adding +1 pop to last city in the onCityAcquired function in case it would get auto razed, and that indeed works :D. Since somebody will win at that point, it doesn't really matter if a size 1 city gets or gets not razed.
Made also some other adjustments, e.g. Rome must be present and alive (yeah, sounds obvious, but was not included).
Guess I can release that tomorrow :).
 
Not sure why onCityAcquired doesn't work for you, since the file I uploaded work for me as intended. Tested in game as well, triggered rome victory message, pop up, no movie :D, then all the graphs, highscore etc
Didn't bother to make those Rome present adjustments, since I assume this should be for scenario, else it will be weird if the 2 targeted civs aren't in the game in the first place too.
It also looks weird if a 3rd party finished off the 2 civs, and Rome wins as a result.
 
Not sure why onCityAcquired doesn't work for you, since the file I uploaded work for me as intended. Tested in game as well, triggered rome victory message, pop up, no movie :D, then all the graphs, highscore etc

:hmm: totally don't understand that.
I hope I didn't mess up anything in my Civ installation...don't think so, because it would have to be the dll, but what else...:hmm:?

Didn't bother to make those Rome present adjustments, since I assume this should be for scenario, else it will be weird if the 2 targeted civs aren't in the game in the first place too.
It also looks weird if a 3rd party finished off the 2 civs, and Rome wins as a result.

Yeah, the victory is more meant for scenarios, but want to make it work with the normal game too, just in case.
 
No idea also then, can provide a save game if you need.
All I changed was the EventManager so I didnt upload the whole mod folder.
But it works perfectly for me so :dunno: why it does not work on your com.

But if you are making it work for normal game, then you probably have to add a check for the 2 civs also, else Rome will win instantly any city is acquired.
 
Back
Top Bottom