HOW TO: Add Popups

hello kael,

i never have read anything that amusing on civfanatics ever ! That is a really nice reading .. maybe we just share the same humor .. and besides I really loved this pop ups in MTV and .. I remember this thing about Boy George .. seriously .. besides .. nice piece of code, no idea, whether i need it ever, but anyway nice to know .. besides the Hoth-Popup MUST find an EasterEgg Place in FFH if not there already.. i mean .. it is just .. good ..
 
Hopefully I can get an answer pretty quick :)

I'm doing Paradox Games-style events, and instead of having a ton of stuff in CvScreensInterface.py I'd rather have them all in my own events (wwiisfnbevents.py), under def eventlist.
Atm the code goes like this:
wwii events.py:
Code:
	def eventlist(event):
		if event = 'WarUSSRvsFIN': #USSR demands land from Finland, Week 44, 1939
			pPlayer = gc.getPlayer(13)
			if pPlayer.isHuman():
				popupInfo = CyPopupInfo()
				popupInfo.setButtonPopupType(ButtonPopupTypes.BUTTONPOPUP_PYTHON)
				popupInfo.setText(CyTranslator().getText("The Soviet Union is demanding that you give them Viipuri.",()))
				popupInfo.setData1('WarUSSRvsFIN1')
				popupInfo.setData2('WarUSSRvsFIN2')
				popupInfo.setData3('WarUSSRvsFIN3')
				popupInfo.setOnClickedPythonCallback("popupthree")
				popupInfo.addPythonButton(CyTranslator().getText("War is not an option, we must accept. (Viipuri is lost and all units east of it deleted)", ()), "")
				popupInfo.addPythonButton(CyTranslator().getText("Negotiate us to be vassalized. (Become Vassal of USSR, possibility of revolts)", ()), "")
				popupInfo.addPythonButton(CyTranslator().getText("Never! (War with USSR)", ()), "")
				popupInfo.addPopup(pPlayer)

def popupmany:
Code:
def popupmany(argsList):
	iButtonId = argsList[0]
	iData1 = argsList[1]
	iData2 = argsList[2]
	iData3 = argsList[3]
	if iButtonId == 0:
		send to wwii events def eventlist(iData1)
	if iButtonId == 1:
		send to wwii events def eventlist(iData2)
	if iButtonId == 2:
		send to wwii events def eventlist(iData3)
What I'd like def popupmany to do is to send the iData back to the events file, into def eventlist, so that I can see all of my events & their results in the same place.
 
so how would you do something like in the American Revolution scenario, where a popup comes up on a certain turn and says "Reinforcements have arrived for the british!" and a bunch of unit spawn for the brits. Also, can you make one that despawns units?
 
so how would you do something like in the American Revolution scenario, where a popup comes up on a certain turn and says "Reinforcements have arrived for the british!" and a bunch of unit spawn for the brits. Also, can you make one that despawns units?

Well... I'm not sure to understand very well your question (I'm French)...
What I understand is : you want to have an event at the turn "t", with a popup that anounces something.
If I understood :
Have a look to the python scripts in Spain 1936 (link below), you'll find what you need.
PM me for more help...
 
I wanted to make a popup when I build a city or raze a city . The thing is that when I write

if CityBuilt
if pPlayer.isHuman():
.....

nothing happens. and if leave out the second part, the popup appears whenever any AI build a city. I want it to appear only when I build a city.
 
Very nice guide, Kael. Works wonders. :D

I have a question about the effects of clicking on a button: I can't seem to get my results outside of the new function. Your example was pretty much a self-contained operation (all the effects were coded right under the ID check), and I haven't found any others that work outside of the few lines of code after the "if ButtonID = x" statement. Perhaps I've just missed something obvious.

Here's a concrete example of what I'm trying to do: I have written a popup that asks the player if he wants to declare war on another player. There are three options, corresponding to "Yes," "No," and "Ask me again X turns later." I have queued it to trigger on a specific turn using a simple "if iGameTurn == iTurnWar" check. The popup itself comes up just fine on the appropriate turn.

The trouble, however, lies in the effect. For the third button, I want the game to update iTurnWar to reflect the new turn (something like iTurnWar = iTurnWar + 10) so it will display the popup again 10 turns later. The problem is, since the Python routine is in CvScreensInterface, it doesn't seem to pass it back to the main events file where I have my other functions. I tried various solutions, ranging from the ridiculous to the obvious, to no avail.

