Adding new Resource Yields to Future Techs

Ugh... Success so close I can taste it, but C++ hates me... :rolleyes:

Made the following change (bolded (yes I remembered the Header)):
Code:
int CvCity::getGlobalReligionYieldByReligion(YieldTypes eIndex, ReligionTypes eReligion, BuildingTypes eBuilding) const
{
	int iYield;

	FAssertMsg(eIndex >= 0, "eIndex expected to be >= 0");
	FAssertMsg(eIndex < NUM_YIELD_TYPES, "eIndex expected to be < NUM_YIELD_TYPES");
	FAssertMsg(eReligion >= 0, "eReligion expected to be >= 0");
	FAssertMsg(eReligion < GC.getNumReligionInfos(), "GC.getNumReligionInfos expected to be >= 0");

	iYield = 0;

	if (isHasReligion(eReligion))
	{
[B]		if (GC.getBuildingInfo(eBuilding).getGlobalReligionYields() != NO_RELIGION)
[/B]		{
				iYield += GC.getReligionInfo(eReligion).getGlobalReligionYield(eIndex) * GC.getGameINLINE().countReligionLevels(eReligion);
		}
	}
	return iYield;
}


void CvCity::updateGlobalReligionYield(YieldTypes eIndex)
{
	int iOldYield = getGlobalReligionYield(eIndex);
	int iNewYield = 0;

	for (int iI = 0; iI < GC.getNumReligionInfos(); iI++)
	{[COLOR="Red"]// The below line is #8390[/COLOR]
		iNewYield += getGlobalReligionYieldByReligion(eIndex, (ReligionTypes)iI);
	}

	if (iOldYield != iNewYield)
	{
		m_aiGlobalReligionYield[eIndex] = iNewYield;
		FAssert(getGlobalReligionYield(eIndex) >= 0);

		changeBaseYieldRate(eIndex, (iNewYield - iOldYield));
	}
}

and got this error:
CvCity.cpp(8390) : error C2660: 'CvCity::getGlobalReligionYieldByReligion' : function does not take 2 arguments

Changing the offending line to:
iNewYield += getGlobalReligionYieldByReligion(eIndex, (ReligionTypes, BuildingTypes)iI);
or
iNewYield += getGlobalReligionYieldByReligion(eIndex, (ReligionTypes), (BuildingTypes)iI);
didn't work either, it just gave me syntax errors about the ",". Removing the comma (with or without the extra brackets in the middle) gives me the same "function does not take 2 arguments."

I'm thinking, make yet another function, this one to produce a boolean result, checking for if (GC.getBuildingInfo(eBuilding).getGlobalReligionYields() != NO_RELIGION), and then calling this cinquinary (is that a word? I mean fifth) function within the existing int CvCity::getGlobalReligionYieldByReligion(). If it's true, then I proceed with calculating the Yield output. Good? Maybe?
 
Ack!! Next page!

I'm not checking if the city has the shrine, I've just confirmed it. It appears that I'm just checking if the city has a religion, and then giving it a bonus for every city that has that religion. And each city is getting that bonus! :eek:

Big booboo...

So, I need to check if the city has the shrine. And thus what I wrote in post #342.

EDIT: an example:
Every city that has Buddhism, gets the full Yields bonus for the Buddhist shrine.
Every city that has Hinduism, gets the full Yields bonus for the Hindu shrine.
And if a city has both Buddhism & Hinduism, then it gets the full bonus from both religions.
Not good...
 
Try this

Code:
	if (isHasReligion(eReligion))
	{
		for (int iI = 0; iI < GC.getNumBuildingInfos(); iI++)
		{
			if (GC.getBuildingInfo(iI).getGlobalReligionYields() != NO_RELIGION && getNumActiveBuilding((BuildingTypes)iI) > 0)
			{
				iYield += getNumActiveBuilding((BuildingTypes)iI) * GC.getReligionInfo(eReligion).getGlobalReligionYield(eIndex) * GC.getGameINLINE().countReligionLevels(eReligion);
			}
		}
	}

