Adding new Resource Yields to Future Techs

Like:

Code:
for (iI = 0; iI <NUM_YIELD_TYPES; iI++)
     {
          changeReligionInfluence(((ReligionTypes)iI), (GC.getBuildingInfo(eBuilding).getReligionChange(iI) * iChange));
     }
I think that might be where the game is counting how much the existing Gold bonus Shrines give should be. I don't see anything else referencing Religion. Although I do see a line that looks like it adds up the Yield bonus for the city. But I see nothing about ReligionCommerce...
 
It occurred to me:

CvPlayer handles all things related directly to the individual siiting in the chair.
CVCity handles all things for each & every city.
But, GlobalReligionCommerce (and so by default, my GlobalReligionYield as well) relies on the total count of a religion's spread throughout the world. Which couldn't be handled by either of those files, right? And I don't think it would be in CvTeam either. But I'm don't where where to look to confirm this hypothesis.

What do you think? Does this sound right, or am I way off?
 
It occurred to me:

CvPlayer handles all things related directly to the individual siiting in the chair.

No, every AI is counted as a player too. CvPlayer is used for AI's as well. CvPlayerAI is used for the AI to calculate the decisions, for their empire, but CvPlayer calculates the effects of the decisions.
 
CvPlayer is where it matters, as it applies to ALL cities that the player owns. Or CvCity is where it matters as it applies only to that one city.

When the CvPlayer or CvCity goes to use the value, then they will check CvGame, which they both have access to, and find out the proper count of all religions (or they will do a loop over all cities in the world to find the count if it is not normally tracked)
 
To add to what xienwolf said, the city holding the Shrine gets the :commerce:, so it must hold the value it gets every turn. Either the game or the player who owns the city should adjust that value as the religion spreads.
 
Trying to mimic void CvCity::setCorporationYield(YieldTypes, but I was also looking at CvCity::getCorporationYieldByCorporation.

In CvCity::getCorporationYieldByCorporation, the game is checking and updating the value of ChangeBaseYieldRate for each new bonus the city has obtained access to. There's also CvCity::getReligionCommerceByReligion, where the game updates the Commerce values for a city, checking if the city has become the Holy City (+4 :culture:), or if the religion is now the State Religion (+1 :culture:).

So, with those two things in mind, I try the below piece of code:
Code:
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];
}

void CvCity::setGlobalReligionYield(YieldTypes eIndex, int iNewValue, ReligionTypes)
{
	int iOldValue;

	FAssertMsg(eIndex >= 0, "eIndex expected to be >= 0");
	FAssertMsg(eIndex < NUM_YIELD_TYPES, "eIndex expected to be < NUM_YIELD_TYPES");

	iOldValue = getGlobalReligionYield(eIndex);

	if (iOldValue != iNewValue)
	{
		m_aiGlobalReligionYield[eIndex] * GC.getGameINLINE().countReligionLevels(ReligionTypes)= iNewValue;
		FAssert(getGlobalReligionYield(eIndex) >= 0);   [COLOR="Red"]/** This is line 8417 **/[/COLOR]

		changeBaseYieldRate(eIndex, (iNewValue - iOldValue));
	}
}
which doesn't work of course. My idea being, this should find the value of what the Shrine gives for the Yield being checked for (m_aiGlobalReligionYield) and then supply that times the number of cities with the religion (countReligionLevels). Unfortunately, I get this error:

CvCity.cpp(8417) : error C2275: 'ReligionTypes' : illegal use of this type as an expression

I did remember to update the header file appropriately, and started a "Rebuild Solution". Any suggestions?
 
In your function declaration:

void CvCity::setGlobalReligionYield(YieldTypes eIndex, int iNewValue, ReligionTypes)


You need to state what the variable name is for the ReligionTypes object being passed in (at the end).

Then in line 8416, you use ReligionTypes when you should be using a variable name, so make sure whatever name you choose you place it there. This is the ACTUAL error you get, not sure why it is passing you the next line number, but sometimes it does that.
 
