Adding new Resource Yields to Future Techs

I should have mentioned far earlier, but you should wear padded gloves, or a forehead protector, when writing code. The reason is, that many times you will wind up slapping yourself in the forehead, or banging your head against the wall, when you realize what went wrong.



CvCity is calling for:

getFutureProduction

CvPlayer has a function for:

getExtraFutureProduction


Thus the error.
 
Thanks for the warning! I did kind of know from my earlier attempts! :lol:

Unfortunately, that didn't work either...

Changed lines 5484-5486 of CvTeam.cpp to show
Code:
GET_PLAYER((PlayerTypes)iI).changeExtraFutureFood(GC.getTechInfo(eTech).getFutureFood() * iChange);
GET_PLAYER((PlayerTypes)iI).changeExtraFutureProduction(GC.getTechInfo(eTech).getFutureProduction() * iChange);
GET_PLAYER((PlayerTypes)iI).changeExtraFutureCommerce(GC.getTechInfo(eTech).getFutureCommerce() * iChange);
but it made no difference. Same error from CvCity.cpp that "getFuture__ is not a member of CvPlayerAI".
 
Not sure what you are saying that you did with CvTeam, but what I am saying is that in CvCity you need to change:

Code:
int CvCity::getYieldRate(YieldTypes eIndex) const
{
    int iFutureYield = 0;
    if (eIndex == YIELD_PRODUCTION)
        iFutureYield = GET_PLAYER(getOwner()).getFutureProduction();
    else if (eIndex == YIELD_COMMERCE)
        iFutureYield = GET_PLAYER(getOwner()).getFutureCommerce();
    else if (eIndex == YIELD_FOOD)
        iFutureYield = GET_PLAYER(getOwner()).getFutureFood();
	return (((getBaseYieldRate(eIndex) + iFutureYield) * getBaseYieldRateModifier(eIndex)) / 100);
}

to

Code:
int CvCity::getYieldRate(YieldTypes eIndex) const
{
    int iFutureYield = 0;
    if (eIndex == YIELD_PRODUCTION)
        iFutureYield = GET_PLAYER(getOwner()).get[COLOR="Orange"]Extra[/COLOR]FutureProduction();
    else if (eIndex == YIELD_COMMERCE)
        iFutureYield = GET_PLAYER(getOwner()).get[COLOR="Orange"]Extra[/COLOR]FutureCommerce();
    else if (eIndex == YIELD_FOOD)
        iFutureYield = GET_PLAYER(getOwner()).get[COLOR="Orange"]Extra[/COLOR]FutureFood();
	return (((getBaseYieldRate(eIndex) + iFutureYield) * getBaseYieldRateModifier(eIndex)) / 100);
}

Then it will work, because that is what you named your functions in CvPlayer
 
Loading map or loading the entire game?

And generall, I troubleshoot by removing everything I just recently added and then bringing it back in one step at a time (first I try to remove only the non *.h changes so the compile is quicker)
 
Loading the whole game. After the init finishes going through everything, it manages to get Baba Yetu started, and I promptly get a CTD, before the main menu screen is able to load.

I'll start trying to take out bits of each .cpp file and see what happens...

Here's an updated set once again:
File removed. Please see post #52


-----------------------------------------------------


EDIT, 01/01/09, 21:20:
I don't know why, but I can't even get the game to load with the succesful set of first changes, the ones that just showed the text in the 'Pedia... I have no idea what I've screwed up, but I've dogged it good... Starting from scratch now, will try to get the text showing again, keep a clean copy of that aside this time. -sigh-
 
Try compiling your DLL with asserts turned on. I don't know specifically how to do this with Civ4, but basically you need to find a #ifdef that contains the name of a compilation variable that you can set to 1, something like ASSERTS or DEBUG. It will be checked wherever it #define's the FASSERT and related macros.

This way, instead of doing a CTD, you'll get a dialog box saying some constraint was violated (index out of bounds, illegal value, etc) along with where specifically it's happening.
 
I don't have specifics because a) I don't have the code here and more importantly b) I don't have your compiler setup. Look in the menus/online-help for information on "defining variables during compilation".

Next, look for the header (.h) file that has something like this:

Code:
#ifdef ASSERTS
#define FASSERT(COND) if (!(COND)) { ... }
#endif

Finally, define that variable "ASSERTS" to be 1 in the compiler.
 