How exactly do you do this? I figured the answer may involve using something like getData1, but I couldn't get it to work.
 
How exactly do you do this? I figured the answer may involve using something like getData1, but I couldn't get it to work.

One thing that has not been mentioned in this thread so far is that the callback function may be located in another
module other than the CvScreensInterface.py

This means that your code may be located in your own module, for example MyCvScreensInterface.py

Then when you are creating the popup specify which module the callback is located in:

popup.setPythonModule("MyCvScreensInterface")

In your MyCvScreenInterface.py file you could declared a global integer for your iTurnWar that would be incremented inside the callback method.
 
Thanks for the reply. I was afraid this thread had died and nobody would say anything. :)

I'm still a little unclear about what you said; wasn't a big point in Kael's guide that the function must necessarily be in the CvScreensInterface module? Not that I'm upset about it - if I can define my own, all the better!

I had thought about using global variables but didn't want to go that way, if I could avoid it, primarily because I wanted to incorporate the global script dictionary as well. (But since that's already global, I shouldn't have to do anything special with it, correct?) I'll look at this later and see what happens. :)
 
What would be the code to use to generate a popup box to select a unit from a stack, like is done when you want to add a warlord to a unit or to choose what ship to load a unit onto?

For this question and others related to popups, I found a nice python file that comes with Civ4 about examples of radio buttons, listboxes, check boxes, edit fields, etc. etc. There are two functions called InitTestPopup() and initPythonTestPopup() with plenty of examples.
The file is called CvPopupInterface.py and mine was found under the directory C:\games\Civ4\Assets\Python\EntryPoints.
 
Thanks for the reply. I was afraid this thread had died and nobody would say anything. :)

I'm still a little unclear about what you said; wasn't a big point in Kael's guide that the function must necessarily be in the CvScreensInterface module? Not that I'm upset about it - if I can define my own, all the better!

I had thought about using global variables but didn't want to go that way, if I could avoid it, primarily because I wanted to incorporate the global script dictionary as well. (But since that's already global, I shouldn't have to do anything special with it, correct?) I'll look at this later and see what happens. :)

This is how I added a routine to launch a triggered event from the python console to demostrate how you would create a popup and how to handle the selected option.
Of course, during a game this is cheating but how else do you quickly test a piece of code? I put this file under ...\Civ4\Beyond the Sword\Assets\Python\EntryPoints directory.
Then after invoking the python console (shift+~) I import my file MyCvScreensInterface.py and call the selectEventTrigger() method:

Spoiler :

Code:
from CvPythonExtensions import *
import CvUtil

#######################################################################################
## Select my events
#######################################################################################
gc = CyGlobalContext()

def selectEventTrigger():
    """
    Present the user with a list of event triggers and
    launch the selected event
    """
    
    iPlayer = 0
    player = gc.getPlayer(iPlayer)
    
    popupInfo = CyPopupInfo()
    popupInfo.setButtonPopupType(ButtonPopupTypes.BUTTONPOPUP_PYTHON)
    popupInfo.setText(CyTranslator().getText("TXT_KEY_POPUP_SELECT_EVENT",()))
    popupInfo.setData1(iPlayer)
    
    # the following python routine must exist in the CvScreensInterface.py file.
    popupInfo.setOnClickedPythonCallback("selectOneEvent")
    # unless a different module is specified
    popupInfo.setPythonModule("MyCvScreensInterface")
    
    
    # The following keys must be defined in the Text\CIV4GameText_Events_BTS.xml file.
    popupInfo.addPythonButton(CyTranslator().getText("TXT_KEY_POPUP_SELECT_EVENT_HORTICULTURE", ()), "")
    popupInfo.addPythonButton(CyTranslator().getText("TXT_KEY_POPUP_SELECT_EVENT_SPICY", ()), "")
    popupInfo.addPythonButton(CyTranslator().getText("TXT_KEY_POPUP_SELECT_EVENT_BLACK_PEARLS", ()), "")
    popupInfo.addPythonButton(CyTranslator().getText("TXT_KEY_POPUP_SELECT_EVENT_SALTPETER", ()), "")
    popupInfo.addPythonButton(CyTranslator().getText("TXT_KEY_POPUP_SELECT_EVENT_TRUFFLES", ()), "")
    popupInfo.addPythonButton(CyTranslator().getText("TXT_KEY_POPUP_SELECT_EVENT_SEA_TURTLES", ()), "")
    popupInfo.addPythonButton(CyTranslator().getText("TXT_KEY_POPUP_SELECT_EVENT_TIN", ()), "")
    popupInfo.addPythonButton(CyTranslator().getText("TXT_KEY_POPUP_SELECT_EVENT_GOLD_RUSH", ()), "")
    popupInfo.addPythonButton(CyTranslator().getText("TXT_KEY_POPUP_SELECT_SPORTS_LEAGUE", ()), "")
    popupInfo.addPythonButton(CyTranslator().getText("TXT_KEY_POPUP_SELECT_INSPIRED_MISSION", ()), "")
    popupInfo.addPythonButton(CyTranslator().getText("TXT_KEY_POPUP_SELECT_NEVER_MIND", ()), "")
    
    popupInfo.addPopup(iPlayer)    
 
 