That'd be correct. And not just changing to ReligionTypes eReligion) in the header, but also on the first line of the function. Actually I don't think the header cares if you assign a name or not, but the top of the function in the CPP absolutely requires it.
 
Actually I don't think the header cares if you assign a name or not, but the top of the function in the CPP absolutely requires it.

That's correct. The compiler ignores parameter names in function declarations, but it's a good idea to specify them and use the same names as the definition (where the { ... } function body goes).
 
Thanks guys. Code changed thusly (I did the header too, might as well):

Code:
void CvCity::setGlobalReligionYield(YieldTypes eIndex, int iNewValue, ReligionTypes eReligion)
{
	int iOldValue;

	FAssertMsg(eIndex >= 0, "eIndex expected to be >= 0");
	FAssertMsg(eIndex < NUM_YIELD_TYPES, "eIndex expected to be < NUM_YIELD_TYPES");

	iOldValue = getGlobalReligionYield(eIndex);

	if (iOldValue != iNewValue)
	{
		m_aiGlobalReligionYield[eIndex] * GC.getGameINLINE().countReligionLevels(eReligion) = iNewValue;  [COLOR="Red"]/** This is line 8417 **/[/COLOR]
		FAssert(getGlobalReligionYield(eIndex) >= 0);

		changeBaseYieldRate(eIndex, (iNewValue - iOldValue));
	}
}

And now I get this error:

CvCity.cpp(8417) : error C2106: '=' : left operand must be l-value

Gonna try to look that up. Oh, and the line number was wrong before because I'm a twerp and wrote the "This is 8417" in the wrong place... :crazyeye:
 
And lvalue is short for "left value" which only means that you can assign a value to it. You cannot assign a value to 2 because it's just a number, and you cannot change what value 2 has. In the above code you are assigning iNewValue to the result of multiplying two numbers together which isn't allowed.

What exactly in English are you trying to do here? If you just want to change the array element to the new value, use

Code:
m_aiGlobalReligionYield[eIndex] = iNewValue;

But then I would wonder why this function takes a ReligionTypes called eReligion but never uses it. What is the array supposed to hold? And where is this function used, i.e. what function(s) call it?
 
The idea was to use this function to add the Yield value from the Shrines to the Yield output of the city.

In CvCity::setCorporationYield(YieldTypes eIndex, int iNewValue), the Yield value of a corporation is added to changeBaseYieldRate, which is the same variable I used to get the TechYields working. I figured, "OK, why go through the trouble of trying to find where CvCity adds up all the different Yield values for output, when I already know the changeBaseYieldRate will do the trick?"

So, I built CvCity::setGlobalReligionYield in an (failed ;)) attempt to do just that. So, since the Yield output of a Shrine is dependant upon the value from the array listed in the XML times the number of cities with the religion for that Shrine, I tried what we see in line 8417. Clearly that don't work :D.

Is it possible that perhaps I should build a separate function to hold the value of the Religion count, and then call that function in the multiplication line? Or am I on Mars here?
 
The problem is that CvCity tracks commerce different from how it tracks yields. You are calling changeBaseYieldRate() correctly by passing in the difference between the old and new values, but you need to calculate the new value outside this function and pass it in.

First you need to find where to call this function. Is there a function that gets called every time a religion is added to / removed from a city? IIRC I couldn't find such a function when I looked back when you started this, but it's been too long to remember. This may be one of the reasons that yields and commerce values are handled differently: commerce values fluctuate more often (every time you adjust the sliders) whereas yields change very rarely.
 
Looking at how the game re-calcs the normal Shrine Commerces, all I really need to do is make sure that my function resets every time a religion spreads to another city. Under normal circumstances, they can't be removed, except by razing the city. I remember finding how that was done and thinking, "Oh. That's easy." So I just have to find it again.