It loops over all the buildings checking for shrines and also multiplies by the number of them to get the full yield amount.
 
Sorry EF, that didn't work either. I'm still getting that "2 arguments" error, and now other stuff too. Here's how things look now:

Code:
int CvCity::getGlobalReligionYieldByReligion(YieldTypes eIndex, ReligionTypes eReligion, BuildingTypes eBuilding) const
{
	int iYield;

	FAssertMsg(eIndex >= 0, "eIndex expected to be >= 0");
	FAssertMsg(eIndex < NUM_YIELD_TYPES, "eIndex expected to be < NUM_YIELD_TYPES");
	FAssertMsg(eReligion >= 0, "eReligion expected to be >= 0");
	FAssertMsg(eReligion < GC.getNumReligionInfos(), "GC.getNumReligionInfos expected to be >= 0");

	iYield = 0;

	if (isHasReligion(eReligion))
	{
		for (int iI = 0; iI < GC.getNumBuildingInfos(); iI++)
		{[COLOR="Red"]// the below line is #8329[/COLOR]
			if (GC.getBuildingInfo(iI).getGlobalReligionYields() != NO_RELIGION && getNumActiveBuilding((BuildingTypes)iI) > 0)
			{
				iYield += getNumActiveBuilding((BuildingTypes)iI) * GC.getReligionInfo(eReligion).getGlobalReligionYield(eIndex) * GC.getGameINLINE().countReligionLevels(eReligion);
			}
		}
	}
	return iYield;
}

void CvCity::updateGlobalReligionYield(YieldTypes eIndex)
{
	int iOldYield = getGlobalReligionYield(eIndex);
	int iNewYield = 0;

	for (int iI = 0; iI < GC.getNumReligionInfos(); iI++)
	{[COLOR="Red"]// the below line is #8401[/COLOR]
		iNewYield += getGlobalReligionYieldByReligion(eIndex, (ReligionTypes)iI);
	}

	if (iOldYield != iNewYield)
	{
		m_aiGlobalReligionYield[eIndex] = iNewYield;
		FAssert(getGlobalReligionYield(eIndex) >= 0);

		changeBaseYieldRate(eIndex, (iNewYield - iOldYield));
	}
}

and that gave me these errors:
CvCity.cpp(8329) : error C2664: 'CvBuildingInfo &CvGlobals::getBuildingInfo(BuildingTypes)' : cannot convert parameter 1 from 'int' to 'BuildingTypes'
Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast)
CvCity.cpp(8329) : error C2228: left of '.getGlobalReligionYields' must have class/struct/union type
CvCity.cpp(8401) : error C2660: 'CvCity::getGlobalReligionYieldByReligion' : function does not take 2 arguments
 
well, this didn't work either:
Code:
bool CvCity::getGlobalReligionYieldbyShrine(BuildingTypes eBuilding) const
{
	bool bHasShrine;
	
	for (int iI = 0; iI < GC.getNumBuildingInfos(); iI++)
	{
		if GC.getBuildingInfo(iI).getGlobalReligionYields() != NO_RELIGION
		{	
			if getNumActiveBuilding((BuildingTypes)iI) > 0)
			{
				bHasShrine = true;
			}
		}
		return bHasShrine;
	}
}

I get that same error C2664 as seen in the above post...
 
OK, I remembered that you had referred me to an existing bHasShrine earlier. It's listed down at the bottom of CvCity, and also CvPlayer & CvTeam. I think the one in CvCity will be fine, but I can't seem to call it. If I could, I think this damned thing would finally be working, but I can't call it. No matter what I do, I get an "error C2664" from the compiler, which is "unexpected identifier."

I've done everything I can think of, including just copy-&-pasting an exact copy of the bool CvCity::hasShrine(ReligionTypes eReligion) into my CvCity::getGlobalReligionYieldByReligion(). I always get that same error. It's driving me nuts! :wallbash:

And here I was thinking my forehead could start to heal...
 
For the errors you need to cast iI to a BuildingTypes

Code:
GC.getBuildingInfo([B][COLOR="Red"](BuildingTypes)[/COLOR][/B]iI)

and remove that extra eBuilding parameter you added to the function

Code:
int CvCity::getGlobalReligionYieldByReligion(YieldTypes eIndex, ReligionTypes eReligion[B][COLOR="Red"][s], BuildingTypes eBuilding[/s][/COLOR][/B]) const
 
Did you mean like this EF?
Code:
int CvCity::getGlobalReligionYieldByReligion(YieldTypes eIndex, ReligionTypes eReligion) const
{
	int iYield;
	
	FAssertMsg(eIndex >= 0, "eIndex expected to be >= 0");
	FAssertMsg(eIndex < NUM_YIELD_TYPES, "eIndex expected to be < NUM_YIELD_TYPES");
	FAssertMsg(eReligion >= 0, "eReligion expected to be >= 0");
	FAssertMsg(eReligion < GC.getNumReligionInfos(), "GC.getNumReligionInfos expected to be >= 0");

	if (isHasReligion(eReligion))
	{[COLOR="Red"]// The below lone is #8326[/COLOR]
		for (int iI = 0; iI < GC.getNumBuildingInfos(BuildingTypes); iI++)
		{[COLOR="Red"]// The below lone is #8328[/COLOR]
		if (GC.getBuildingInfo(iI).getGlobalReligionYields() != NO_RELIGION && getNumActiveBuilding((BuildingTypes)iI) > 0)
		{
			iYield += GC.getReligionInfo(eReligion).getGlobalReligionYield(eIndex) * GC.getGameINLINE().countReligionLevels(eReligion);
		}
		}}
	return iYield;
}

Because the above gave me this error:
CvCity.cpp(8326) : error C2275: 'BuildingTypes' : illegal use of this type as an expression
c:\Documents and Settings\Richard Langlois\Desktop\Civ IV Mods\CvGameCoreDLL\CvEnums.h(1098) : see declaration of 'BuildingTypes'
CvCity.cpp(8328) : error C2664: 'CvBuildingInfo &CvGlobals::getBuildingInfo(BuildingTypes)' : cannot convert parameter 1 from 'int' to 'BuildingTypes'
Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast)
CvCity.cpp(8328) : error C2228: left of '.getGlobalReligionYields' must have class/struct/union type
Thanks...
 
You made the second change I posted, but you skipped the first which should be made on line 8328.
 
Sorry EF, are you referring to your post #344? Using it and your suggestion in post #348 results in the below:
Code:
int CvCity::getGlobalReligionYieldByReligion(YieldTypes eIndex, ReligionTypes eReligion) const
{
	int iYield;
	
	FAssertMsg(eIndex >= 0, "eIndex expected to be >= 0");
	FAssertMsg(eIndex < NUM_YIELD_TYPES, "eIndex expected to be < NUM_YIELD_TYPES");
	FAssertMsg(eReligion >= 0, "eReligion expected to be >= 0");
	FAssertMsg(eReligion < GC.getNumReligionInfos(), "GC.getNumReligionInfos expected to be >= 0");

	iYield = 0;

	if (isHasReligion(eReligion))
	{
		for (int iI = 0; iI < GC.getNumBuildingInfos(BuildingTypes); iI++)
		{
		if (GC.getBuildingInfo(iI).getGlobalReligionYields() != NO_RELIGION && getNumActiveBuilding((BuildingTypes)iI) > 0)
		{
			iYield += getNumActiveBuilding((BuildingTypes)iI) * GC.getReligionInfo(eReligion).getGlobalReligionYield(eIndex) * GC.getGameINLINE().countReligionLevels(eReligion);
			}
		}
	}
	return iYield;
}