OK, I finally got things back to normal. Thanks for the pointer EF. Turns out the problem was, that for some reason, the game will not accept a copy of CIV4ArtDefines_Interface in the Mod folder. I also had some changes to CvTechChooser.py left over from trying to get the widgets to work, which I have completely shelved for now.

So, now the game loads again. And starts a new game. No Python difficulties that I can see. The Future Techs are listed, and in both the Science Advisor, and the 'Pedia, they show the correct bonuses on the popup boxes.

I have added in changes to CvPlayer.h, CvPlayer.cpp, & CvCity.cpp, shown here:
Spoiler CvPlayer.h :
Code:
	int getExtraHappiness() const;																																						// Exposed to Python
	void changeExtraHappiness(int iChange);

	////////////////////////////////////////////////////////////////////////
	// RichMod Start - Future Bonuses
	int getFutureFood() const;																																						// Exposed to Python
	void changeFutureFood(int iChange);

	int getFutureProduction() const;																																						// Exposed to Python
	void changeFutureProduction(int iChange);

	int getFutureCommerce() const;																																						// Exposed to Python
	void changeFutureCommerce(int iChange);
	// RichMod End - Future Bonuses
	////////////////////////////////////////////////////////////////////////

	int getBuildingHappiness() const;																																					// Exposed to Python
	void changeBuildingHappiness(int iChange);

[COLOR="Red"]@@@@@@@@@@@@@@@
@@@  BREAK  @@@
@@@@@@@@@@@@@@@[/COLOR]

		int m_iExtraHappiness;
	/////////////////////////////////////////////////////////////////////////
	// RichMod Start - Future Bonuses
	int m_iFutureFood;
	int m_iFutureProduction;
	int m_iFutureCommerce;
	// RichMod End - Future Bonuses
	/////////////////////////////////////////////////////////////////////////
	int m_iBuildingHappiness;
Spoiler CvPlayer.cpp :
Code:
	m_iExtraHappiness = 0;
	/////////////////////////////////////////////////////////////////////////
	// RichMod Start - Future Bonuses
	m_iFutureFood = 0;
	m_iFutureProduction = 0;
	m_iFutureCommerce = 0;
	// RichMod End - Future Bonuses
	/////////////////////////////////////////////////////////////////////////
	m_iBuildingHappiness = 0;


[COLOR="Red"]@@@@@@@@@@@@@@@
@@@  BREAK  @@@
@@@@@@@@@@@@@@@[/COLOR]


void CvPlayer::changeExtraHappiness(int iChange)
{
	if (iChange != 0)
	{
		m_iExtraHappiness = (m_iExtraHappiness + iChange);

		AI_makeAssignWorkDirty();
	}
}

////////////////////////////////////////////////////////////////////////////////////
// RichMod Start - Future Bonuses
int CvPlayer::getFutureFood() const
{
	return m_iFutureFood;
}


void CvPlayer::changeFutureFood(int iChange)
{
	if (iChange != 0)
{
		m_iFutureFood = (m_iFutureFood + iChange);

		AI_makeAssignWorkDirty();
	}
}

int CvPlayer::getFutureProduction() const
{
	return m_iFutureProduction;
}


void CvPlayer::changeFutureProduction(int iChange)
{
	if (iChange != 0)
	{
		m_iFutureProduction = (m_iFutureProduction + iChange);

		AI_makeAssignWorkDirty();
	}
}

int CvPlayer::getFutureCommerce() const
{
	return m_iFutureCommerce;
}


void CvPlayer::changeFutureCommerce(int iChange)
{
	if (iChange != 0)
	{
		m_iFutureCommerce = (m_iFutureCommerce + iChange);

		AI_makeAssignWorkDirty();
	}
}
// RichMod End - Future Bonuses
////////////////////////////////////////////////////////////////////////////////////

int CvPlayer::getBuildingHappiness() const


[COLOR="Red"]@@@@@@@@@@@@@@@
@@@  BREAK  @@@
@@@@@@@@@@@@@@@[/COLOR]


	pStream->Read(&m_iExtraHappiness);
	/////////////////////////////////////////////////////////////////////////
	// RichMod Start - Future Bonuses
	pStream->Read(&m_iFutureFood);
	pStream->Read(&m_iFutureProduction);
	pStream->Read(&m_iFutureCommerce);
	// RichMod End - Future Bonuses
	/////////////////////////////////////////////////////////////////////////
	pStream->Read(&m_iBuildingHappiness);