So:
  1. Build a function designed to get the value of GC.getGameINLINE().countReligionLevels(eReligion).
  2. Build another function designed to be called when the game updates countReligionLevels, and instruct this second function to update (ie: call again) the first function
  3. make a third function that will call my CvCity::setGlobalReligionYield so that changeBaseYieldRate can get updated.

Sound right?

ps: should the first function call the third? I think that causes a loop, right?
 
If your GlobalReligionYield tag has been added to BuildingInfo or BuildingClassInfo, you really have no choice but to tell every city to update its yields when a religion's count changes.

I expect you'll be limiting the use of this tag to Shrines which means holy cities. In that case, whatever CvGame function that tracks the spread of religions can tell just the holy city for the religion in question to update its yields.

I don't know if this is clear or not: functions perform actions while fields (class variables such as m_aiGlobalReligionYields) hold data. When you say, "the game updates countReligionLevels," you're mixing the two a bit. It could be just your wording, but if you're thinking that countReligionLevels holds values that can be changed, you are mixing the concepts.

Think of functions as procedural instructions that you can follow and variables as buckets where you can save values to use later. You typically call functions to have them modify variables, but the functions themselves don't hold any data.

Back to the task at hand, I followed the calling chain back from CvCity::updateBuildingCommerce() which is responsible for summing up all of the commerce sources for each building. Every player's building commerce is recalculated by CvGame::updateBuildingCommerce() every turn. More importantly for your feature, it's also called by CvPlayer::changeHasReligionCount(). So every time a player's religion count is changed, every player is told to update the building commerce for every one of its cities.

You definitely don't want to rewrite all of the yield-handling code to work like commerce, so my recommendation is to create a new function in CvGame that you call from CvPlayer::changeHasReligionCount():

Code:
void CvGame::updateGlobalReligionYield(ReligionTypes eReligion)
    find holy city for eReligion
    city->updateGlobalReligionYield(eReligion)

It should find the holy city for the religion and call another new function with the same name but on CvCity.

Code:
void CvCity::updateGlobalReligionYield(ReligionTypes eReligion)
    if this city has the building that gains yields for eReligion
        int iCount = GC.getGameINLINE().countReligionSpread(eReligion);
        for each yield
            setGlobalReligionYield(eReligion, eYield, iNewValue)  // your function

You must change the array in CvCity to be an array of arrays so it can track the yields for each religion separately. You function needs to know the previous total for that religion and yield combination in order to apply the difference via changeBaseYieldRate().
 
You were multiplying on the wrong side of the equation:

m_aiGlobalReligionYield[eIndex] * GC.getGameINLINE().countReligionLevels(eReligion) = iNewValue; /** This is line 8417 **/


should be

m_aiGlobalReligionYield[eIndex] = GC.getGameINLINE().countReligionLevels(eReligion) * iNewValue; /** This is line 8417 **/

And you ought to actually calculate iNewValue before your IF statement anyway, so that comparison with iOldValue actually has some meaning.

so:

iOldValue = get___()
iNewValue = iNewValue * GC.getGameINLINE().countReligionLevels(eReligion)

if (iOldValue != iNewValue)



Though looking at the function you are using to count religions... Are you sure that gives you the number of cities with the religion, and not the percentage of world influence for the religion?
 
Thank-you xienwolf. I don't think your suggestion worked, but I was in a bit of a hurrry, so I need to double-check.

EF, how would I check if my building (or rather, more specifcally, the Shrine) is actually in the city? Could I just run a simple IF to check that the value of m_aiGlobalReligionYield is not zero?
 
No, it will start at zero and never get detected if you do that. The simplest to code method is to loop over all buildings looking for the one that provides global religion yields for the religion being checked. This function only gets called when a religion is added/removed to/from a city, so the minor performance hit is trivial. The other option is to add a boolean array to the city to track if it has the shrine for each religion and update it in processBuilding().
 
Back
Top Bottom