How do I write an event for a war to be declared later.

nokmirt

Emperor
Joined
Feb 14, 2009
Messages
5,088
Location
Iowa USA
I am working on a mod called 1861 AD. The scenario begins in April 1861, at the beginning of the American Civil War. I want to write events for later declarations of war between civs, but I am not sure how to write the Python event code.

What is the basic code to make one civ declare war on another, and to have the war last up to a certain point?

I am reverting my game turns back to weeks, instead of two turns a month.

The wars I want to have occur at the proper time are as follows.

-The American Civil War from April 12, 1861 – April 9, 1865, I have this war in progress at the outset. I gave each side a attitude modifier of -75 towards the other, that should keep them fighting for more than 6 months I hope.

- The French-Mexican War from 8 December 1861 - 21 June 1867 The belligerents in clude Spain, and England, but being as they played a small role in any fighting, France will be the main participant. So week 2, December 1862- Week 3, 1867.

-The Austro-Prussian War, or the Seven Weeks War should occur between 14 June – 23 August 1866. So we'll say Week 2 June, 1866 and week 4 August, 1866

There are others such as the Taiping Rebellion, Franco-Prussian War, Zulu Wars, and the 1st Boer War, just for starters.

Thanks for any help with Python. I want to learn, but code for BTS 3.19 is more advanced, than it was for vanilla, and I do not know any of it.
 
What I would like is an example of the code, or if it can be done with xml, a brief explanation on event times. The tutorials are quite vague. Thanks
 
Can't be done only via XML.

One question:
Do you really need an event (i mean with the popup and the possibility to choose an option), or will "just" an automatic war declaration with a popup with only text also do the job?

I suppose a popup saying. France has declared war on Mexico. And Yes, an automatic war declaration with a popup with only text. As long as it occurs at a certain time. I believe in Vanilla, Python used a turn counter, and a trigger. If the trigger, basically stated, civ 1 is going to declare war on civ 2 on turn 15. Thats when it occurred, or was turned on. The code is different, from what I understand for BTS 3.19. So I am not sure exactly how to make this happen, if there is an easier way, I am all ears. I hope they remedy this in Civ 5, and make event modding easier, with more obvious options available, like the basic principle of declaring war. Thanks The_J
 
Okay, here a short example, goes into the CvEventManager, after, like you can see, onBeginGameTurn:

PHP:
    def onBeginGameTurn(self, argsList):
		'Called at the beginning of the end of each turn'
        iGameTurn = argsList[0]
        CvTopCivs.CvTopCivs().turnChecker(iGameTurn)
###new code
        if iGameTurn == 10:
            ###declare war begin###
            iTypeDeclaringCiv == gc.getInfoTypeForString("CIVILIZATION_GERMANY")
            iTypeVictim == gc.getInfoTypeForString("CIVILIZATION_ENGLAND")
            iDeclaringPlayer = -1
            iVictimPlayer = -1
            iMaxCiv = gc.getMAX_PLAYERS()
            for iCivs in range(iMaxCiv):
                pPlayer = gc.getPlayer(iCivs)
                if pPlayer.getCivilizationType ()==iTypeDeclaringCiv:
                    iDeclaringPlayer == iCivs
                elif pPlayer.getCivilizationType ()==iTypeVictim:
                    iVictimPlayer == iCivs
            if iDeclaringPlayer ==-1 or iVictimPlayer ==-1:
                return
            gc.getTeam(gc.getPlayer(iDeclaringPlayer).getTeam()).declareWar(iVictimPlayer, false, WarPlanTypes.WARPLAN_TOTAL)
            ###declare war end
            ###popup begin
            popup = PyPopup.PyPopup(-1)
            popup.setHeaderString(CyTranslator().getText("TXT_KEY_HEADER_TEXT_SOMETHING_BLABLAB",(gc.getPlayer(iDeclaringPlayer).getCivilizationDescription () ,gc.getPlayer(iVictimPlayer).getCivilizationDescription () )))
            popup.setBodyString(CyTranslator().getText("TXT_KEY_THE_BODY_TEXT_SOMETHING_BLABLA",(gc.getPlayer(iDeclaringPlayer).getCivilizationDescription () ,gc.getPlayer(iVictimPlayer).getCivilizationDescription () )))
            popup.launch(True, PopupStates.POPUPSTATE_IMMEDIATE)
            ###popup end
###new code end

In this case, in round 10 of the game, Germany will declare war on England.
Just exchange the round number, the 2 civilizations and define the text for it.
In the text, you can reference with %s1 and %s2 the declaring player and the player on which war is declared, you that you can also use a generic text, if you wish.
 
Thank you and I am indebted to you The_J. I will mess around with it in, and see how it works. I just have so many wars in this time period, and I want to at least make sure some of the major ones occur.

One question on the Python, what determines how long the war lasts? I see the Python starts the war, but does the war between the two countries just randomly take it's course? If that is the case that is fine. I am trying not to get confused here, I just want to understand how it works.

I have one more question: Has the Python became more user friendly since vanilla or more complicated? Truly though, thanks for the help.
 
