Adding new Resource Yields to Future Techs

You'll want to multiply your iValue by how many units of production/food/commerce the tech gives you. Just incase you use this field on a non-future tech someday and have it do something like +3 food with Refrigeration. Then the AI knows that +3 food is better than +1 food.
 
Glad you're feeling better.

But I'm having trouble figuring out how to call the amount of change from a given tech...

You already do: CvTechInfo::getYieldChange(i) returns the actual yield change: -4, +1, 0, etc. Just multiply the return value of the function by some factor. For example:

Code:
int iChange = GC.getTechInfo((TechTypes)iI).getYieldChange(YIELD_PRODUCTION);
if (iChange != 0)
{
	iValue += (iChange * getNumCities() * ((atWar) ? 50 : 15) * 5);
}
 
Well, "better" is a relative term. I still feel like freshly lain asphalt... But thanks for the well-wishes! ;)

How does this look?
Code:
if (GC.getTechInfo((TechTypes)iI).getYieldChange(YIELD_FOOD))
{
	int iChange = GC.getTechInfo((TechTypes)iI).getYieldChange(YIELD_FOOD)
	if (iChange != 0)
	{
		if (iPercentOfDomination < 75)
		{
			iValue += (iChange * getNumCities() * 200);
		}
		else
		{
			iValue += (iChange * getNumCities() * 80);
		}
	}
}

if (GC.getTechInfo((TechTypes)iI).getYieldChange(YIELD_PRODUCTION))
{
	int iChange = GC.getTechInfo((TechTypes)iI).getYieldChange(YIELD_PRODUCTION)
	if (iChange != 0)
	{
		iValue += (iChange * (getNumCities() + ((atWar) ? 50 : 15)) * 5);
	}
}

if (GC.getTechInfo((TechTypes)iI).getYieldChange(YIELD_COMMERCE))
{
	int iChange = GC.getTechInfo((TechTypes)iI).getYieldChange(YIELD_COMMERCE)
	if (iChange != 0)
	{
		iValue += (iChange * getNumCities() + ((bFinancialTrouble) ? 45 : 15) * 5);
	}
}

Thanks again!
 
That looks great (almost). The only thing I'd change is removing the 3 outermost if tests since you test the same thing (correctly) inside with (iChange != 0).

For example,

Code:
[s]if (GC.getTechInfo((TechTypes)iI).getYieldChange(YIELD_PRODUCTION))[/s]
[s]{[/s]
	int iChange = GC.getTechInfo((TechTypes)iI).getYieldChange(YIELD_PRODUCTION)
	if (iChange != 0)
	{
		iValue += (iChange * (getNumCities() + ((atWar) ? 50 : 15)) * 5);
	}
[s]}[/s]

You'll need to make sure you declare iChange just once, or you can change each like this:

Code:
if (GC.getTechInfo((TechTypes)iI).getYieldChange(YIELD_PRODUCTION) [B][COLOR="YellowGreen"]!= 0[/COLOR][/B])
{
	int iChange = GC.getTechInfo((TechTypes)iI).getYieldChange(YIELD_PRODUCTION)
	[s]if (iChange != 0)[/s]
	[s]{[/s]
		iValue += (iChange * (getNumCities() + ((atWar) ? 50 : 15)) * 5);
	[s]}[/s]
}

The first way is just easier to read, IMHO. If you go the second route, make sure you don't miss the "!= 0" I added to the first line or you'll ignore negative values (I think ...).
 
Thanks EF. Trying to compile, encountered this error twice:
CvPlayerAI.cpp|3356|error C2374: 'iChange' : redefinition; multiple initialization

So I got rid of the "int" calls at the start of the lines for Y_PROD & Y_COMM. The compiler accepts it, but I wanted to check if you thought that was valid.

Also, I realized I hadn't answered some of your questions from earlier. The Prod & Comm calculations do add first, but then multiply afterwards, so everything works out. Also, there is no "bAtWar" function, but you were right about atWar normally calling other arguments. Unfortunately, the way it's setup, it can't call zero args, so "atWar()" doesn't work either. All I need is a way for the AI to determine if it is in a war, and atWar seems to be designed to check whom the AI is warring with. Any ideas?
 
