Unofficial Patch for 3.19

Minor addition: when clearing a Forest/Jungle from a tile with an improvement that requires it (Lumbermill and Forest Preserve), the following code in CvDLLWidgetData::parseActionHelp() adds a second message below the "Will remove the <feature>" one.

Code:
				if (pMissionPlot->getFeatureType() != NO_FEATURE)
				{
					if (GC.getBuildInfo(eBuild).isFeatureRemove(pMissionPlot->getFeatureType()))
					{
						iProduction = pMissionPlot->getFeatureProduction(eBuild, pHeadSelectedUnit->getTeam(), &pCity);

						if (iProduction > 0)
						{
							szBuffer.append(NEWLINE);
							szBuffer.append(gDLL->getText("TXT_KEY_ACTION_CHANGE_PRODUCTION", iProduction, pCity->getNameKey()));
						}

						szBuffer.append(NEWLINE);
						szBuffer.append(gDLL->getText("TXT_KEY_ACTION_REMOVE_FEATURE", GC.getFeatureInfo(pMissionPlot->getFeatureType()).getTextKeyWide()));

// BUG - Unofficial Patch - start
						if (eImprovement == NO_IMPROVEMENT && pMissionPlot->getImprovementType() != NO_IMPROVEMENT && GC.getImprovementInfo(pMissionPlot->getImprovementType()).getFeatureMakesValid(pMissionPlot->getFeatureType()))
						{
							szBuffer.append(NEWLINE);
							szBuffer.append(gDLL->getText("TXT_KEY_ACTION_WILL_DESTROY_IMP", GC.getImprovementInfo(pMissionPlot->getImprovementType()).getTextKeyWide()));
						}
// BUG - Unofficial Patch - end
					}

				}

Edit: Fixed so that it won't show a double message for build actions that will both replace a previous improvement and remove a feature that the previous improvement requires.
 
Woot JDog is alive... Alright my turn, can't let everyone else have all the fun. :) Edit - moved here from the BBAI forum where I posted it originally cuz I wasn't thinking about where I was posting it cuz I was busy and should pay more attention to thinking about where I'm posting things next time. *nods*

If you set a Feature to have a negative iTurnDamage XML value so that it provides healing (as I do with the Oasis in my mod for example), units there do correctly heal faster, however the tile mouseover pane will not tell you about it like it will for a damage effect. This issue would only potentially affect mods, however the turns-needed-to-fully-heal value displayed in the Heal Command's mouseover is also wrong because it ignores iTurnDamage altogether, even with positive damage values. Lastly I added a text line for the Pedia entries of feature types if there is a damage or healing effect, which was missing.

Modified at the bottom of CvGameTextMgr::setPlotHelp()

Code:
	if (pPlot->getFeatureType() != NO_FEATURE)
	{
		//
		// Mongoose FeatureDamageFix BEGIN
		//
		int iDamage = GC.getFeatureInfo(pPlot->getFeatureType()).getTurnDamage();
		if (iDamage > 0)
		{
			szString.append(CvWString::format(SETCOLR, TEXT_COLOR("COLOR_NEGATIVE_TEXT")));
			szString.append(NEWLINE);
			szString.append(gDLL->getText("TXT_KEY_PLOT_DAMAGE", iDamage));
			szString.append(CvWString::format( ENDCOLR));
		}
		else if (iDamage < 0)
		{
			szString.append(CvWString::format(SETCOLR, TEXT_COLOR("COLOR_POSITIVE_TEXT")));
			szString.append(NEWLINE);
			szString.append(gDLL->getText("TXT_KEY_PLOT_DAMAGE", iDamage));
			szString.append(CvWString::format( ENDCOLR));
		}
		//
		// Mongoose FeatureDamageFix END
		//
	}

Added into the middle of CvUnit::healTurns()