[COLOR="Red"]@@@@@@@@@@@@@@@
@@@  BREAK  @@@
@@@@@@@@@@@@@@@[/COLOR]


	pStream->Write(m_iExtraHappiness);
	/////////////////////////////////////////////////////////////////////////
	// RichMod Start - Future Bonuses
	pStream->Write(m_iFutureFood);
	pStream->Write(m_iFutureProduction);
	pStream->Write(m_iFutureCommerce);
	// RichMod End - Future Bonuses
	/////////////////////////////////////////////////////////////////////////
	pStream->Write(m_iBuildingHappiness);
Spoiler CvCity.cpp :
Code:
////////////////////////////////////////////////////////////////////////////
// RichMod Start - Future Bonuses
// 
// Original Code:
// 
// int CvCity::getYieldRate(YieldTypes eIndex) const
// {
//  	return ((getBaseYieldRate(eIndex) * getBaseYieldRateModifier(eIndex)) / 100);
// }
// 
// New Code:
int CvCity::getYieldRate(YieldTypes eIndex) const
{
	int iFutureYield = 0;
	if (eIndex == YIELD_FOOD)
		iFutureYield = GET_PLAYER(getOwner()).getFutureFood();
	else if (eIndex == YIELD_PRODUCTION)
		iFutureYield = GET_PLAYER(getOwner()).getFutureProduction();
	else if (eIndex == YIELD_COMMERCE)
		iFutureYield = GET_PLAYER(getOwner()).getFutureCommerce();
	return (((getBaseYieldRate(eIndex) + iFutureYield) * getBaseYieldRateModifier(eIndex)) / 100);
}
// RichMod End - Future Bonuses
////////////////////////////////////////////////////////////////////////////////////
But it doesn't work. The program loads fine, and I can start a new game, and all the previously add text-work shows up still. But the Future Techs have no effect.

For the lines in CvCity, I have tried both GET_PLAYER(getOwner())., and GET_PLAYER(getOwnerINLINE()).. Neither worked. Thanks guys.
 
Can you post your latest CvTeam.cpp changes? The RAR you posted has changeExtraFutureXXX() calls, but those don't match the latest CvPlayer functions. All of the code you posted immediately above this post looks good.

You need to find how logging is done in the SDK (writing log messages) and add logging code to your functions to ensure that a) the effects are being added to the player and b) the player's values are used in the city.
 
Changes have been removed from CvTeam. They were causing problems, and based on what xienwolf has said so far, I should only need listings in either CvPlayer or CvTeam. Did I mis-understand? :confused:

I'll repost the changes here, and once again delete the old file. And look up how to enable logging. Thanks!

View attachment Future Bonus.rar
 
CvPlayer should keep track of its future XXXs from the techs, but CvTeam must call changeFutureXXX() when each future tech is researched. Are you calling those change functions from somewhere else?
 
Umm... Please remember I'm like the Sorcerer's Apprentice here, muddling around in things I don't really understand.

I think I have Change functions for the FutureYields, found at lines 494-505 of CvPlayer.h, and lines 8673-8723 of CvPlayer.cpp. I will try again having functions specified in CvTeam.cpp as well, and see what happens. The place I had previously identified in CvTeam for insertion is lines 5473-5486:

Spoiler CvTeam.cpp locale for inserting FutureYields :
Code:
	for (iI = 0; iI < MAX_PLAYERS; iI++)
	{
		if (GET_PLAYER((PlayerTypes)iI).getTeam() == getID())
		{
			GET_PLAYER((PlayerTypes)iI).changeFeatureProductionModifier(GC.getTechInfo(eTech).getFeatureProductionModifier() * iChange);
			GET_PLAYER((PlayerTypes)iI).changeWorkerSpeedModifier(GC.getTechInfo(eTech).getWorkerSpeedModifier() * iChange);
			GET_PLAYER((PlayerTypes)iI).changeTradeRoutes(GC.getTechInfo(eTech).getTradeRoutes() * iChange);
			GET_PLAYER((PlayerTypes)iI).changeExtraHealth(GC.getTechInfo(eTech).getHealth() * iChange);
			GET_PLAYER((PlayerTypes)iI).changeExtraHappiness(GC.getTechInfo(eTech).getHappiness() * iChange);
[COLOR="DarkOrange"]			////////////////////////////////////////////////////////////////////////////
			// RichMod Start - Future Bonuses
			GET_PLAYER((PlayerTypes)iI).changeFutureFood(GC.getTechInfo(eTech).getFutureFood() * iChange);
			GET_PLAYER((PlayerTypes)iI).changeFutureProduction(GC.getTechInfo(eTech).getFutureProduction() * iChange);
			GET_PLAYER((PlayerTypes)iI).changeFutureCommerce(GC.getTechInfo(eTech).getFutureCommerce() * iChange);
			// RichMod End - Future Bonuses
			////////////////////////////////////////////////////////////////////////////[/COLOR]
			GET_PLAYER((PlayerTypes)iI).changeAssets(GC.getTechInfo(eTech).getAssetValue() * iChange);
			GET_PLAYER((PlayerTypes)iI).changePower(GC.getTechInfo(eTech).getPowerValue() * iChange);
			GET_PLAYER((PlayerTypes)iI).changeTechScore(getTechScore(eTech) * iChange);
		}
	}