So I got rid of the "int" calls at the start of the lines for Y_PROD & Y_COMM. The compiler accepts it, but I wanted to check if you thought that was valid.

That's exactly the solution. The "int" before each iChange was telling the compiler what type of value the iChange variable held. You can only tell it once for each variable, thus the errors for the 2nd and 3rd times. Since you are using the values it holds immediately and don't need to hold onto them, it's okay to reuse the variable.

Here's a metaphor: when you own a single car, you call it "my car". This is just like iChange holding a single value. If you sell your car and buy a new one, you can continue calling the new car "my car" without any confusion. If instead you buy a second car and keep the original, you now need a new variable name, e.g. "my other car".

With iChange, you are using the sell-then-buy approach, and that works fine. If you wanted to make a calculation using both the :hammers: and :commerce: changes at the same time, you'd have to use new variable names for each, e.g. iProdChange and iCommChange.

All I need is a way for the AI to determine if it is in a war, and atWar seems to be designed to check whom the AI is warring with.

There's CvTeam::getAtWarCount(bool bIgnoreMinor) for getting the number of wars:

Code:
bool bAtWar = GET_TEAM(getTeam()).getAtWarCount(true) > 0;

With that at the top of your code area, you can use bAtWar in your code where you have "atWar".
 
Thanks again EF. That code snippet compiled fine.

It appears that I managed to do something wrong in RawYields.py though... Here's a screenie:

You'll note the lines that say "XML key" & "Modifiers (???%)". Well, the "XML key" is supposed to be my extra yields, but I can't get RawYields to recognize the TXT_KEY entry I made. And I've done something else wrong, because "Modifiers (???%)" is actually extra production provided by an Engineer Specialist...

Don't know what I screwed up either, everything looks right, I followed your instructions carefully... Here're the files: View attachment Array.rar.

Thanks EF...
 

Attachments

  • untitled.JPG
    untitled.JPG
    8.4 KB · Views: 129
Can you post your XML file so I can check the key? Also, in RawYields.py you call CyPlayer::getTechYieldChange(), but CyPlayer only has getYieldChange() [no Tech in name]. I would think that would cause a Python error and break when you tested it, so are these the actual up-to-date files you sent?

My guess is that the function being called is returning something that cannot be formatted as an int, and that's somehow goofing the modifier row. Although, your tech yield change shouldn't go into that field, so I don't know exactly what's wrong.

If you can package up the entire mod (built DLL and all files as you are testing it), I can run it here and see better what's going on. If you make it really easy for me to test it out, I'd be happy to give it a whirl.
 
Here's the XML:
Code:
<Text>
	<Tag>TXT_KEY_TECH_YIELD_CHANGES</Tag>
	<English>Extra (%d1)</English>
</Text>
And I used pPlayer.getTechYieldChange() cause that's what I named it in CyPlayerInterface1.cpp.

Unfortunately, I can't give you the whole Mod, all wrapped up in a bow, because everything is too intimately tied up in everything else, and BUG 3.5 too. I'd have to zip the entire thing, and I can't host a 100+ MB file here... I know there's a website where I could, but I can't remember what it is anymore... :cry:

Sorry EF, I know that's a pain... One thing I did try, removing the "Tech" from RawYields.py. But that causes a repeating failure in the Python log, and breaks the whole RawYields widget... It still looks to me like I properly called CyPlayer.cpp in CyPlayerInterface1.cpp. Maybe I missed a cross-referencing file somewhere?
 
Ah, I hadn't looked into the CyPlayerInterface1.cpp file. I assumed the Python function name would match the C++ function name. You are, of course, free to do it how you want. If it compiles and works in Python, you're good to go, and it does once you get the XML key right.

The part where the Engineer Specialist shows up as a modifier makes me think that some part of the code is using the wrong line item identifier (the all-caps variables defined at the top of the module). I'll take another look at the code you sent and see what I can find.
 
