Adding extra information to plots while in WB

LoneTraveller

Warlord
Joined
Apr 30, 2008
Messages
283
Location
Montreal, Quebec
hi, it's been a while since I have modded Civ4 so I might of forgotten some things over time.

I've been playing Civ5 for a month and I want to reproduce it's Strategic Resources (SR) 'management' but in Civ4.

Now so far, I have edited the CvPlot and CyPlot classes for accessors, modifiers and variables for the amount of SRs on a plot object.

The problem is setting the amount of SRs in a simple to use way. I was thinking of using WorldBuilder to set that amount at the same time that a player would place a resource on a selected tile. I have found a function called ''CvPlot::setBonusType(BonusTypes eNewValue)'' and I wonder how to add code that would 'launch' a prompt in WB asking for an integer and using that number for the number of SRs on that tile.

I have very very little experience with Python so I'm not sure if what I want to do is feasible.

Any constructive input is welcome :)

Thank you
 
What you wanna do is attach a string value (ScriptData) to each plot with a resource on it. It could be a numerical character, like "7". But I don't believe you can do this with the World Builder, so you need to map each plot and add a value to it by script.

You can modify the value with CyPlot.setScriptData() and you can access this string with the CyPlot.getScriptData() method. The conversion to and from string/integer is done with the str() and int() built-in Python functions.

My best advice at this point is to learn Python. You can learn this and Python modding in something like a week, if you only commit to it. Then you'll be able to do all the cool things you have thought of. See my signature for some obvious entry points.
 
My best advice at this point is to learn Python. You can learn this and Python modding in something like a week, if you only commit to it. Then you'll be able to do all the cool things you have thought of. See my signature for some obvious entry points.

I hate python. I started out with Java then C++. I'm used to a serious programing language. An indentation sensitive language is a joke to me sorry.

I will try your links and will still hope that there is another way out

Thank you for your answer
 
I'm sorry you feel that way. You're loss, however.
 
What you wanna do is attach a string value (ScriptData) to each plot with a resource on it. It could be a numerical character, like "7". But I don't believe you can do this with the World Builder, so you need to map each plot and add a value to it by script.

There must be a way to do this by hand...

I fiddled a bit into the python file for WB (CvWBDesc.py) and...I'm not sure what to do with it. I wanted to generate a popup when a strategic resource would be added. I saw the popup while loading a game but it disappeared before I could click 'ok'.

I'm curious where the actions for adding resources in WB are located. I would call it in JavaScript as a mouse 'onClick' event.
 
hi, it's been a while since I have modded Civ4 so I might of forgotten some things over time.

I've been playing Civ5 for a month and I want to reproduce it's Strategic Resources (SR) 'management' but in Civ4.

Now so far, I have edited the CvPlot and CyPlot classes for accessors, modifiers and variables for the amount of SRs on a plot object.

The problem is setting the amount of SRs in a simple to use way. I was thinking of using WorldBuilder to set that amount at the same time that a player would place a resource on a selected tile. I have found a function called ''CvPlot::setBonusType(BonusTypes eNewValue)'' and I wonder how to add code that would 'launch' a prompt in WB asking for an integer and using that number for the number of SRs on that tile.

I have very very little experience with Python so I'm not sure if what I want to do is feasible.

Any constructive input is welcome :)

Thank you

no need to use python (hopefully)

You can create a Popup in C++ in CvPlot::setBonusType

to check if the Worldbuilder is open, you can use gDLL->GetWorldBuilderMode(), which returns a bool.
 
You can create a Popup in C++ in CvPlot::setBonusType

How do I do that from the SDK ? I can launch a popup with text from python but not to the point of launching one with a 'textfield' that would require an integer.

Thanks for the tip about if WB is open :)
 
I don't know how you can add a textfield. But you could add a Button for every integer from 0 to 10. Or do you want even more resources on a plot?

In fact you probably could even do a hack by just triggering an event instead of creating a popup(which would generate the popup and everything else). All you would have to do then is define the eventtrigger, the different event options and tie code to the event options either by using the doPython tag or by adding a new xml tag to CvEventInfos.
 