# some standard event trigger names as they apperar in the 
# Events\CIV4EventTriggerInfos.xml file.
eventTriggerKey = { 
0 : 'EVENTTRIGGER_HORTICULTURE',
1 : 'EVENTTRIGGER_SPICY',
2 : 'EVENTTRIGGER_BLACK_PEARLS',
3 : 'EVENTTRIGGER_SALTPETER',
4 : 'EVENTTRIGGER_TRUFFLES',
5 : 'EVENTTRIGGER_SEA_TURTLES',
6 : 'EVENTTRIGGER_TIN',
7 : 'EVENTTRIGGER_GOLD_RUSH',
8 : 'EVENTTRIGGER_SPORTS_LEAGUE',
9 : 'EVENTTRIGGER_INSPIRED_MISSION'
}

def selectOneEvent(argsList):
    iButtonId = argsList[0]
    iData1    = argsList[1]
        
    eventTriggerName = None
    eventTriggerNumber = -1
    
    if iButtonId in eventTriggerKey.keys():
        eventTriggerName = eventTriggerKey[iButtonId]

    if eventTriggerName == None:
        return
        
    eventTriggerNumber = CvUtil.findInfoTypeNum(gc.getEventTriggerInfo, gc.getNumEventTriggerInfos(), eventTriggerName) 
    
    if eventTriggerNumber == -1:
        return
    
    message = 'addImmediateMessage: You selected Event: %s[%d]' % (eventTriggerName, eventTriggerNumber)
    CyInterface().addImmediateMessage(message, "")
    message = 'pyPrint: You selected Event: %s[%d]' % (eventTriggerName, eventTriggerNumber)
    CvUtil.pyPrint(message)
    message = 'print: You selected Event: %s[%d]' % (eventTriggerName, eventTriggerNumber)
    print message
        
    pPlayer = gc.getPlayer(iData1)
    pPlayer.trigger(eventTriggerNumber)


 
Here's a related question on popups: I like the "official" events popup screen (with the bullet points and hover-over effect details), but I find the XML event handler too cumbersome to use and I'd like to do it all in Python. I looked for the place where the event screen is defined but couldn't find it.

Where exactly is the code for the event screen itself?
 
In a sense I did, but I used a work-around solution with the multiple choice popups. My original problem with creating pseudo-events was owing to my own clumsiness in Python more than anything else. :rolleyes:

I still would really like to make a popup that looks like the random events one - the popup that has the "hover-over effects" display. I haven't checked out where that's explicitly used (probably in SDK, since I never saw it in any of the Python files) but if I find it I might write up a brief tutorial on how to use it. :)
 
In a sense I did, but I used a work-around solution with the multiple choice popups. My original problem with creating pseudo-events was owing to my own clumsiness in Python more than anything else. :rolleyes:

I still would really like to make a popup that looks like the random events one - the popup that has the "hover-over effects" display. I haven't checked out where that's explicitly used (probably in SDK, since I never saw it in any of the Python files) but if I find it I might write up a brief tutorial on how to use it. :)

Its actually easy to call an event from pyton with the BtS code. I dont write custom popups anymore, I just create and event that will never happen and only trigger it when I want the popup to occur.

For an example of an event thats only called when wanted check out the partisans event in BtS (called from CvEventManager.py).
 
Top Bottom