Code:
int CvUnit::healTurns(const CvPlot* pPlot) const
{
	int iHeal;
	int iTurns;

	if (!isHurt())
	{
		return 0;
	}

	iHeal = healRate(pPlot);

	//
	// Mongoose FeatureDamageFix BEGIN
	//
	FeatureTypes eFeature = pPlot->getFeatureType();
	if (eFeature != NO_FEATURE)
	{
		iHeal -= GC.getFeatureInfo(eFeature).getTurnDamage();
	}
	//
	// Mongoose FeatureDamageFix END
	//

	if (iHeal > 0)
	{
		iTurns = (getDamage() / iHeal);

And added into the middle of CvGameTextMgr::setFeatureHelp()

Code:
	else if (feature.getHealthPercent() < 0)
	{
		szBuffer.append(gDLL->getText("TXT_KEY_FEATURE_BAD_HEALTH", szHealth.GetCString()));
	}

	if (feature.getDefenseModifier() != 0)
	{
		szBuffer.append(gDLL->getText("TXT_KEY_TERRAIN_DEFENSE_MODIFIER", feature.getDefenseModifier()));
	}

	//
	// Mongoose FeatureDamageFix BEGIN
	//
	if (feature.getTurnDamage() > 0)
	{
		szBuffer.append(gDLL->getText("TXT_KEY_TERRAIN_TURN_DAMAGE", feature.getTurnDamage()));
	}
	else if (feature.getTurnDamage() < 0)
	{
		szBuffer.append(gDLL->getText("TXT_KEY_TERRAIN_TURN_HEALING", -feature.getTurnDamage()));
	}
	//
	// Mongoose FeatureDamageFix END
	//

	if (feature.isAddsFreshWater())
	{
		szBuffer.append(gDLL->getText("TXT_KEY_FEATURE_ADDS_FRESH_WATER"));
	}

	if (feature.isImpassable())
	{
		szBuffer.append(gDLL->getText("TXT_KEY_TERRAIN_IMPASSABLE"));
	}

Which uses two new XML text tags

Code:
	<TEXT>
		<Tag>TXT_KEY_TERRAIN_TURN_DAMAGE</Tag>
		<English>[NEWLINE][ICON_BULLET]%D1%% Damage/Turn</English>
	</TEXT>
	<TEXT>
		<Tag>TXT_KEY_TERRAIN_TURN_HEALING</Tag>
		<English>[NEWLINE][ICON_BULLET]%D1%% Healing/Turn</English>
	</TEXT>
 
Oh and here's another thing I found a few weeks ago. I'm not certain if I'm the first to fix this, but I'm not yet aware of anyone else having done so.

Basically it removes an erroneous extra increment command that was breaking GameFont.tga files when using exactly 49 or 74 resource types in a mod. (I'm pretty sure that 50-73 and 75 resource types still worked however.) Anyway with this change you can freely finish filling up the second bonus/resource row in the vanilla GameFont file, and use the third one, and it all works fine without having to resort to wider and/or strangely-shaped/formatted GameFont files. You'll still need a bigger file if you need more than what the three vanilla rows can hold which is 75 resources, but it should make those solutions a lot easier to implement.

In the middle of CvGameTextMgr::assignFontIds()

Code:
	do 
	{
		++iCurSymbolID;
	} while (iCurSymbolID % iPadAmount != 0);

	if (2 * (GC.getNumReligionInfos() + GC.getNumCorporationInfos()) < iPadAmount)
	{
		do 
		{
			++iCurSymbolID;
		} while (iCurSymbolID % iPadAmount != 0);
	}

	// set bonus symbols
	int bonusBaseID = iCurSymbolID;

	//
	// Mongoose GameFontFix BEGIN
	//
	//
	// Mongoose GameFontFix END
	//

	for (int i = 0; i < GC.getNumBonusInfos(); i++)
	{
		int bonusID = bonusBaseID + GC.getBonusInfo((BonusTypes) i).getArtInfo()->getFontButtonIndex();
		GC.getBonusInfo((BonusTypes) i).setChar(bonusID);
		++iCurSymbolID;
	}

	do 
	{
		++iCurSymbolID;
	} while (iCurSymbolID % iPadAmount != 0);
 
There's a bug with simultaneous team turns. I don't see it fixed in the repository files. Original thread.

The problem is in CvGame::doTurn(). (line 5689 in the repository file, rev 32). The break is supposed to be inside the if but because it's not we only check the first civilization.

The relevant code
Code:
	else if (isSimultaneousTeamTurns())
 	{
 		for (iI = 0; iI < MAX_TEAMS; iI++)
 		{
 			CvTeam& kTeam = GET_TEAM((TeamTypes)iI);
 			if (kTeam.isAlive())
 			{
 				kTeam.setTurnActive(true);
 				FAssert(getNumGameTurnActive() == kTeam.getAliveCount());
 			}
 
 			[B]break[/B];
 		}
 	}
 
I've found an egregious bug in the Choose Religions gameoption. When you see the popup to pick a religion, you can manipulate it to let you found as many as 5 new religions that turn.

Here is how to reproduce it:

Start a new BTS game with Choose Religions. Give your self 2 Great Prophet's via the Worldbuilder and bulb Mysticism and Meditation. The choose religion popup should appear. RIGHT CLICK on any of the religions, and the popup will disappear and then re-appear moments later, continue RIGHT CLICKING 5-6 times like this. Then left click and begin choosing religions. The popup will keep appearing and let you found 5 religions in one turn.

I'm not familiar enough with how Popups work, but this is an egregious bug. Props to egogo for finding it.
 
More importantly it's not a problem if you don't use Choose Religion :p

@LunarMongoose
I think your change to CvUnit::healRate() is a bad idea.
If you look at CvUnit::doTurn()
Code:
void CvUnit::doTurn()
{

[COLOR="Gray"][I](...bla...)[/I][/COLOR]

	if (baseCombatStr() > 0)
	{
		FeatureTypes eFeature = plot()->getFeatureType();
		if (NO_FEATURE != eFeature)
		{
			if (0 != GC.getFeatureInfo(eFeature).getTurnDamage())
			{
				[B]changeDamage([/B]GC.getFeatureInfo(eFeature).getTurnDamage(), NO_PLAYER[B])[/B];
			}
		}
	}

	if (hasMoved())
	{
		if (isAlwaysHeal())
		{
			[B]doHeal()[/B];
		}
	}
	else
	{
		if (isHurt())
		{
			[B]doHeal()[/B];
		}

[COLOR="Gray"]		if (!isCargo())
		{
			changeFortifyTurns(1);
		}[/COLOR]
	}

and CvUnit::doHeal()
Code:
void CvUnit::doHeal()
{
	changeDamage(-(healRate(plot())));
}
you'll surely notice that your change would cause the feature damage to be applied twice, once as actual damage via changedamage() and once more as a reduction to healing.

If you want healturns() to return the right number, you'll have to fix that function directly.

Code:
int CvUnit::healTurns(const CvPlot* pPlot) const
{
	int iHeal;
	int iTurns;

	if (!isHurt())
	{
		return 0;
	}

	iHeal = healRate(pPlot);

[B]	FeatureTypes eFeature = plot()->getFeatureType();
	if (NO_FEATURE != eFeature)
	{
		iHeal -= GC.getFeatureInfo(eFeature).getTurnDamage();
	}[/B]

	if (iHeal > 0)
	{
		iTurns = (getDamage() / iHeal);

		if ((getDamage() % iHeal) != 0)
		{
			iTurns++;
		}

		return iTurns;
	}
	else
	{
		return MAX_INT;
	}
}
 
you'll surely notice that your change would cause the feature damage to be applied twice, once as actual damage via changedamage() and once more as a reduction to healing.

If you want healturns() to return the right number, you'll have to fix that function directly.

Wow, I'm getting sloppy in my old age. Sorry, probably would've noticed that if we'd actually played any the last week. Your fix to my fix is, of course, exactly correct, and I updated my original post in case JDog hasn't seen this yet. Thanks Fuyu.
 
I'm adding one final thing to this component that is now necessary. The game blocks the heal command from appearing at all when the heal rate is zero or negative... from the usual sources (zero heal rate in enemy territory, negative heal rate promotions, etc). But with Fuyu's change it will still display a heal command, with a turns-to-heal value of MAX_INT, in-game if a feature is causing a zero or negative heal rate. Sooo, this will fix that. :)

Code:
bool CvUnit::canHeal(const CvPlot* pPlot) const
{
	if (!isHurt())
	{
		return false;
	}

	if (isWaiting())
	{
		return false;
	}

	//
	// Mongoose FeatureDamageFix BEGIN
	//
	if (healTurns(pPlot) == MAX_INT)
	{
		return false;
	}
	//
	// Mongoose FeatureDamageFix END
	//

	return true;
}
 
Just grabbed the 1.01c source files from SF, which lead me to the following points:

You haven't added my CargoLoadFix update yet, wanted to make sure you didn't forget about it! (See the bottom of the Version 1.5 thread, where you already said it looked good. :p)

You didn't use the code segment in my last post here exactly as-is, even though I posted the whole function for a reason. Sigh, you need to learn to trust me more, dood. ;) You left the vanilla "if (healRate(pPlot) <= 0)" condition in at the end, however this is completely redundant with the new check of healTurns(pPlot) returning MAX_INT or not since healTurns calls healRate itself, and uses the same condition as part of its return value. So your version will cause healRate, which is a relatively expensive function, to get called twice most of the time, when it never needs to be.
 
Thanks EF, jesusin, snarko, and LM! Your changes from the last month have been folded in and will be part of UP 1.6.

I can't seem to find this beta 1.6 in SF? :)
 
When holding ALT to see combat odds against an enemy, you are matched up against the best enemy unit in that plot. However, if there is a unit in that plot with whom you are not at war, but is better at defending than your enemy, it will show your odds against that unit. This is a display bug only, when attacking you are still only matched up against enemy units.

The problem is in CvGameTextMgr's setCombatPlotHelp:
Code:
bool CvGameTextMgr::setCombatPlotHelp(CvWStringBuffer &szString, CvPlot* pPlot)
...
		pDefender = pPlot->getBestDefender(NO_PLAYER, pAttacker->getOwnerINLINE(), pAttacker, false, NO_TEAM == pAttacker->getDeclareWarMove(pPlot));

As far as I know, and please correct me if I'm wrong, there's no way to see combat odds against someone with whom you aren't at war. So the fix is simple, just change the 3rd parameter, bTestAtWar, from false to true:
Code:
		pDefender = pPlot->getBestDefender(NO_PLAYER, pAttacker->getOwnerINLINE(), pAttacker, [B]true[/B], NO_TEAM == pAttacker->getDeclareWarMove(pPlot));
 
You can see combat odds by holding down ALT while hovering over a plot, so I changed the above to this in BULL:

Code:
pDefender = pPlot->getBestDefender(
	NO_PLAYER, pAttacker->getOwnerINLINE(), pAttacker, 
	[B][COLOR="Red"]!gDLL->altKey()[/COLOR][/B], NO_TEAM == pAttacker->getDeclareWarMove(pPlot));
 
I only know of two ways, dragging and ALT. Both dragging the unit and ALT work the same as far as I know.

I had noticed the bug when playing but didn't have a save showing it, so when I was looking for the bug and testing the fix, I was using "advanced start" and old saves. In the old saves, I had open borders with everyone, and with "advanced start" there are 10 years of universal peace. In neither case will it show you the odds, so I drew the wrong conclusion about when it would show the odds. I felt unsure, hence my "please" in my previous post. I vaguely remembered getting odds against units before war.

The game will only show you the odds if you are able to attack the unit. As a side note, they should have made an override key so you could see the odds anyway, like a SHIFT-ALT.

It seems to me, the problem wouldn't be fixed by your patch when someone drags a unit to look at the odds. Would your fix intentionally differentiate the combat odds shown when holding ALT and when dragging a unit?
 
I only know of two ways, dragging and ALT. Both dragging the unit and ALT work the same as far as I know.

I hold down right-click on the target tile to see the odds, and release it on my unit if I want to cancel the order. So that's a third way I guess. I've never tried dragging units before.

It seems to me, the problem wouldn't be fixed by your patch when someone drags a unit to look at the odds. Would your fix intentionally differentiate the combat odds shown when holding ALT and when dragging a unit?

Do you mean my patch that uses the state of the ALT key? The way I have it the odds of the friendly unit that you can DoW on would be shown only if you used the ALT key to hover over the target. I chose that since I use the right-click (non-ALT) method normally.
 
I tried to recreate the bug exactly, but I only seem to get it when it thinks I want to attack friendly units. Is there ever a time when it shows the wrong battle odds but doesn't ask you if you want to fight the friendly units? I know I've seen the wrong odds, but maybe it was always accompanied by a declaration of war question. If that's the case, then this isn't a bug, it's a control/interface issue.

I hold down right-click on the target tile to see the odds, and release it on my unit if I want to cancel the order. So that's a third way I guess. I've never tried dragging units before.

Ah, I turned on Right Click menus, so that doesn't work for me.

Do you mean my patch that uses the state of the ALT key? The way I have it the odds of the friendly unit that you can DoW on would be shown only if you used the ALT key to hover over the target. I chose that since I use the right-click (non-ALT) method normally.

I was just worried about consistency. If it's to distinguish between two valid interpretations then this isn't a bug for UP.
 
It's a bug in that you cannot see the odds for the unit you'll end up fighting, and it won't ask you if you'd like to DoW on the friendly unit if there's an unfriendly unit there. In that sense, it's a bug in my eyes.

The reason I suggest doing it the way I have is that you can still see the odds against the other unit if you'd like to DoW them. Of course, that's only if they are a better defender than the one you're at war with. So either way it's suboptimal.
 
Top Bottom