I believe you can add a text box to a popup using gDLL->getInterfaceIFace()->popupCreateEditBox().

You can then access what was typed in the box using pPopupReturn->getEditBoxString(), which returns a CvWString string.

I'm not positive on this, I've never used it; I got it from ButtonPopupTypes::BUTTONPOPUP_ADMIN_PASSWORD, so you can look there for more info.
 
Thanks for all your input :)

I thought of something else after reading your comments and being naturally hard-headed I ignored all that you have said and tried something else :)

I found a file in the Python folder of the Vanilla version named 'CvWBPopups.py'. On examination of this file I determined that (when in WB and selecting to edit a city) a popup appears and that data could be 'imported' in the game. I liked what I saw so I tried adding content to that file in a way that was mimicking the existing mechanism. I was encouraged when I saw the first 4 lines of code in the file. The most important one was :

Code:
WBPopupEditPlot 		= WorldBuilderPopupTypes.WBPOPUP_PLOT

So in the constructor I added an entry 'self.WBPopupditPlot' with the corresponding code following it. I edited the self.initEditCity for self.initEditPlot cause I figured that it was just there to state which function to call upon.

Afterward I wrote 2 functions in the same file named 'initEditPlot' and 'applyEditPlot' both seem to go along the lines of the pre-existing functions.

Now when I launch my mod, enter any game and use WB for bonuses on tile, nothing happens. I think it is because I'm missing something to link up what I make with the way applying bonuses are done in WB.

I have attached only the python file from my mod below. Perhaps one of you maybe able to fix the problem.

Tomorrow I will try the suggestion of Sephi and try to figure out a way of launching a popup from the SDK.

oh yeah...the ISRM.py file is something I made that catalogs the strategic resources (SR) in the mod and makes an integer array with it. Each index represent a number in the Bonuses that represent a SR.

Thank you for your time :)
 

Attachments

Back later than I thought...

I'm slowly editing the CvPlot::setBonusType() function and I'm at the point where I want to launch a popup (through Python, in WB) in which the user will enter an integer representing the amount of resources he/she wants on the plot.

Not knowing how to launch a popup from the SDK I'm adding a function to my ISRM.py file which will do it instead. The problem is that I don't know how to retrieve the data from the 'EditBox' when using the PyPopup class. I have seen a few tutorials on here but they all seem to use an event manager in a way that I'm not sure if it is worth it or necessary.

I was hoping for predefined function that would allow me to manipulate the retrieve data right after a ''modpopup.launch()'' command. Is this possible ? Is there a way to create a CyPopupReturn object from a CyPopup ?

Thanks for the help :)
 
Also I need to call my ISRM.py (only once) from somewhere python object in the game. Is there a suggested place to put it ?

Also :) I need to call a function in my ISRM object declared above from the SDK with the CvPlot concerned in 'args'. I saw a function call that resembled 'gDLL->getPythonIFace()->callPythonFunction(pythonClass, pythonFunction)' but this seems just for 'void' functions. What about those who return a value and how do they work ?

Thanks for the input
 
back from a month of 55 hours of work per week