The one problem with using the BeginGameTurn event is player ordering. If the player for Mexico comes before the player for France, France will declare war, Mexico will respond, and then France will actually get to attack Mexico. In effect France is saying, "I'm going to attack you on my next turn, but I shall let you respond first." Similarly, any players between them in ID order that Mexico can get bribe into the war will get to take a swing at France, too.

There is a half-solution. If France is an AI you can use BeginPlayerTurn. I believe this event is fired before the AI moves its units. If France is played by a human, you cannot use this event as it's fired after they hit the End Turn button.

I see two solutions for this latter issue. If you're using BUG you can add a duplicate check in BeginActivePlayerTurn. This new event is fired just as the player can begin moving units. If not, you could put the check in onEndPlayerTurn for the next player. For example, if France is player 4 and England is player 3, France would DoW on Mexico at the end of England's turn.

Either way, it's slightly more complicated but I think worth it. If you go this route, definitely have two checks: one for AIs and another for humans. It's best if the player declares during their turn I think as it minimizes the chances of unforeseen consequences. ;)
 
The one problem with using the BeginGameTurn event is player ordering. If the player for Mexico comes before the player for France, France will declare war, Mexico will respond, and then France will actually get to attack Mexico. In effect France is saying, "I'm going to attack you on my next turn, but I shall let you respond first." Similarly, any players between them in ID order that Mexico can get bribe into the war will get to take a swing at France, too.

There is a half-solution. If France is an AI you can use BeginPlayerTurn. I believe this event is fired before the AI moves its units. If France is played by a human, you cannot use this event as it's fired after they hit the End Turn button.

I see two solutions for this latter issue. If you're using BUG you can add a duplicate check in BeginActivePlayerTurn. This new event is fired just as the player can begin moving units. If not, you could put the check in onEndPlayerTurn for the next player. For example, if France is player 4 and England is player 3, France would DoW on Mexico at the end of England's turn.

Either way, it's slightly more complicated but I think worth it. If you go this route, definitely have two checks: one for AIs and another for humans. It's best if the player declares during their turn I think as it minimizes the chances of unforeseen consequences. ;)

Interesting, I will keep this in mind. Thank you for pointing that out.
 
One question on the Python, what determines how long the war lasts? I see the Python starts the war, but does the war between the two countries just randomly take it's course? If that is the case that is fine. I am trying not to get confused here, I just want to understand how it works.

You're right, there's no determined end, that just goes randomly on.

You could force peace via python, if you want to.

I have one more question: Has the Python became more user friendly since vanilla or more complicated?

Neither, nor imho. Just more options.

The one problem with using the BeginGameTurn event is player ordering. If the player for Mexico comes before the player for France, France will declare war, Mexico will respond, and then France will actually get to attack Mexico. In effect France is saying, "I'm going to attack you on my next turn, but I shall let you respond first." Similarly, any players between them in ID order that Mexico can get bribe into the war will get to take a swing at France, too.

:crazyeye:, sure, that you are not confusing onBeginGameTurn and onBeginPlayerTurn?
If not, then i don't really understand what you're saying :dunno:.
 
:crazyeye:, sure, that you are not confusing onBeginGameTurn and onBeginPlayerTurn?

Yes, I'm sure. There is one begin/end game turn pair per game turn as you'd expect. In between them are begin/end player turn pairs--one per player. For example, a four player game could look like this:

  • Begin Game Turn [France DoW Mexico but cannot attack yet]
    • Begin Player 0 Turn
    • End Player 0 Turn
    • Begin Player 1 Turn [Mexico retaliates, bribes England into war]
    • End Player 1 Turn
    • Begin Player 2 Turn [England invades France]
    • End Player 2 Turn
    • Begin Player 3 Turn [France's first chance to attack]
    • End Player 3 Turn
  • End Game Turn
 
Ah, okay....well...negligible imho.

Quite likely, but I figure it's better to point out a potential problem than not say anything. ;)

The function could be moved to onBeginPlayerTurn, but i would say 17 more checks per round is not really necessary for this small design weakness.

As I stated above, this alone causes problems for human players who would end up DoWing immediately after hitting the End Turn button. All other players would get to go before the human could move any units on the offensive.
 
I usually do something like:

Code:
          if (gc.getPlayer(self.iCisalpinaGaulID).isAlive()):
	          pPlayer = gc.getPlayer(self.iCisalpinaGaulID)
	          pCGTeam = gc.getTeam(pPlayer.getTeam())
	
	          if (not pCGTeam.isAtWar(self.iRomanID)):
	               pCGTeam.declareWar(self.iRomanID, false)

I don't know if declaring war while already at war has any issues (like war weariness gets reset?). I do know that a CTD will be generated if one of the civs is not alive, but I'd guess that the loop through all the possible civIDs is the same as just checking isAlive.

And if you find some need to influence how long the war goes on, or set some history/initial conditions, changeWarWeariness and AI_changeAttitudeExtra are available.

eg)
pPlayer.AI_changeAttitudeExtra(self.iRomanID,-10)
pPlayer.AI_changeAttitudeExtra(self.iGermaniaID,70)
eTeam.changeWarWeariness(self.iEpirotesID, 100)

100 WW will have angry citizens right away. + attitude improves relations. Attitude can be set in the WBS file too.
 
Back
Top Bottom