Adding new Resource Yields to Future Techs

Actually, I used CvGameTextMgr::setBuildingHelp. I've just been copying exactly GlobalReligionCommerce. I thought that'd be the easiest way to at least get started and have it show up in the 'Pedia...

So, wherever GlobalReligionCommerce shows up, I've inserted directly above it an entry for GlobalReligionYield that is identical (except for Commerce -> Yield).
 
Gotcha, so linked to building and not to religion. That should parse well enough, so I'd say post your code so we can see it. But before that, you can check to see if the error is in XML loading or Text ouput pretty simple. Go to CvInfos and change your ::get____() functions to ALWAYS return some integer value. Then you completely ignore the XML and you know for sure that every building should provide some value. Like maybe 3 food, 4 production and 6 commerce. Then you load up the game and glance at any building to see if your text string appears at all. If it appears, then your XML loading is to blame. If it doesn't, then it is your Text output code.
 
OK, here is my code. My stuff in bold, followed each time by some stock code so you know where my stuff is.

Spoiler CvGameTxtMgr.cpp :

Code:
[B]	if (kBuilding.getGlobalReligionYield() != NO_RELIGION)
	{
		szFirstBuffer = gDLL->getText("TXT_KEY_BUILDING_PER_CITY_WITH", GC.getReligionInfo((ReligionTypes) kBuilding.getGlobalReligionYield()).getChar());
		setYieldChangeHelp(szBuffer, L"", L"", szFirstBuffer, GC.getReligionInfo((ReligionTypes) kBuilding.getGlobalReligionYield()).getGlobalReligionYieldArray());
	}[/B]

	if (kBuilding.getGlobalReligionCommerce() != NO_RELIGION)
	{
		szFirstBuffer = gDLL->getText("TXT_KEY_BUILDING_PER_CITY_WITH", GC.getReligionInfo((ReligionTypes) kBuilding.getGlobalReligionCommerce()).getChar());
		setCommerceChangeHelp(szBuffer, L"", L"", szFirstBuffer, GC.getReligionInfo((ReligionTypes) kBuilding.getGlobalReligionCommerce()).getGlobalReligionCommerceArray());
	}

Spoiler CvInfos.h :

Code:
[B]	DllExport int getGlobalReligionYield() const;				// Exposed to Python[/B]
	DllExport int getGlobalReligionCommerce() const;				// Exposed to Python

[COLOR="Red"]---------------[/COLOR]

[B]	int m_iGlobalReligionYield;
[/B]	int m_iGlobalReligionCommerce;

[COLOR="Red"]---------------[/COLOR]

[B]	DllExport int getGlobalReligionYield(int i) const;		// Exposed to Python
	int* getGlobalReligionYieldArray() const;			
[/B]	DllExport int getGlobalReligionCommerce(int i) const;		// Exposed to Python

[COLOR="Red"]---------------[/COLOR]

[B]	int* m_paiGlobalReligionYield;		
[/B]	int* m_paiGlobalReligionCommerce;


Spoiler CvInfos.cpp :

Code:
[b]m_iGlobalReligionYield(0),
[/b]m_iGlobalReligionCommerce(0),

[COLOR="Red"]---------------[/COLOR]

[b]int CvBuildingInfo::getGlobalReligionYield() const
{
	return m_iGlobalReligionYield;
}
[/b]
int CvBuildingInfo::getGlobalReligionCommerce() const
{
	return m_iGlobalReligionCommerce;
}

[COLOR="Red"]---------------[/COLOR]

[b]	stream->Read(&m_iGlobalReligionYield);
[/b]	stream->Read(&m_iGlobalReligionCommerce);

[COLOR="Red"]---------------[/COLOR]

[b]	stream->Write(m_iGlobalReligionYield);
[/b]	stream->Write(m_iGlobalReligionCommerce);

[COLOR="Red"]---------------[/COLOR]

[b]	pXML->GetChildXmlValByName(szTextVal, "GlobalReligionYields");
	m_iGlobalReligionYield = pXML->FindInInfoClass(szTextVal);
[/b]
	pXML->GetChildXmlValByName(szTextVal, "GlobalReligionCommerce");
	m_iGlobalReligionCommerce = pXML->FindInInfoClass(szTextVal);

