I am SO close, but need a bit of help...

renegadechicken

Warlord
Joined
Aug 12, 2007
Messages
227
Location
Civ II Verne Scenario
UPDATE: Done! Thanks to EmperorFool, who did all the coding (AND told me where to put everything!), this is no longer a work in progress, but a finished product! Enjoy, modders!

Download link: Events with Images mod


---------------------------------------------------------------
OLD STUFF
I am in the process of (what I consider to be) revolutionizing Events for all modders everywhere! :)

It all started with me wanting to include a popup with a picture just before events fired to give more visual appeal and atmosphere to events, like the one below:

Spoiler :


However, the popup would not appear before the event fired, and it was just weird having it show up after you've already made a decision on how to handle the event, so I went to the forums for help on ideas on how to make the popup appear prior to the event. Willem, a fellow forum-goer, wondered why I didn't just add the picture to the event screen so I could have them both at once. I chuckled to myself and thought how wonderful that would be, but it's just not possible. Then I thought about it for a second, and realized that's EXACTLY what needs to be done!

At Willem's suggestion, I PMed EmperorFool, a renowned modder on this site, and asked him if he knew where the event screen was handled so I could add an option to include a .dds picture to the event screen. He found it with no problem, but sadly it's in the SDK, which I don't know anything about.

So I have come to you, modding community, in the hopes that one of you will have a few minutes (I suspect maybe 10-20) to devote to this small but significant task. According to EmperorFool, there are only two steps to do this: add a tag in EventInfos.xml to hold the image (which I can do, as long as someone does the next step!), and then modify a bit of SDK to insert a call to add the image.

If you are interested in doing this for the modding community, I will forward you the message from EmperorFool which contains the bit of code that needs modifying. Thanks in advance to anyone willing to do this for us all! :)
 
Actually this looks like something that would be a good thing to learn the sdk with. If your interested in letting a modding newb try it, I'll give it a shot.
 
Of course! :) Below is the code that needs to be adjusted:

Code:
bool CvDLLButtonPopup::launchEventPopup(CvPopup* pPopup, CvPopupInfo &info)
{
	CvPlayer& kActivePlayer = GET_PLAYER(GC.getGameINLINE().getActivePlayer());
	EventTriggeredData* pTriggeredData = kActivePlayer.getEventTriggered(info.getData1());
	if (NULL == pTriggeredData)
	{
		return false;
	}

	if (pTriggeredData->m_eTrigger == NO_EVENTTRIGGER)
	{
		return false;
	}

	CvEventTriggerInfo& kTrigger = GC.getEventTriggerInfo(pTriggeredData->m_eTrigger);
	
	gDLL->getInterfaceIFace()->popupSetBodyString(pPopup, pTriggeredData->m_szText);

	bool bEventAvailable = false;
	for (int i = 0; i < kTrigger.getNumEvents(); i++)
	{
		if (GET_PLAYER(GC.getGameINLINE().getActivePlayer()).canDoEvent((EventTypes)kTrigger.getEvent(i), *pTriggeredData))
		{
			gDLL->getInterfaceIFace()->popupAddGenericButton(pPopup, GC.getEventInfo((EventTypes)kTrigger.getEvent(i)).getDescription(), GC.getEventInfo((EventTypes)kTrigger.getEvent(i)).getButton(), kTrigger.getEvent(i), WIDGET_CHOOSE_EVENT, kTrigger.getEvent(i), info.getData1());
			bEventAvailable = true;
		}
		else
		{
			gDLL->getInterfaceIFace()->popupAddGenericButton(pPopup, GC.getEventInfo((EventTypes)kTrigger.getEvent(i)).getDescription(), ARTFILEMGR.getInterfaceArtInfo("INTERFACE_EVENT_UNAVAILABLE_BULLET")->getPath(), -1, WIDGET_CHOOSE_EVENT, kTrigger.getEvent(i), info.getData1(), false);
		}
	}

	if (!bEventAvailable)
	{
		return false;
	}

	if (kTrigger.isPickCity())
	{
		CvCity* pCity = kActivePlayer.getCity(pTriggeredData->m_iCityId);
		FAssert(NULL != pCity);
		if (NULL != pCity)
		{
			gDLL->getInterfaceIFace()->popupAddGenericButton(pPopup, gDLL->getText("TXT_KEY_POPUP_EXAMINE_CITY").c_str(), ARTFILEMGR.getInterfaceArtInfo("INTERFACE_BUTTONS_CITYSELECTION")->getPath(), GC.getNumEventInfos(), WIDGET_GENERAL, -1, -1);
		}
	}

	if (kTrigger.isShowPlot())
	{
		CvPlot* pPlot = GC.getMapINLINE().plot(pTriggeredData->m_iPlotX, pTriggeredData->m_iPlotY);
		if (NULL != pPlot)
		{
			gDLL->getEngineIFace()->addColoredPlot(pPlot->getX_INLINE(), pPlot->getY_INLINE(), GC.getColorInfo((ColorTypes)GC.getInfoTypeForString("COLOR_WARNING_TEXT")).getColor(), PLOT_STYLE_CIRCLE, PLOT_LANDSCAPE_LAYER_RECOMMENDED_PLOTS);
			gDLL->getInterfaceIFace()->lookAt(pPlot->getPoint(), CAMERALOOKAT_NORMAL);
		}
	}

	gDLL->getInterfaceIFace()->popupLaunch(pPopup, !bEventAvailable, POPUPSTATE_IMMEDIATE);

	return true;
}