Look right?
 
AHA!!!! Limited success!!! Thank-you EF, you were bang-on, I need functions in CvTeam as well as CvPlayer! :clap: :worship: :woohoo:

But, as I said, limited. FutureFood & Future Commerce work like charms. FutureProduction unfortunately, does squat. Ideas?

And of course, nothing's showing anywhere, but we can get to that later.
 
No worries if you're not understanding all this. That's the fun of learning. CvPlayer has the functions that do something when told to do it, but it's CvTeam that calls those functions to actually tell the player when to do it. In this case, that happens when the team acquires a new technology.

All of the posted code looks fine to me, but it never hurts to double-check that you have everything right. Make sure the XML for the tech that gives future production is correct.
 
Thanks for the reassurance. What I appreciate most of all is you guys' continued patience with me! :D

I went over all the code twice. Everything is spelled the same, no silly typos anywhere. That includes the XML. I tested the tag by using it for the two other Future techs, and it's not the Future Production tech itself, but rather the FutureProduction tag. I don't know why, because everything is spelled correctly, everywhere.

So, back to figuring out how to turn on logging, then I can get a better idea (I hope) of what is and isn't happening...
 
It looks like you can define _DEBUG to be 1 to get asserts enabled. If that doesn't work, try setting FASSERT_ENABLE to 1. This is in FAssert.h.

Then to create an assertion:

Code:
FAssertMsg([COLOR="Green"][I]<boolean expression>[/I][/COLOR], [COLOR="SandyBrown"][I]"<failure message>"[/I][/COLOR]);

These are less useful for what you want now as you don't want a CTD yet. You want to see what values are stored in the CvPlayer.

For that, here's an example of using logging:

Code:
if (GC.getLogging())    // logging turned on in INI I think
{
	if (gDLL->getChtLvl() > 0)    // chat level? I have no idea
	{
		TCHAR szOut[1024];
		sprintf(szOut, "Player %d City %d built at %d:%d\n", eOwner, iID, iX, iY);
		gDLL->messageControlLog(szOut);
	}
}
 
Use this in CvPlayer.cpp

Code:
void CvPlayer::changeFutureProduction(int iChange)
{
	if (iChange != 0)
	{
		m_iFutureProduction = (m_iFutureProduction + iChange);
		if (GC.getLogging())
		{
			TCHAR szOut[1024];
			sprintf(szOut, "New future production: %d\n", m_iFutureProduction);
			gDLL->messageControlLog(szOut);
		}

		AI_makeAssignWorkDirty();
	}
}

and this in CvCity.cpp:

Code:
int CvCity::getYieldRate(YieldTypes eIndex) const
{
	int iFutureYield = 0;
	if (eIndex == YIELD_FOOD)
		iFutureYield = GET_PLAYER(getOwner()).getFutureFood();
	else if (eIndex == YIELD_PRODUCTION)
		iFutureYield = GET_PLAYER(getOwner()).getFutureProduction();
	else if (eIndex == YIELD_COMMERCE)
		iFutureYield = GET_PLAYER(getOwner()).getFutureCommerce();
	if (iFutureYield > 0 && GC.getLogging())
	{
		TCHAR szOut[1024];
		sprintf(szOut, "Yield %d future change: %d\n", eIndex, iFutureYield);
		gDLL->messageControlLog(szOut);
	}
	return (((getBaseYieldRate(eIndex) + iFutureYield) * getBaseYieldRateModifier(eIndex)) / 100);
}
 
Top Bottom