Development Thread

For the Show Hidden Attitude Mod I have a suggestion/request: In debug mode, all hidden attitudes should be visible even if the dll wasn't compiled with the all-revealing spoiler option. (GC.getGameINLINE().isDebugMode() should have the same revealing effect as the _MOD_SHAM_SPOILER cflag)
 
I agree, and I'll do that after I get 1.1 out the door. DaveMcW did it for one of the modifiers, but not all.
 
I think it is not intended that I can see Worst Enemy is X even if I didn't meet X yet.

The Worst Enemy Is part from CvGameTextMgr::getOtherRelationsString() should probably look like this:
Code:
	if (!kThisTeam.isHuman())
	{
		TeamTypes eWorstEnemy = kThisTeam.AI_getWorstEnemy();
		if (eWorstEnemy != NO_TEAM && eWorstEnemy != eSkipTeam && (eOtherTeam == NO_TEAM || eWorstEnemy == eOtherTeam)[B] && GET_TEAM(eWorstEnemy).isHasMet(GC.getGameINLINE().getActiveTeam())[/B])
		{
			szString.append(NEWLINE);
			szString.append(gDLL->getText(L"TXT_KEY_WORST_ENEMY_IS", GET_TEAM(eWorstEnemy).getName().GetCString()));
		}
	}
 
You shouldn't see anything about anyone you haven't met. I thought that was already in there. I must have removed it when I rewrote it. Shoot. :( That's what I get for doing a major feature right before release after a two week period of inactivity. :mad:
 
I saw a post saying that certain BUG options need to be set the same setting for all players in Multiplayer games, to keep things from going OOS. So what I'm requesting, and will help with development on, is a means to check certain flagged options (probably set up this flagging tag in the confg xml files) and verify they are all the same, if not it would set all players to having the same settings as the host player (the player that sets up the MP game). I'm not sure where to start, but I'm fairly certain this is doable. Any ideas on how to start me off on this?
 
The solution would be trivial if BUG could depend on always running as a mod--having a custom DLL. I'd just move these settings into CvPlayer using PlayerOptions. All of the options such as Workers Start Automated are done this way and kept in-sync across all machines in a multiplayer game. This would allow players to have different settings and keep the game from going OOS.

But BUG doesn't have that luxury. :( And as odd as this sounds, neither does BULL. I know, BULL is a custom DLL, so clearly it can do whatever it wants. The problem is that it's not having a custom DLL that is important; it's the ability to add more PlayerOptionTypes values that get written into the saved game. If I modify BULL to have more PlayerOptionTypes, I break saved-game-compatibility with any non-BULL games.

One option is to have an MP-only DLL that has those options as PlayerOptions and a normal DLL that leaves them in BUG. That's probably not so bad an option, actually, but I'm hoping maybe someone sees an easier solution.

I thought of using net messages to tell each machine the settings each player is using, but that seems a) like a lot of work and b) dicey at best. Given that the game has a built-in facility this (PlayerOptions), it doesn't seem like a good solution.

Forcing everyone in code to use the same setting would work, but it would also be a lot of work and I think less elegant than a separate MP DLL.

Edit: BTW, the options include any setting that alters the game mechanics. This means that all the settings that control what gets displayed in a hover don't matter. The ones that matter are Pre-Chop (2) and Sentry Healing (also 2). The Governors Build Workers settings (again 2) are already PlayerOptions. The game has 3 slots for modders in the PlayerOptions, and GBW took 2 of them.
 
Well, to be honest part of the reason I liked the idea of forcing the options as set by the host player, is that it's an elegant solution that would work for some of the RevolutionDCM options :mischief: In RevDCM there are gameplay options set in the BUG screen tabs, like "Super Spies" that allow promotions for spies, and "IDW" that causes battles to have cultural effects on tiles. So that's why I was interested in doing things that way. If a BULL_MP decides to move everything into the player options path, that means I'd have to do the same for all the RevDCM options, not bad but it sounds complex. Anyway I'm willing to help working on getting the functionality working so that BUG options can be standardized in MP games, and so that the game wol't OOS if different settings exist on different machines, but I need direction on where to begin and specifics on how to start. Also at the end of the day I'll need a means to enforce standardization for some options; I don't see any way around it; well I do by making them game options, but if all the options are added to custom game start up options it becomes a huge unwieldy mess of a list.
 