Since I don't actually know ANY C++, I'm not exactly sure where to put the extra line(s) to tell the popup to include an image, but if you feel up to the task, make the changes and upload them here, and I can see if they work (or you could test them too if you wanted; totally up to you!). Remember, according to EmperorFool, "It might not actually be too hard to add an image here. First, you would add an EventInfo field in XML to hold the image. Next you'd modify the code above and insert a call to add the image.", so apparently you need to make sure to create some sort of tag for the XML...or something...lol. I really don't know this SDK stuff! :)

Thanks to any who try this! :) I can always add the XML tag, as long as I know what exactly you changed.
 
When I'm trying something that I'm not sure up front will work the way I want, I do the hard part that I'm unsure of first. I am positive you can easily add an XML field to hold the image in CvEventInfo, so don't bother with that yet. First, try to get any image to show in the popup.

This line

Code:
gDLL->getInterfaceIFace()->popupSetBodyString(pPopup, pTriggeredData->m_szText);

places the main event text. The lines after it place the options for events with a choice. Just insert the call to place the image before the line above. This is probably the function you want:

Code:
CvDLLInterfaceIFaceBase::popupAddDDS( 
    CvPopup* pPopup, 
    const char* szIconFilename, 
    int iWidth = 0, 
    int iHeight = 0, 
    CvWString szHelpText = "")

I assume that leaving width and height 0 will use the image's actual values, and you don't need help text for it since the description is below it already. That leaves something like this:

Code:
gDLL->getInterfaceIFace()->popupAddDDS(pPopup, "Art/Events/rebel_base.dds");

Then compile (the hard part) and bingo! Just add the image in the right spot in CustomAssets/Art, and you should be good to go.
 
Whoa....did you just do it? You just coded it for me? If so, thank you so much!! :)

I assume I need to add that code to the section you pointed out, but once I do that, I need to edit the EventSchema.txt as well, right? Or wait, you just made it so that it's an "isolated" popup that will only work with that .dds, just to test it? So all I need to do is add that code in the right place in the SDK and have the .dds in that folder, and I can test it by triggering the event using the console?

Man I hope this works! Even if it doesn't, thank you once again for your invaluable help, EmperorFool!
 
Ok, I just opened up the CvGameCoreDLL folder, and I'm a bit lost...which file do I edit/add this code to? There are quite a few of them, and I'm not sure which one it goes in.