[COLOR="Red"]---------------[/COLOR]

[b]m_paiGlobalReligionYield(NULL),
[/b]m_paiGlobalReligionCommerce(NULL),

[COLOR="Red"]---------------[/COLOR]

[b]	SAFE_DELETE_ARRAY(m_paiGlobalReligionYield);
[/b]	SAFE_DELETE_ARRAY(m_paiGlobalReligionCommerce);

[COLOR="Red"]---------------[/COLOR]

[b]int CvReligionInfo::getGlobalReligionYield(int i) const
{
	FAssertMsg(i < NUM_YIELD_TYPES, "Index out of bounds");
	FAssertMsg(i > -1, "Index out of bounds");
	return m_paiGlobalReligionYield ? m_paiGlobalReligionYield[i] : -1; 
}

int* CvReligionInfo::getGlobalReligionYieldArray() const
{
	return m_paiGlobalReligionYield;
}
[/b]
int CvReligionInfo::getGlobalReligionCommerce(int i) const
{
	FAssertMsg(i < NUM_COMMERCE_TYPES, "Index out of bounds");
	FAssertMsg(i > -1, "Index out of bounds");
	return m_paiGlobalReligionCommerce ? m_paiGlobalReligionCommerce[i] : -1; 
}

[COLOR="Red"]---------------[/COLOR]

[b]	if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"GlobalReligionYields"))
	{
		pXML->SetYields(&m_paiGlobalReligionYield);
		gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
	}
	else
	{
		pXML->InitList(&m_paiGlobalReligionYield, NUM_YIELD_TYPES);
	}