I'm in the process of debugging this new mod and I'm wondering how to get the CvPlot where the user in WB is modifying the amount of bonus resources (I'll just start with that for now) but from the CvDLLButtonPopup::OnOkClicked(...) function.

What I have done is setup a popup which works when the user adds a Bonus resource. There is a place where the user enters a number and then there is a 'ok' button. The dll compiles but I get a runtime error and generate .dmp file. the dmp file says the crash was caused by :

Code:
>CvGameCoreDLL.dll!CvPlayerRecord::getVictory()
CvGameCoreDLL.dll!CvDLLButtonPopup::OnOkClicked()

now I can find to call for getVictory() in the function OnOkClicked() and what I have added to the former is the following :

Code:
case BUTTONPOPUP_EDIT_AMOUNT_SR:
		{int numberSR = _wtoi(pPopupReturn->getEditBoxString(0));
		// Get current CvPlot, add numberSR to setBonusAmount()
		CvCity* pCity = GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getCity(info.getData1());
		int x = pCity->getX();
		int y = pCity->getY();
		CvPlot* pPlot = GC.getMap().plot(x, y); 
		pPlot->setBonusAmount(numberSR); }
		break;
	// LoneTraveler Strategic Resource Mod End

Now I'm rather sure that the problem is the ''CvCity* pCity = GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getCity(info.getData1());'' line but I don't with what to replace it.

Please help

Thank you for your time
 
It sounds like you're missing some information, so you can try using a debugger to see exactly where the runtime error occurs, and to check the values of the variables to see what's wrong (see my signature for a tutorial, if you need one).

Is data1 really a valid city ID? can you post the code which creates the popup?
 
It sounds like you're missing some information, so you can try using a debugger to see exactly where the runtime error occurs, and to check the values of the variables to see what's wrong (see my signature for a tutorial, if you need one).

I have followed your 'debugging' post and VS says that the error comes from the 2nd of the following lines :

Code:
CvCity* pCity = GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getCity(info.getData1());
int x = pCity->getX();

Is data1 really a valid city ID? can you post the code which creates the popup?

I honestly am not sure how 'data1' is being generated so here is the code :

Code:
bool CvDLLButtonPopup::launchEditAmountSRPopup(CvPopup* pPopup, CvPopupInfo &info)
{
	if(gDLL->GetWorldBuilderMode()) 
	{
		gDLL->getInterfaceIFace()->popupSetHeaderString(pPopup, gDLL->getText("TXT_KEY_EDIT_AMOUNT_SR_TITLE"));
		gDLL->getInterfaceIFace()->popupSetBodyString(pPopup, gDLL->getText("TXT_KEY_EDIT_AMOUNT_SR"));
		gDLL->getInterfaceIFace()->popupCreateEditBox(pPopup, "1", WIDGET_GENERAL, gDLL->getText("TXT_KEY_EDIT_AMOUNT_SR"), 0, POPUP_LAYOUT_STRETCH, 0, MAX_PASSWORD_CHAR_COUNT);
	}

	gDLL->getInterfaceIFace()->popupLaunch(pPopup, true, POPUPSTATE_IMMEDIATE);

	return true;
}

Thanks for your help Asaf :)
 
I assume the crash is there because pCity is an invalid pointer.
When you get the crash in VS, you can hover over 'pCity' or look at the locals or autos windows to see its value.
You'll probably see its value as 0 (or 0x00000000), which is a marker pointer for an illegal address (NULL). That means that getCity() in the previous line could not find the city with the given ID.

You can also do the same for 'info' and see what's 'data1' value in it.

data1 is set in the CvPopupInfo structure. It is determined in CvPopupInfo's constructor.
Search for the call to launchEditAmountSRPopup(). It should be in CvDLLButtonPopup::launchButtonPopup(). Then see which button popup enum value it is matched to (the "case" before the call). Should be something like BUTTONPOPUP_EditAmountSR or something (depends on your code).

Search for this value and you should see something similar to this code:
Code:
CvPopupInfo* pInfo = new CvPopupInfo(BUTTONPOPUP_EditAmountSR, ...)

in the '...' you can place more information, specifically data1, data2 etc.
Set data1 to be the city ID.
 
Everything you said accurate but the problem is that I don't necessarily want the pCity, it's the CvPlot selected (concerned) when the popup is launched that I want.

I don't know the command to get this CvPlot. I've been looking into the function 'OnOkClicked(...)' for something similar and didn't realize at first that not all CvPlots had CvCitys' on them...:rolleyes:
 
Then you can use the x,y coordinates as data1, data2 of the popup info, and use this to get the plot:
Code:
int iX = info.getData1();
int iY = info.getData2();
CvPlot* pPlot = GC.getMapINLINE().plot(iX, iY);
 
Back
Top Bottom