OK, I found the file-upload site, it's MediaFire. Here's a link to my complete mod, less some of the graphics changes. Remember, it's built into BUG 3.5, I haven't upgraded to 3.5.1 yet. Unfortunately, that means that there're files spread out over both a mod directory and CustomAssets, etc (you know the drill, I know you know the drill, why am I preaching...? :D). This is a complete and UTD copy of my Mod, everything included, changed Asset files too.

As for what I did wrong in RawYields.py, I'm at a loss. I've traced everything back, and triple-checked all my spellings. I'm sure the Python is working (kinda), because it is displaying the correct sum of Yield change. But, like the above screenie showed, including it is throwing Specialists off. I'm wondering if maybe it has something to do with the difference between how the Technologies & Specialist sections are encoding within RawYields...? I'm grasping at straws here... :crazyeye:

Sorry if I came off a little flip before, it wasn't intentional... :blush:

Thanks again for your help EF. I'm gonna start trying to take a stab at changing the Shrines to give Commerce instead of Gold for a few days, see how I do with that. Maybe I'll come back to this TXT_KEY problem and have a nice, convenient, little eureka moment. ... ... I can dream, right? ;)
 
Oh no, I didn't think you were being flippant, and nor was I. I made a bad assumption without checking, and I was poking fun to avert suspicion. :mischief: Seriously, it's all good.

I've downloaded your mod and will take a gander tomorrow possibly. I've got a busy weekend, so it may be next week that I get to peek. I think in the end it will probably be a simple fix. Clearly you have the C++ to Python bridge working as you pull the correct value out of the DLL. The rest is just getting RawYields.py and that XML key to behave.

You'll be happy to hear that I have working code in BUG's SVN so that you don't need CvModName.py anymore. It actually finds the mod folder correctly now without any modder intervention. I'll be adding a new property called something like Settings Folder Name where BUG will look for the INI files. You'll be free to name it anything you like, and neither BUG nor Civ4 will care.
 
You'll be happy to hear that I have working code in BUG's SVN so that you don't need CvModName.py anymore...
Cool!! Maybe I'll wait for 3.5.2 then, before upgrading... Hmm, maybe not, cause then I'll wait for whatever's neat from 3.5.3, etc... :p

I've downloaded your mod and will take a gander tomorrow possibly...
Don't rush on my account. I'll be out of commision this week I expect anyways (tooth coming out... :cry:), so I don't think my brain will be working well enough to follow up on anything anyways.

Seriously, it's all good.
Sorry :)rolleyes:) to be hyper-sensitive... I've crunched on toes before without any clue what I'd done, so sometimes I'm too vigilant with the apologies... We'll just both pretend I never said anything! :mischief: :D

I'm gonna start trying to take a stab at changing the Shrines to give Commerce
And one of these days, I'll learn that nothing is ever as easy as I think it will be! :lol: I went ahead and tried to add a Yield array to ReligionInfos.xml, and I got everything in fine, until I got to CvCity.cpp, CvCityAI.cpp, & CvPlayerAI.cpp. Now, forgetting the AI's for the nonce (I think I might actually be able to figure them out for myself, but am going to try later) CvCity left me stumped with how to get it to count Yields from Shrines. Here's what I added, under void CvCity::setBuildingYieldChange
Code:
if (GC.getBuildingInfo(eBuilding).getGlobalReligionYield() != NO_RELIGION)
{
	iChange += (GC.getReligionInfo((ReligionTypes)(GC.getBuildingInfo(eBuilding).getGlobalReligionYield())).getGlobalReligionYield([COLOR="DarkOrange"]eYield[/COLOR]) * GC.getGameINLINE().countReligionLevels((ReligionTypes)(GC.getBuildingInfo(eBuilding).getGlobalReligionYield()))) * getNumActiveBuilding(eBuilding);
}
The above code is actually copied almost word-for-word from int CvCity::getBuildingCommerceByBuilding, but, needless to say, it worked even worse than a lead balloon's supposed to (ah, MythBusters...). So, I'll try to pick at that tonight, hopefully tomorrow, maybe go over RawYields again some too...