[/b]
	if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"GlobalReligionCommerces"))
	{
		pXML->SetCommerce(&m_paiGlobalReligionCommerce);


xienwolf, though I love your idea of forcing just a single output from my code, and I understand the concept, I'm afraid I can't figure out how to implement it. What would I change the getGlobalReligionYield statement to? I mean, how exactly would I write it?

And interpreting the resluts, I'm afarid you lost me. :crazyeye: If I change my code to force +4:food:, and the 'Pedia shows +4:food:, then the problem is my XML, I've typo'd something. But if I don't see +4:food:, then I've buggered the code somehow, right?
 
Basically you are just removing some variables to isolate the fault. So to test that the XML loading is fine, you would change your CvInfos to use:

Spoiler CvInfos.cpp :

Code:
[b]int CvReligionInfo::getGlobalReligionYield(int i) const
{
	FAssertMsg(i < NUM_YIELD_TYPES, "Index out of bounds");
	FAssertMsg(i > -1, "Index out of bounds");

	int[] FakeArray = {1,2,3};
	return m_FakeArray[i]; 
//	return m_paiGlobalReligionYield ? m_paiGlobalReligionYield[i] : -1; 
}

int* CvReligionInfo::getGlobalReligionYieldArray() const
{
	return {1,2,3};   //Pretty sure there are 3 Yields in the game...
//	return m_paiGlobalReligionYield;
}
[/b]


Writting this all outside of the DLL, so I could have some formatting wrong. But the point is to create a dummy array which you know DOES have values loaded in it.

To be sure that your GameText is running, you would add something like this:


Spoiler CvGameTxtMgr.cpp :

Code:
[B]		szBuffer.append(NEWLINE);
		szBuffer.append(NEWLINE);
        szBuffer.append(gDLL->getText("Testing for Global Religion Yield"));
	if (kBuilding.getGlobalReligionYield() != NO_RELIGION)
	{
		szBuffer.append(NEWLINE);
		szBuffer.append(NEWLINE);
        szBuffer.append(gDLL->getText("Global Religion Yield Detected"));
		szBuffer.append(NEWLINE);
		szBuffer.append(NEWLINE);
		szFirstBuffer = gDLL->getText("TXT_KEY_BUILDING_PER_CITY_WITH", GC.getReligionInfo((ReligionTypes) kBuilding.getGlobalReligionYield()).getChar());
		setYieldChangeHelp(szBuffer, L"", L"", szFirstBuffer, GC.getReligionInfo((ReligionTypes) kBuilding.getGlobalReligionYield()).getGlobalReligionYieldArray());
		szBuffer.append(NEWLINE);
		szBuffer.append(NEWLINE);
	}
		szBuffer.append(NEWLINE);
		szBuffer.append(NEWLINE);
[/B]

	if (kBuilding.getGlobalReligionCommerce() != NO_RELIGION)
	{
		szFirstBuffer = gDLL->getText("TXT_KEY_BUILDING_PER_CITY_WITH", GC.getReligionInfo((ReligionTypes) kBuilding.getGlobalReligionCommerce()).getChar());
		setCommerceChangeHelp(szBuffer, L"", L"", szFirstBuffer, GC.getReligionInfo((ReligionTypes) kBuilding.getGlobalReligionCommerce()).getGlobalReligionCommerceArray());
	}

The excessive NEWLINE use is so that it stands out nice and easy in the pedia for you.

You can also force your ::getGlobalReligionYield() function to always "return (ReligionTypes)0;" if you wanted to make absolutely certain that this text function runs for every building.



I'd start with the GameTextMgr test first, then if it is displaying "Global Religion Yield Detected" on the appropriate building (and only on the appropriate ones) add the CvInfos test, otherwise add the getGlobalReligionYield() modification since it would seem that it is failing to ever notice a religion declared (hinting at an error in that portion of the XML loading)



Looking at it one last time, I find this suspicious:

pXML->GetChildXmlValByName(szTextVal, "GlobalReligionYields");

I am almost certain you do not want that s at the end of GlobalReligionYields. I would imagine the XML structure is something like:

<GlobalReligionYield>RELIGION_ISLAM<GlobalReligionYield>

And then sometime later you have commerces listed inside of <GlobalReligionYields> tags.
 
I think you're right about GlobalReligionYieldS -> GlobalReligionYield. Unfortunately, it wasn't a nice easy fix.

The XML being drawn from however, is Civ4ReligionInfo, which defines the seven religions in general, including what the Shrines give. So it's not in Civ4BuildingInfo that things are taking place. Here's an example of GRCommerce & GBY:
Code:
	<GlobalReligionYields>
		<iGlobalReligionYield>0</iGlobalReligionYield>
		<iGlobalReligionYield>0</iGlobalReligionYield>
		<iGlobalReligionYield>2</iGlobalReligionYield>
	</GlobalReligionYields>
	<GlobalReligionCommerces>
		<iGlobalReligionCommerce>1</iGlobalReligionCommerce>
		<iGlobalReligionCommerce>0</iGlobalReligionCommerce>
		<iGlobalReligionCommerce>0</iGlobalReligionCommerce>
	</GlobalReligionCommerces>
I'll be able to try your new code for testing tomorrow. Thank again!
 
Ah, now I see that it is calling the religion for the array. Missed that before. But just ditching that extra s will probably solve everything for you. The rest just looks too flawless, and that extra s wouldn't cause any direct errors.
 
I wasn't clear before: You were right about the S at the end of GlobalReligionYield, I agree with you that it should not be there. It has been removed. Doing so had no effect.

I tried your "Newline" suggestion for CGTM, no effect. Nothing, zip. 'Pedia entries for the seven Shrines look perfectly normal, like I'd never added a thing, same as they did before. Ah well... :sad:

I will be trying your suggestion of the "FakeArray" for CvInfos tomorrow (later today? :crazyeye:). It'll take me longer cause I'll have to construct the "m_FakeArray" item. I just hope I can do that...

Thanks xienwolf.
 
You should be able to just type in an array manually like how I had in the sample. Curly braces around an appropriate quantity of integers.

Do you know how to print to a log file? It might be useful to print exactly what is being loaded from the XML at the moment it is loading it (before it can even be converted to an INT).

You need logging enabled, then you can use commands along these lines:

TCHAR szFile[1024];
TCHAR szOut[1024];
sprintf(szFile, "Debugger - Player %d - Set %d.log", GC.getGameINLINE().getActivePlayer(), getGameTurn()/50);

sprintf(szOut, "[%04d] %5d of %-5d -- %s\n", getGameTurn()+1, Result, iNum, pszLog);
gDLL->logMsg(szFile,szOut, false, false);


This sample being from my logger for random numbers, but it demonstrates how to output both an INT and a String value to the file for review.
 
Well, just adding the "FakeArray" code to CvInfos causes an error when compiling, so I need to change something. this is what CodeBlocks spits out at me:
Spoiler :
Line 15710 is int[] FakeArray = {1,2,3};
Code:
CvInfos.cpp|15710|warning C4091: '' : ignored on left of 'int' when no variable is declared|
CvInfos.cpp|15710|error C2143: syntax error : missing ';' before '['|
CvInfos.cpp|15710|error C3409: empty attribute block is not allowed|
CvInfos.cpp|15710|error C2146: syntax error : missing ';' before identifier 'FakeArray'|
CvInfos.cpp|15710|error C2065: 'FakeArray' : undeclared identifier|
CvInfos.cpp|15710|error C2059: syntax error : '{'|
CvInfos.cpp|15710|error C2143: syntax error : missing ';' before '{'|
CvInfos.cpp|15710|error C2143: syntax error : missing ';' before '}'|
CvInfos.cpp|15711|error C2065: 'm_FakeArray' : undeclared identifier|
CvInfos.cpp|15717|error C2059: syntax error : '{'|
CvInfos.cpp|15717|error C2143: syntax error : missing ';' before '{'|
CvInfos.cpp|15717|error C2143: syntax error : missing ';' before '}'|
||=== Build finished: 11 errors, 1 warnings ===|
So, it doesn't work on it's own. I can see that it doesn't like the term FakeArray, that's easy to fix, but it looks like maybe some of the brackets are wrong. I just have to play with it.

Unfortunately, as for the logging... I have logs turned on, but I don't know how to construct something specific to my situation. I appreciate the example, but I'm afraid I don't know how to use it... :cry: I just don't know enough C++... :sad:
 
OK, I'm sorry xienwolf, I'm trying, but you're gonna have to lead me a little closer to the nose...

Here's what CvInfos.cpp looks like right now (my code bold):
Code:
[B]int CvReligionInfo::getGlobalReligionYield(int i) const
{
	FAssertMsg(i < NUM_YIELD_TYPES, "Index out of bounds");
	FAssertMsg(i > -1, "Index out of bounds");

	int FakeArray [] = {1,2,3};
	return i+1;
}

int* CvReligionInfo::getGlobalReligionYieldArray() const
{
	return {1,2,3}; [/b][I](this is line 15717)[/I][b]
}[/B]

int CvReligionInfo::getGlobalReligionCommerce(int i) const

With a corresponding section in CvInfos.h saying:
Code:
	[B]int FakeArray() const;[/B]
	DllExport int getGlobalReligionCommerce(int i) const;		// Exposed to Python

I know this isn't what you intended for me to write, cause CodeBlocks doesn't like the return {1,2,3}; in CvInfos.cpp, but I don't know how to fix it. The error is:
CvInfos.cpp|15717|error C2059: syntax error : '{'|
CvInfos.cpp|15717|error C2143: syntax error : missing ';' before '{'|
CvInfos.cpp|15717|error C2143: syntax error : missing ';' before '}'|
||=== Build finished: 3 errors, 0 warnings ===|
Sorry xienwolf...
 
No problem, it just doesn't like an impromptu array I suppose.

Since you use the "return i+1;" in the first of the two functions, you don't need FakeArray. But in the second function it wants the array defined better, so move the FakeArray down into the second function and use "return FakeArray"

Code:
[B]int CvReligionInfo::getGlobalReligionYield(int i) const
{
	FAssertMsg(i < NUM_YIELD_TYPES, "Index out of bounds");
	FAssertMsg(i > -1, "Index out of bounds");

	return i+1;
}

int* CvReligionInfo::getGlobalReligionYieldArray() const
{
	int FakeArray [] = {1,2,3};
	return FakeArray;
}[/B]


You shouldn't need anything in CvInfos for FakeArray at all. We are defining it locally (Use in this function only), the header is for things you want to use in multiple functions
 
OK, that compiled, though with an error:
CvInfos.cpp|15717|warning C4172: returning address of local variable or temporary|
Is that just warning us of what we already know, that we defined & called the same item at once?

Unfortunately, either I'm crazy or we're missing something, cause the 'Pedia is still utterly unaffected... Now I'm at a loss. The FutureYields were so easy to get showing! :cry: :wallbash:
 
Instead of having a fake array, just initialize the real array with 1, 2, 3 in the function that returns the array. Yes, it will set the values each time it's called, but this is just for testing.

The reason you cannot return the fake array is that it lives on the stack as a local variable in that function. As soon as the function exits with the return, that space is reclaimed as the stack is unwound.
 
Oh, that error would mean that you DO need to declare the array globally (in the header, and then NOT re-declare in the function) in order to pass it out to other files. I suppose I should have seen that one coming.

Pedia information isn't displaying at all just means that now we know for sure the error is in the CvGameTextMgr file (which doesn't mean we are error free in CvInfos neccessarily, but we can hope).