I think it is not intended that I can see Worst Enemy is X even if I didn't meet X yet.

Ah okay, I see it was just that one line that is checked outside of the loop. I've added the check and will commit it after testing.
 
Oh, I see. Well, those really should be game options given how they work. I understand your desire to make that custom game screen less crowded, but I think writing code to enforce options across machines is itching for trouble. How many options are we talking about here?

I suppose it wouldn't be too hard. You'd need a single message broadcast by the host* for each option. For non-string options you can get away with using the standard modNetMessage. I doubt you have any string options that need such synchronization. This would have to be broadcast during game start and load events. It could be done every time those settings are changed, too, to catch changes before they cause an OOS.

What should happen if anyone has a different setting? Just change their setting locally? That's probably safe enough since the player hasn't had a chance to take any actions that would have effects dependent on those settings.

* How do you detect the host in an MP game? Is it always player 0? This is important because BUG will need to pick a player to be in charge. We don't want every player broadcasting their settings--just the host.
 
nvm?..
damn I just shouldn't merge python files manually with ignore indentation on.

Especially if I don't have to merge anything at all.
 
AI related: How does your Actual Building Effects code catch the base yield boni for religious buildings that come with having certain wonders & state religion, or having the same religion as the apostolic palace?
Is it CvCity::getBuildingYieldChange(BuildingClassTypes eBuildingClass, YieldTypes eYield) ?
 
If I remember when I get home, I'll tell ya. In the meantime, the code is in CvCity::getAdditionalYieldByBuilding(). It's probably that one you posted, though. Or is there one on CvPlayer?
 
Actual Building Effects again:

You're doing Area Effects but not Global?
Code:
	[COLOR="Green"]// Area[/COLOR]
	addGoodOrBad(kBuilding.getAreaHealth(), iGood, iBad);
missing:
Code:
	[COLOR="Green"]// Global[/COLOR]
	addGoodOrBad(kBuilding.getGlobalHealth(), iGood, iBad);
same for Happiness

But with happiness, there's one more case you didn't consider that isn't present in the unmodded game but should still be checked: It's possible that building one building can change the buildingclass happy bonus of other buildings. The AI checks for that on a global level using these lines:
Code:
				for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
				{
					if (kBuilding.getBuildingHappinessChanges(iI) != 0)
					{
						iValue += (kBuilding.getBuildingHappinessChange[B]s[/B](iI) * kOwner.getBuildingClassCount((BuildingClassTypes)iI) * 8);
					}
				}

For actual effects you'd need to check if the city already has a building of a buildingclass that gets a happinessChange from the building you are building :crazyeye:
Code:
	[COLOR="Green"]// Other Building Classes[/COLOR]
	CvBuildingInfo& kLoopBuilding;
	int iBuildingHappinessChanges;
	for (iI = 0; iI < GC.getNumBuildingInfos(); iI++)
	{
		kLoopBuilding = GC.getBuildingInfo(iI);
		iBuildingHappinessChanges = kBuilding.getBuildingHappinessChange[B]s[/B](kLoopBuilding.getBuildingClassType());
		if (iBuildingHappinessChanges != 0 && (getNumRealBuilding(iI) + getNumFreeBuilding(iI)) > 0)
		{
			addGoodOrBad(iBuildingHappinessChanges * (getNumRealBuilding(iI) + getNumFreeBuilding(iI)), iGood, iBad);
		}
	}
 
Thanks, I've added all three of those now. Dunno how I missed the two global ones as I went through both CvCity:: and CvPlayer::processBuilding() line-by-line. :confused:

I tweaked the Building Classes code slightly, but there is one change that is significant: I call getNumBuilding() instead of adding the Real and Free buildings. This function does the same calculation except it caps it at CITY_MAX_NUM_BUILDINGS. I'm looking now to see if the function that calculates the city happiness uses this as well. Here's the code I have:

Code:
	// Other Building Classes
	for (iI = 0; iI < GC.getNumBuildingInfos(); iI++)
	{
		int iBuildingHappinessChanges = kBuilding.getBuildingHappinessChanges(GC.getBuildingInfo((BuildingTypes)iI).getBuildingClassType());
		if (iBuildingHappinessChanges != 0)
		{
			addGoodOrBad(iBuildingHappinessChanges * getNumBuilding((BuildingTypes)iI), iGood, iBad);
		}
	}

Other stylistic changes in case you're wondering include

  • Removed check that the number of buildings isn't zero since addGoodOrBad() does this already (< 0 and > 0 checks), and an extra function call when the player doesn't have any of that building isn't going to kill hover text performance.
  • Moved declaration of iBuildingHappinessChanges to inside for() block where it's used since the compiler is smart enough to allocate a single slot on the stack for it and reuse it across all iterations.
  • Removed use of CvBuildingInfo reference since it's used in only one spot.
I made all these changes in the interest of having as little code there as possible without affecting performance. It keeps the otherwise long function easy to read and understand quickly.
 
There's one problem with this code, but it will only appear in mods that allow multiple buildings of the same class to appear in a single city, for example a mod that keeps civ X's UBs in a city conquered by civ Y.

CvPlayer::processBuilding() provides the extra happiness only to the BuildingType for the player's CivilizationType. You might consider this to be a bug in the original game, but Civ4 has a requirement that a city can only have its owner's BuildingType for each BuildingClass. Mods that remove this requirement must be sure to change all places in the code that assume this, BULL included I think.

So I'll rewrite it to loop over BuildingClassTypes instead.

Edit: Done.

Code:
	// Other Building Classes
	CvCivilizationInfo& kCivilization = GC.getCivilizationInfo(getCivilizationType());
	for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
	{
		int iBuildingHappinessChanges = kBuilding.getBuildingHappinessChanges(iI);
		if (iBuildingHappinessChanges != 0)
		{
			BuildingTypes eLoopBuilding = (BuildingTypes)kCivilization.getCivilizationBuildings(iI);
			if (eLoopBuilding != NO_BUILDING)
			{
				addGoodOrBad(iBuildingHappinessChanges * getNumBuilding(eLoopBuilding), iGood, iBad);
			}
		}
	}
 
Perfect, I knew I should let you do this instead of doing it myself ;)

Btw, is it possible that a building of a certain buildclass increases happiness for all buildings of the same class, as in it increases its own happy bonus over buildingclass? If you have 1 building in 1 city, it gives 1 happy, if you have 7 cities and construct that building in all of them, each would give 7 happy.. It would be crazy but I think it's not disallowed.
In that case you'd need to check for that too.
 
Perfect, I knew I should let you do this instead of doing it myself ;)

Absolutely not! Providing the code made it much easier for me to add this in. So I tweaked it a little because I'm super anal, but that took four minutes instead of a twenty to look up all the functions and make sure it was right. Believe me, that helps a ton and vastly increases the likelihood I'll do something. :D

Btw, is it possible that a building of a certain buildclass increases happiness for all buildings of the same class.

Oooh, good point. CvPlayer::processBuilding() is called at the very end of CvCity::processBuilding(), so I don't know what would happen in this case. It may not affect itself, but it would affect the same building in the player's other cities I think. Hmm, which is faster: working through the code or setting up a trial? :lol:
 
No, if it's called at the end and can't affect itself and if the buildingHappinessChange variable is created anew every turn, then it's safe to say that it is not intended and shouldn't be used, ignoring it is the better option then.
It was just a thought.


Oh right, I should read more carefully, you wrote you don't know what would happen. No idea, do you know a mod that uses this tag?
 
Back
Top Bottom