Yeesh, I just keep digging deeper, don't I? Is there a bottom to this thing...? :D :crazyeye:
 
Yes, it's odd to see how Firaxis coded things one way for Yields and another way for Commerce. CvCity has a function to recalculate the total Commerce for any given type, yet there is no equivalent function for Yields. With Yields, everything needs to alter Base Yield as you did with Tech Yield Change.

In this case, however, the added :commerce: will change as the religion spreads--not only when the Shrine is added to the city. This will make it more complicated, but not impossible.

You have two options: 1) shoehorn it in the same way you did Tech Yield Change, or 2) bite the bullet and build your own calculateBaseYield() or whatever matches the Commerce function's name.

Hmm, I think I'd still go with (1), but it may pay to track down the current logic flow for how religion spread adds :gold: to the Shrine. That would give you a good road map and better insight into whether or not (2) is the better path.
 
What do you think of just "shoe-horning" (love that term ;)) the new ShrineYields into my original code that I added for the TechYields?
Code:
for (iI = 0; iI < NUM_YIELD_TYPES; iI++)
{
	changeBaseYieldRate((YieldTypes)iI, GET_PLAYER(getOwnerINLINE()).getYieldChange((YieldTypes)iI));
}
Perhaps that would be easiest? I already have a model for how to count up the changes to the ShrineYields from how CvCity counts up changes to Shrine Commerce (down in int CvCity::getBuildingCommerceByBuilding, search for GlobalReligionCommerce). The important thing is that the Yields are tabulated, right? Who cares if they get added in when CvCity is counting up Building yield changes, or at the end when it adds in random leftover stuff, so long as it gets counted. ... ... Right? :confused:

As for the logic flow, I think that's all in CvCity... Everything else I found for GlobalReligionCommerce (which is the relevant XML tag for adding Gold to Shrines) seems to just be the necessary stuff to declare the tag and say what's in it. It seems the only instance of functionality is CvCity... That should probably be double-checked... :mischief:
 
OK, I don't know enough C++... I'm gonna try teaching myself some more, hopefully I can sort this out... I think, EF, that option 2 will be the best bet for adding Yields to Shrines, but like I said, I don't yet know enough...

Also, I forgot to mention, when you have the opportunity to look at my mod, let me know what you think of what I did to the Specialist Stacker. I made a small change to it, I much prefer it. If you like it too, and think others might, please feel free to add it to BUG.
 
I've been very busy building a new install script for BUG so we can release an installer more frequently (nightly, hopefully!) and working on the BUG DLL. I'll take a look at the SS soon as I'm looking to improve it.

Your method sounds good, so give it a shot (I still recommend tracing through how the Shrine :gold: gets applied when its religion spreads). When you have a question, post something with code and I can take a look.
 
Well, I'm back, finally. Got a nasty virus on my PC just two days after my last post, and I only just decided that a complete format and reinstall was going to be the only way to recover about a week ago. So, now that I have everything running again, I can finally get back to business in regards to adding Yields to Shrines.

As per xienwolf's inital advice, I tried to add a new GlobalReligionYield to CvInfos and CvGameTextMgr first, just to get it showing the 'Pedia. But nothing shows, and I'm not quite sure why...

Trying to start small, baby-steps like before, but it's turning out to be harder than the Tech Yields...

So, although I can't imagine why this would be the case, does the 'Pedia look up religion info differently than Tech info? IE: is there an extra step I need to take other than just CvInfos and CvGameTextMgr?
 
With how bland religions are in basic Civ, I would imagine that the python file to construct your output doesn't account for there BEING any differences. So whatever you create for the religion you'll have to tell python how/where to display it.

You don't specifically state that you created a new function in CvGameTextMgr, so I assume you used CvGameTextMgr::setReligionHelp? By default that gets a very tiny box, but I would imagine it should develop a scrollbar if you added information to it.
 
Top Bottom