Which I'm afraid doesn't work. I get the following:
CvCity.cpp(8326) : error C2275: 'BuildingTypes' : illegal use of this type as an expression
c:\Documents and Settings\Richard Langlois\Desktop\Civ IV Mods\CvGameCoreDLL\CvEnums.h(1098) : see declaration of 'BuildingTypes'
CvCity.cpp(8328) : error C2664: 'CvBuildingInfo &CvGlobals::getBuildingInfo(BuildingTypes)' : cannot convert parameter 1 from 'int' to 'BuildingTypes'
Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast)
CvCity.cpp(8328) : error C2228: left of '.getGlobalReligionYields' must have class/struct/union type

Sorry...

I'm sure everything would work if I could just figure out how to call that dratted bHasShrine boolean... ergh....
 
No, the first change in my post 348 says to add "(BuildingTypes)" to line 8328 to cast the iI passed to getBuildingInfo() to the right type.

Code:
if (GC.getBuildingInfo([B][COLOR="Red"](BuildingTypes)[/COLOR][/B]iI).getGlobalReligionYields() != NO_RELIGION && getNumActiveBuilding((BuildingTypes)iI) > 0)
 
OK, fixed that, thanks. The code now looks like this:
Code:
int CvCity::getGlobalReligionYieldByReligion(YieldTypes eIndex, ReligionTypes eReligion) const
{
	int iYield;
	
	FAssertMsg(eIndex >= 0, "eIndex expected to be >= 0");
	FAssertMsg(eIndex < NUM_YIELD_TYPES, "eIndex expected to be < NUM_YIELD_TYPES");
	FAssertMsg(eReligion >= 0, "eReligion expected to be >= 0");
	FAssertMsg(eReligion < GC.getNumReligionInfos(), "GC.getNumReligionInfos expected to be >= 0");

	iYield = 0;

	if (isHasReligion(eReligion))
	{
		for (int iI = 0; iI < GC.getNumBuildingInfos(BuildingTypes); iI++)
		{
		if (GC.getBuildingInfo((BuildingTypes)iI).getGlobalReligionYields() != NO_RELIGION && getNumActiveBuilding((BuildingTypes)iI) > 0)
		{
			iYield += getNumActiveBuilding((BuildingTypes)iI) * GC.getReligionInfo(eReligion).getGlobalReligionYield(eIndex) * GC.getGameINLINE().countReligionLevels(eReligion);
			}
		}
	}
	return iYield;
}
And gives this error instead:
CvCity.cpp(8328) : error C2275: 'BuildingTypes' : illegal use of this type as an expression
At least it's a different error. That's progress, right?


EDIT:
Which I just fixed with this:
Code:
for (int iI = 0; iI < GC.getNumBuildingInfos(); iI++)
Compiling now. Fingers crossed!!
 
Have you tried adding breakpoints and using a debug DLL to verify that it's calling the functions you expect?
 
If you followed Refar's guide originally, you should be able to simply change "Final_Release" at the top to "Debug" and build. You can set up Visual Studio to attach to the game automatically or you can do so after launching BTS with Debug : Attach to Process... in VS.

Make sure you run BTS in windowed (non full screen) mode!

You set breakpoints by clicking in the left margin of source files. You'll see a red circle where you have set one.

And yes, I believe there's a guide on setting up and using the debugger.
 
OK, the Debug mode seems to be working fine. I definately have a broken line, this one:
Code:
if (GC.getBuildingInfo((BuildingTypes)iI).getGlobalReligionYields() != NO_RELIGION && getNumActiveBuilding((BuildingTypes)iI) > 0)

I started a game, founded a city, and used WB to gift a Buddhist missionary to myself. When I spread the religion, the game processes through each of my added functions, and gets to int CvCity::getGlobalReligionYieldByReligion(YieldTypes eIndex, ReligionTypes eReligion) const. At that point, it starts going through the function over and over, each time for YIELD_FOOD, once for each religion. That seems right. It should go through it a total of 21 times (3 yields times 7 religions). Thing is, when it gets to religion 4 (Buddhism), the game gets stuck on the above line. I've hit F5 a few dozen times, it will not progress past that line. So, on the first pass through the Yields array, as soon as it gets to the religion that's being spread, we crash.

