1. We have added a Gift Upgrades feature that allows you to gift an account upgrade to another member, just in time for the holiday season. You can see the gift option when going to the Account Upgrades screen, or on any user profile screen.
    Dismiss Notice

Unofficial Patch for 3.19

Discussion in 'Civ4 - Unofficial Patches' started by jdog5000, Jun 12, 2009.

  1. EmperorFool

    EmperorFool Deity

    Joined:
    Mar 2, 2007
    Messages:
    9,633
    Location:
    Mountain View, California
    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.
     
  2. jdog5000

    jdog5000 Revolutionary

    Joined:
    Nov 25, 2003
    Messages:
    2,601
    Location:
    California
    Great stuff, thanks EF and jesusin!
     
  3. LunarMongoose

    LunarMongoose King

    Joined:
    Jan 29, 2006
    Messages:
    731
    Gender:
    Male
    Location:
    Boston, MA, USA
    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>
     
  4. LunarMongoose

    LunarMongoose King

    Joined:
    Jan 29, 2006
    Messages:
    731
    Gender:
    Male
    Location:
    Boston, MA, USA
    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);
     
  5. snarko

    snarko DLLer

    Joined:
    Dec 9, 2003
    Messages:
    1,512
    Location:
    Sweden
    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];
     		}
     	}
     
  6. Afforess

    Afforess The White Wizard

    Joined:
    Jul 31, 2007
    Messages:
    12,239
    Location:
    Austin, Texas
    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.
     
  7. r_rolo1

    r_rolo1 King of myself

    Joined:
    May 19, 2006
    Messages:
    13,818
    Location:
    Lisbon, Portugal
    That seems similar to the infinite techs from Liberalism/Oracle bug ... should be easily solvable.
     
  8. NBAfan

    NBAfan boss

    Joined:
    Aug 30, 2007
    Messages:
    3,351
    Location:
    Dallas TX,United States
    Is it a problem if you don't right click?
     
  9. Fuyu

    Fuyu Emperor

    Joined:
    Nov 5, 2009
    Messages:
    1,225
    Location:
    Austria
    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;
    	}
    }
     
  10. LunarMongoose

    LunarMongoose King

    Joined:
    Jan 29, 2006
    Messages:
    731
    Gender:
    Male
    Location:
    Boston, MA, USA
    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.
     
  11. LunarMongoose

    LunarMongoose King

    Joined:
    Jan 29, 2006
    Messages:
    731
    Gender:
    Male
    Location:
    Boston, MA, USA
    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;
    }
     
  12. jdog5000

    jdog5000 Revolutionary

    Joined:
    Nov 25, 2003
    Messages:
    2,601
    Location:
    California
    Thanks EF, jesusin, snarko, and LM! Your changes from the last month have been folded in and will be part of UP 1.6.
     
  13. LunarMongoose

    LunarMongoose King

    Joined:
    Jan 29, 2006
    Messages:
    731
    Gender:
    Male
    Location:
    Boston, MA, USA
    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.
     
  14. Ninja2

    Ninja2 Great Engineer

    Joined:
    Nov 17, 2005
    Messages:
    1,142
    Location:
    Denmarkia
    I can't seem to find this beta 1.6 in SF? :)
     
  15. DannyDaemonic

    DannyDaemonic Chieftain

    Joined:
    Jun 6, 2010
    Messages:
    25
    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));
    
     
  16. EmperorFool

    EmperorFool Deity

    Joined:
    Mar 2, 2007
    Messages:
    9,633
    Location:
    Mountain View, California
    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));
    
     
  17. DannyDaemonic

    DannyDaemonic Chieftain

    Joined:
    Jun 6, 2010
    Messages:
    25
    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?
     
  18. EmperorFool

    EmperorFool Deity

    Joined:
    Mar 2, 2007
    Messages:
    9,633
    Location:
    Mountain View, California
    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.

    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.
     
  19. DannyDaemonic

    DannyDaemonic Chieftain

    Joined:
    Jun 6, 2010
    Messages:
    25
    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.

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

    I was just worried about consistency. If it's to distinguish between two valid interpretations then this isn't a bug for UP.
     
  20. EmperorFool

    EmperorFool Deity

    Joined:
    Mar 2, 2007
    Messages:
    9,633
    Location:
    Mountain View, California
    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.
     

Share This Page