Go ahead and revert your CvInfos back to what you had originally (remove the debug modifications) and focus on CvGameTextMgr. Place lines of text like:

szBuffer.append(gDLL->getText("About to check IF (getGlobalReligionYield)"));

before every IF statement or loop or function call, so that when you look in the pedia it will tell you what the last function is that it ran. That will at least narrow down where to look for the error. Then start replacing whatever function call or IF statement that has the error with straight values (ie - replace IF (getGlobalReligionYield != NO_RELIGION) with IF (true)) Also make the previous statement print the values about to be used in the IF statement if you want to be really efficient:

szBuffer.append(gDLL->getText("About to check IF (getGlobalReligionYield (%d) != NO_RELIGION (-1))", kBuilding.getGlobalReligionYield()));
 
I'm starting to think I'm working in the wrong file...

I tried your suggestion xienwolf, but nothing changes in the 'Pedia. The Wonders page still looks normal. Here's what CvGameTextMgr looks like now:

Code:
// RichMod Shrine Yields Start - Step 1, Add Yields to Shrines
if (kBuilding.getGlobalReligionYield() != false)
{
	szFirstBuffer = gDLL->getText("TXT_KEY_BUILDING_PER_CITY_WITH", GC.getReligionInfo((ReligionTypes) kBuilding.getGlobalReligionYield()).getChar());
	setYieldChangeHelp(szBuffer, L"", L"", szFirstBuffer, GC.getReligionInfo((ReligionTypes) kBuilding.getGlobalReligionYield()).getGlobalReligionYieldArray());
}
// RichMod Shrine Yields End - Step 1, Add Yields to Shrines
	