What's weird is, this doesn't cause a CTD in a normal Final_Release game. I would think that getting stuck on one line like this would break the game, but it appears to run fine.

I don't know how to troubleshoot this. It's completely unexpected to me...

Here's where I put my breakpoints:

Code:
[COLOR="Red"][B]*[/B][/COLOR]int CvCity::getGlobalReligionYield(YieldTypes eIndex) const												 
{
	FAssertMsg(eIndex >= 0, "eIndex expected to be >= 0");
	FAssertMsg(eIndex < NUM_YIELD_TYPES, "eIndex expected to be < NUM_YIELD_TYPES");
	return m_aiGlobalReligionYield[eIndex];
}


[COLOR="Red"][B]*[/B][/COLOR]int CvCity::getGlobalReligionYieldByReligion(YieldTypes eIndex, ReligionTypes eReligion) const
{
	int iYield;
	
	FAssertMsg(eIndex >= 0, "eIndex expected to be >= 0");
	FAssertMsg(eIndex < NUM_YIELD_TYPES, "eIndex expected to be < NUM_YIELD_TYPES");
	FAssertMsg(eReligion >= 0, "eReligion expected to be >= 0");
	FAssertMsg(eReligion < GC.getNumReligionInfos(), "GC.getNumReligionInfos expected to be >= 0");

	iYield = 0;

[COLOR="Red"][B]*[/B][/COLOR]	if (isHasReligion(eReligion))
	{
[COLOR="Red"][B]*[/B][/COLOR]		for (int iI = 0; iI < GC.getNumBuildingInfos(); iI++)
		{
[COLOR="Red"][B]*[/B][/COLOR]		if (GC.getBuildingInfo((BuildingTypes)iI).getGlobalReligionYields() != NO_RELIGION && getNumActiveBuilding((BuildingTypes)iI) > 0)
		{
			iYield += getNumActiveBuilding((BuildingTypes)iI) * GC.getReligionInfo(eReligion).getGlobalReligionYield(eIndex) * GC.getGameINLINE().countReligionLevels(eReligion);
			}
		}
	}
[COLOR="Red"][B]*[/B][/COLOR]	return iYield;
}


[COLOR="Red"][B]*[/B][/COLOR]void CvCity::updateGlobalReligionYield(YieldTypes eIndex)
{
	int iOldYield = getGlobalReligionYield(eIndex);
	int iNewYield = 0;

	for (int iI = 0; iI < GC.getNumReligionInfos(); iI++)
	{
		iNewYield += getGlobalReligionYieldByReligion(eIndex, (ReligionTypes)iI);
	}

	if (iOldYield != iNewYield)
	{
		m_aiGlobalReligionYield[eIndex] = iNewYield;
		FAssert(getGlobalReligionYield(eIndex) >= 0);

		changeBaseYieldRate(eIndex, (iNewYield - iOldYield));
	}
}


void CvCity::updateGlobalReligionYield()
[COLOR="Red"][B]*[/B][/COLOR]{
	int iI;

	for (iI = 0; iI < NUM_YIELD_TYPES; iI++)
	{
		updateGlobalReligionYield((YieldTypes)iI);
	}
}
 
Keep in mind that the Debug build has the asserts activated while the Final_Release does not. It's possible that one of those function calls in the if() expression is triggering an assert, but that should popup a message immediately, and you should be able to see the line where it failed.

But you say it's looping over and over on that line? That should really be impossible. Are you stepping over or into it? Stepping over would execute the if() and its entire {} block if true. Stepping info would jump into CvBuildingInfo::getGlobalReligionYields() and each part of the if() expression.

Can you please post the latest CvBuildingInfo::getGlobalReligionYields() function? You didn't modify CvGame::countReligionLevels() did you?
 
Back
Top Bottom