Is there a good tutorial on SDK? I've looked, and I can't find one that makes any sense. I don't know how SDK works, or even what those letters stand for! :) I'm not even sure what compiling is... Honestly, I'm willing to learn, but I just don't know where to start! :) If I know where to add the code, I can do it, but I need to know how to compile as well.
 
Editing the file (CvDLLButtonPopup.cpp) is only the first step. You need to use a make file to compile all the .cpp and .h files into a new CvGameCoreDLL.dll file. This part, sadly, is a PITA. I have mine setup for BULL which includes files not in the original SDK, so I can't just build you one from my code.

There are instructions posted to this SDK forum for setting up Visual C++ 2005 Express Edition and a make file. There are also instructions to use Code:Blocks, a similar tool. Both programs are free. You'll need to download some other free tools from Microsoft for either approach.

You are correct in your last statement about the code I wrote: it is only a test for a single image. However, once the new field is added to CvEventInfo, it would be pretty easy to pull up the correct image.
 
Ah, I see what you're saying...I think. So all those files in that folder are compiled to make up the large, single file that controls everything. So I need to follow the instructions in that tutorial so I can compile the edited one with all the unchanged ones to create the new big file (I must sound like a first grader or something...lol).

It seems pretty simple...doesn't the program compile it for me? Why is that a pain? It must be harder than I'm imagining...
 
Okay, here is the code with the edits (additions are in bold, and only in that one section):

Code:
bool CvDLLButtonPopup::launchEventPopup(CvPopup* pPopup, CvPopupInfo &info)
{
	CvPlayer& kActivePlayer = GET_PLAYER(GC.getGameINLINE().getActivePlayer());
	EventTriggeredData* pTriggeredData = kActivePlayer.getEventTriggered(info.getData1());
	if (NULL == pTriggeredData)
	{
		return false;
	}

	if (pTriggeredData->m_eTrigger == NO_EVENTTRIGGER)
	{
		return false;
	}

	CvEventTriggerInfo& kTrigger = GC.getEventTriggerInfo(pTriggeredData->m_eTrigger);

       [B]CvDLLInterfaceIFaceBase::popupAddDDS(
		CvPopup* pPopup, 
		const char* szIconFilename, 
		int iWidth = 0, 
		int iHeight = 0, 
		CvWString szHelpText = "")

       gDLL->getInterfaceIFace()->popupAddDDS(pPopup, "Art/Interface/PopUps/rebelbase.dds");[/B]
	
	gDLL->getInterfaceIFace()->popupSetBodyString(pPopup, pTriggeredData->m_szText);

	bool bEventAvailable = false;
	for (int i = 0; i < kTrigger.getNumEvents(); i++)
	{
		if (GET_PLAYER(GC.getGameINLINE().getActivePlayer()).canDoEvent((EventTypes)kTrigger.getEvent(i), *pTriggeredData))
		{
			gDLL->getInterfaceIFace()->popupAddGenericButton(pPopup, GC.getEventInfo((EventTypes)kTrigger.getEvent(i)).getDescription(), GC.getEventInfo((EventTypes)kTrigger.getEvent(i)).getButton(), kTrigger.getEvent(i), WIDGET_CHOOSE_EVENT, kTrigger.getEvent(i), info.getData1());
			bEventAvailable = true;
		}
		else
		{
			gDLL->getInterfaceIFace()->popupAddGenericButton(pPopup, GC.getEventInfo((EventTypes)kTrigger.getEvent(i)).getDescription(), ARTFILEMGR.getInterfaceArtInfo("INTERFACE_EVENT_UNAVAILABLE_BULLET")->getPath(), -1, WIDGET_CHOOSE_EVENT, kTrigger.getEvent(i), info.getData1(), false);
		}
	}

	if (!bEventAvailable)
	{
		return false;
	}

	if (kTrigger.isPickCity())
	{
		CvCity* pCity = kActivePlayer.getCity(pTriggeredData->m_iCityId);
		FAssert(NULL != pCity);
		if (NULL != pCity)
		{
			gDLL->getInterfaceIFace()->popupAddGenericButton(pPopup, gDLL->getText("TXT_KEY_POPUP_EXAMINE_CITY").c_str(), ARTFILEMGR.getInterfaceArtInfo("INTERFACE_BUTTONS_CITYSELECTION")->getPath(), GC.getNumEventInfos(), WIDGET_GENERAL, -1, -1);
		}
	}

	if (kTrigger.isShowPlot())
	{
		CvPlot* pPlot = GC.getMapINLINE().plot(pTriggeredData->m_iPlotX, pTriggeredData->m_iPlotY);
		if (NULL != pPlot)
		{
			gDLL->getEngineIFace()->addColoredPlot(pPlot->getX_INLINE(), pPlot->getY_INLINE(), GC.getColorInfo((ColorTypes)GC.getInfoTypeForString("COLOR_WARNING_TEXT")).getColor(), PLOT_STYLE_CIRCLE, PLOT_LANDSCAPE_LAYER_RECOMMENDED_PLOTS);
			gDLL->getInterfaceIFace()->lookAt(pPlot->getPoint(), CAMERALOOKAT_NORMAL);
		}
	}

	gDLL->getInterfaceIFace()->popupLaunch(pPopup, !bEventAvailable, POPUPSTATE_IMMEDIATE);

	return true;
}