if (kBuilding.getGlobalReligionCommerce() != NO_RELIGION)
{
	szBuffer.append(gDLL->getText("About to check IF (getGlobalReligionCommerce (%d) != NO_RELIGION (-1))", kBuilding.getGlobalReligionCommerce()));
	szFirstBuffer = gDLL->getText("TXT_KEY_BUILDING_PER_CITY_WITH", GC.getReligionInfo((ReligionTypes) kBuilding.getGlobalReligionCommerce()).getChar());
	setCommerceChangeHelp(szBuffer, L"", L"", szFirstBuffer, GC.getReligionInfo((ReligionTypes) kBuilding.getGlobalReligionCommerce()).getGlobalReligionCommerceArray());
}
Your first suggested szBuffer line didn't do anything, I'm afraid. With both, I've tried at the beginning & the end of the IF statements (both stock & mine), and before and after them. I also tried changing "if (kbuilding.getGlobalReligionCommerce" to TRUE, and that did nothing either...

Like I said, I think I'm in the wrong file. Could this part of 'Pedia be drawn from somewhere else?
 
It is possible, some functions in the DLL ar edeprecated without comment. I guess the only way to be sure would be if you can find something which you know for sure IS displayed in the pedia that is also listed in this section of the code, and search for it appearing somewhere else as well.

I don't suppose you'd be willing to switch to Visual Studio for a compiler so that you can debug the thing and step through the code? :) Would be more helpful than the attempts to modify how the buffer is built as you could just set a breakpoint and look for a way to activate it, then walk through and check each value along the way.
 
Back
Top Bottom