[Python]How to fire up a popup when clicking a Great People Button in City Screen?

stmartin

aka. poyuzhe
Joined
Aug 4, 2007
Messages
640
Location
Shanghai
The fact 1: when the mouse is moved over a Great People Button in City Screen, the help text for that Great People emerges. So there must be a way to trigger an event, such as a firing up a popupInfo, when the same button is clicked. Edit: Well, I don't trust this assertion anymore, probably I'm wrong.:)

The fact 2: however I just couldn't figure out how to do that...

The question: So if anyone could give me a little tutorial, you are my hero!
 
The popup for that one is handled in the SDK, and adding a click effect by the same means would be quite simple really. But that assumes you are already willing to/comfortable with, edit the SDK files instead of doing just python and XML.

You can follow this guide to set up the DLL, and try to compile an unmodded version of it to verify things work. Then we can discuss how to go about making the changes, if nobody has dropped in and announced a way to do it with Python by then.
 
Many thanks! I have tried compiling and making changes in SDK already so let's begin the tutorial:lol: Really I'm not asking too much tutorial, just let me know which part of which SDK file to take a look at. Of Course more tutorial is always welcomed!
 
Aye, for now I haven't the time to go into too much depth, I just didn't want to check things out and discover that merely being in the SDK was too much :) Personally I think all mods ought to stay in there, just so much more POWER! ;)

The file you are interested in is CvDLLWidgetData.cpp. This is where all WIDGET_* items are defined and given their jobs. In this particular case, you peek at CvMainInterface.py (or just guess) to find that you are interested in modification to WIDGET_HELP_GREAT_PEOPLE.

So, open up your project and CvDLLWidgetData.cpp, then search for "WIDGET_HELP_GREAT_PEOPLE"

First result will be:
Code:
	case WIDGET_HELP_GREAT_PEOPLE:
		parseGreatPeopleHelp(widgetDataStruct, szBuffer);
		break;

This is what will happen when you move the mouse over it. The game is directed to a later function CvDLLWidgetData::parseGreatPeopleHelp

Now, that is the only instance in this file, and is listed under CvDLLWidgetData::parseHelp. This function is called whenever the mouse moves onto an item with a Widget_Type defined. When the mouse CLICKS on an item with a Widget_Type, the function CvDLLWidgetData::executeAction is called. So all that you need to do is add a new case to this section of the code. So head down there and add a command for when someone clicks on "WIDGET_HELP_GREAT_PEOPLE" along the lines of:

Code:
	case WIDGET_HELP_GREAT_PEOPLE:
		doGreatPeople();
		break;


This will cause it to run a function that you will define later in the .cpp (and in the .h file since you are finally creating something new. Unless you want to have it open a window that already exists, in which case you can use the same function call as the other Widget already does).

The function you will define will depend on precisely what you want to happen when you click on the GPP Bar, so I'll leave you to look at all of the other functions called in CvDLLWidgetData::executeAction, almost certainly one of them does much the same as what you want to do, since you can find the buttons for the Advisors to open a new screen, or the buttons for renaming a unit/city for opening a text entry box, and all sorts of other examples. Just think of what already does roughly what you want, look up the Widget_type for that item, and then find it in CvDLLWidgetTypes.cpp.
 
Thanks man, it's AWesome! I've done it!

There's a minor mystery though. I added log message among my newly defined function. Since it's a total success, these new messages should show up in the log. But they don't! EDIT: My bad, they do show up... but anyway, please take a look at the code to see if I can somehow improve it:). Here's the code:
Code:
void CvDLLWidgetData::doAlterSpecialistsGPP(CvWidgetDataStruct &widgetDataStruct)
{
    CvString szLogMsg;
    szLogMsg.Format("doAlterSpecialistsGPP called");
    gDLL->logMsg("sdk.log", szLogMsg);
    CvCity* pCity = gDLL->getInterfaceIFace()->getHeadSelectedCity();
    if (NULL != pCity)
    {
        if(pCity->getNumBuilding((BuildingTypes)GC.getInfoTypeForString("BUILDING_SILK_ROAD")) == 1)
        {
            szLogMsg.Format("Silk Road found in city");
            gDLL->logMsg("sdk.log", szLogMsg);
            CvPopupInfo* pInfo = new CvPopupInfo(BUTTONPOPUP_PYTHON);
		if (NULL != pInfo)
		{
		    pInfo->setText(gDLL->getText("TXT_KEY_POPUP_ALTER_SPECIALISTS_GPP"));
                    pInfo->setData1(pCity->getID());
                    pInfo->setOnClickedPythonCallback("triggerAlterSpecialistsGPP");
                    pInfo->addPythonButton(gDLL->getText("TXT_KEY_UNIT_GREAT_PROPHET"), "");
                    pInfo->addPythonButton(gDLL->getText("TXT_KEY_UNIT_GREAT_ARTIST"), "");
                    pInfo->addPythonButton(gDLL->getText("TXT_KEY_UNIT_GREAT_SCIENTIST"), "");
                    pInfo->addPythonButton(gDLL->getText("TXT_KEY_UNIT_GREAT_MERCHANT"), "");
                    pInfo->addPythonButton(gDLL->getText("TXT_KEY_UNIT_GREAT_ENGINEER"), "");
                    pInfo->addPythonButton(gDLL->getText("TXT_KEY_SPECIALIST_GREAT_SPY"), "");
                    szLogMsg.Format("Buttons added");
                    gDLL->logMsg("sdk.log", szLogMsg);
		    gDLL->getInterfaceIFace()->addPopup(pInfo, GC.getGameINLINE().getActivePlayer(), true);
		    szLogMsg.Format("Popup fired up");
                    gDLL->logMsg("sdk.log", szLogMsg);
		    }
            }
    }
}

Yes, this code looks bad.:lol:
 
Top Bottom