Is that what I need to do? I'm going to try it, even though I have no idea what I did or if it's remotely correct... :) Just need to compile all this junk...
 
Ah, I see what you're saying...I think. So all those files in that folder are compiled to make up the large, single file that controls everything. So I need to follow the instructions in that tutorial so I can compile the edited one with all the unchanged ones to create the new big file (I must sound like a first grader or something...lol).

It seems pretty simple...doesn't the program compile it for me? Why is that a pain? It must be harder than I'm imagining...

I used this tutorial, and it worked fine, I had no prior experience with programming before that:
http://forums.civfanatics.com/showthread.php?t=196283

First try to compile the source code into a .dll unaltered. Once you get that working try to compile your modded code.

For a brief explanation of how it works. Computers don't understand C++ or other programming languages. Everything a computer does is in binary, all the processor understands is 0s and 1s. We, as humans, right code in programming languages so we can read and understand them. But to get it so that the computer can understand, and run the functions we want, the code is run through compilers to compile the code into machine language so that the information can be understood by the computer.
 
For a brief explanation of how it works. Computers don't understand C++ or other programming languages. Everything a computer does is in binary, all the processor understands is 0s and 1s. We, as humans, right code in programming languages so we can read and understand them. But to get it so that the computer can understand, and run the functions we want, the code is run through compilers to compile the code into machine language so that the information can be understood by the computer.

Ahhhh, I see. That makes sense. Oh, and thanks for the handy tutorial link! I'm actually already compiling my changes now, but when they go horribly wrong and break my game, I'll know where to go. Thankfully I had to foresight to back up the entire folder, so hopefully I won't have to reinstall...right? :D
 
Ok, well, as I thought they might, things have gone horribly wrong...

The good news is that, as far as I can tell, it compiled nicely. The bad news is that there were two error "messages" down at the very bottom of the screen in Code::Blocks. It was probably something I did. :( Here they are:

Code:
error c2275:  'CvPopup'   :  illegal use of this type as an expression
error c2059:  syntax error  :  'const'
=== Build finished: 2 errors, 0 warnings ===

So apparently it didn't like the following two lines of code:

Code:
       CvDLLInterfaceIFaceBase::popupAddDDS(
--->		CvPopup* pPopup, 
--->		const char* szIconFilename, 
		int iWidth = 0, 
		int iHeight = 0, 
		CvWString szHelpText = "")

       gDLL->getInterfaceIFace()->popupAddDDS(pPopup, "Art/Interface/PopUps/rebelbase.dds");

What did I do wrong? :crazyeye: Was it my formatting?
 
If you get an error, the build fails, so it didn't compile. Did you compile an unaltered core first? Do that first, it'll make working on changes easier, as the compiler only needs to recompile the part of the code from the file you alter after it makes a working gamecore.
 
Oh, ok. So in other words, I should've done what you said in the first place. :) Oh well, I'll do that now...

You don't happen to know what's wrong with the code, though, do you? In either case, thanks for the help!
 
You only need the single last line of what you have added. The first multiline part I posted was what's called a function declaration. I was merely pointing out what function was needed here. The second block of code (1 line) that I posted is called a function call. This is where you are actually using the function.

To reiterate, keep only the part that starts with

Code:
gDLL->getInterfaceIFace()->...

Good job on going through the tutorial. I only said it was a pain as in a lot of grunt work that's no fun. It's only difficult if you do what I did: think you know so much you can deviate from the directions to make it "better". :mischief: I eventually followed the directions.
 
Ohhhhh...wow, I really only need the last line? Nice coding! :)

Man, when I was going through that tutorial, I followed it to the letter. I must've checked it like three times to make SURE I was doing it right, because honestly, I had NO idea what they were talking about. Honestly I'm amazed that I made it through that thing.

Thanks for helping me with the code, and correcting my...over eagerness to add stuff. :) I'm off to give it a try!
 
I actually never though I'd see this day. My hopes were high, sure, but I didn't really think this was possible. Thanks to you, EmperorFool, events can now have images with them! :)

:bowdown:

Here's the proof that it works, so you can see the fruits of your labors:

Spoiler :


Thanks again-- once we refine the code to allow for any picture to be used (that's the XML part, right?), we can share it with the rest of the modding community! I don't know about you, but I'm very excited! I may be the one uploading it, but you're the one who has changed events for us all! :)
 
Awesome! So now it's time to add the XML field. There are a few files you'll need to hit. CvInfos.cpp is in charge of reading the XML I think. It defines CvEventInfo for sure. Then you need to change the schema for CIV4EventInfos.xml. I haven't done any of this--just helped someone else find where to do it once.
 
Awesome! So now it's time to add the XML field. There are a few files you'll need to hit. CvInfos.cpp is in charge of reading the XML I think. It defines CvEventInfo for sure. Then you need to change the schema for CIV4EventInfos.xml. I haven't done any of this--just helped someone else find where to do it once.

Okay, I can change the schema with no problems, cuz that's XML. I just can't do any of the SDK, because I really don't understand it at all. :( So can someone help me out (we're almost there!) by changing this code:

Code:
gDLL->getInterfaceIFace()->popupAddDDS(pPopup, "Art/Events/rebel_base.dds");

to something that will allow any .dds to be used, based on what is entered in the (brand new!) <EventArt/> tag in the EventTriggerInfos.xml (which I've updated using the EventSchema.txt, but it obviously doesn't do anything yet). For example, you could put in:

Code:
<EventTriggerInfo>
			<Type>EVENTTRIGGER_REBEL_HIDEOUT</Type>
			<WorldNewsTexts>
				<Text>TXT_KEY_EVENTTRIGGER_REBEL_HIDEOUT</Text>
			</WorldNewsTexts>
			<TriggerTexts>
				<TriggerText>
					<Text>TXT_KEY_EVENT_TRIGGER_REBEL_HIDEOUT</Text>
					<Era>NONE</Era>
				</TriggerText>
			</TriggerTexts>
                        [B][I]<EventArt>Art/Interface/PopUps/rebelbase.dds</EventArt>[/I][/B]
			<bSinglePlayer>0</bSinglePlayer>

Clear as mud? I hope someone can do this, because it's the very last step! Thanks once again for your incredible help, everyone! Especially you, EmperorFool, who had to do it for me and then babystep me through adding it all in. :) I know you're busy, so thanks for taking the time to help me out!
 
Top Bottom