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. Roland Johansen

    Roland Johansen Deity

    Joined:
    Apr 29, 2003
    Messages:
    4,292
    Location:
    the Netherlands
    He's talking about a unit with a great general attached. Those don't lose experience on upgrading.

    EDIT: I shouldn't be posting in multiple threads at once. I'm too slow everywhere.
     
  2. Grave

    Grave 1 Goat = 400 Horses

    Joined:
    May 5, 2002
    Messages:
    1,530
    Location:
    Louisiana
    I have a request...

    I'd like to see units be able to be traded for gold in the diplomacy screen. Perhaps the value of the unit could be determined by the cost to upgrade that unit? You would of course have to have the required PreReqTechs for the unit you wish to purchase.

    Example: Say I want to buy a Longbowman. It would cost me the amount of gold it would take to upgrade a standard Archer to a Longbowman in order to purchase that Longbowman.


    Just a rough idea....
     
  3. deanej

    deanej Deity

    Joined:
    Apr 8, 2006
    Messages:
    4,859
    Location:
    New York State
    That's beyond the scope of an unofficial patch. Interesting idea for a mod though.
     
  4. GravityWave

    GravityWave Deposed Emperor

    Joined:
    Mar 25, 2008
    Messages:
    290
    Gender:
    Male
    Location:
    England
    Yes, I am sure there is a cap. At around 4xx (iirc) instead of the experience indicator saying how many points you need to get the next promotions it stays the same - i.e instead of saying 11 / 17 it would say 11 / 10 so you can never get another promo. I'm not surprised you ain't reached the cap as most people probably don't DOW on everyone and have mounted units with GG, Blitz, morale, & mobility (Justinian is my stress relief).

    Unfortunately I don't have a save at moment, but next time I play as Byzantium I'll try to remember to post one.
     
  5. Afforess

    Afforess The White Wizard

    Joined:
    Jul 31, 2007
    Messages:
    12,239
    Location:
    Austin, Texas
  6. jdog5000

    jdog5000 Revolutionary

    Joined:
    Nov 25, 2003
    Messages:
    2,601
    Location:
    California
  7. jdog5000

    jdog5000 Revolutionary

    Joined:
    Nov 25, 2003
    Messages:
    2,601
    Location:
    California
    Version 1.2 has been posted here at CFC!

    Version 1.20 changes:
    Spoiler :

    - CvUnit::canSpread - Moved Python cannot spread callback to end of function where it belongs, will speed up those mods which use this callback a little
    - CvPlayerAI::AI_missionaryValue - Fixed copy and past bug causing overvaluation of missionaries for AIs going for cultural victory early in the game.
    - CvGameTextMgr (many places) - Fixed issues where unhappiness and unhealthiness from civics or buildings would incorrectly show up as -(unhappy face) instead of +(unhappy face) in several circumstances. (Thanks EmporerFool, Grave, Afforess)
    - CvGameTextMgr - Game will now properly display info for buildings which generate unhappiness in an area or globally, or produce state religion unhappiness (should these ever come up in mods)
    - CvPlayerAI::AI_doTurnPost and CvPlayerAI::AI_doTurnUnitsPost - Added in accidentally skipped fix for AI_doSplit issues as suggested by alexman
    - CvTeamAI::AI_calculateAreaAIType - Fixed incorrect index usage (thanks cephalo)
    - CvCity::popOrder - Fixed issue with improper use of iExtra causing national wonders to max out early in some mods (thanks davidlallen)
    - CvTeam::addTeam - Fixed bug where, if civs A and B join in a permanent alliance, they get the max of A and B's espionage points against C but C just keeps its point against A and loses its points to B if that's higher
    - CvUnit::canMoveInto - Removed strange behavior where setting a unit to be unable to enter a terrain type would be overridden by features (forrest, fallout) (thanks TC01)
    - CvCityAI::AI_chooseProduction - Fixed bug reducing AI production of workers, and a similar issue for barb players producing too many
     
  8. Munch

    Munch Benevolent Despot

    Joined:
    May 25, 2006
    Messages:
    2,081
    Stupid question ... I've just patched to 3.19 and installed Better AI 0.81. Do I need to get this unofficial patch or is everything I need already in the Better AI mod? Cheers!
     
  9. MadmanAtW

    MadmanAtW Knight

    Joined:
    Apr 13, 2008
    Messages:
    579
    Location:
    San Leandro, CA
    Better AI includes the unofficial patch, so you're all set.
     
  10. Munch

    Munch Benevolent Despot

    Joined:
    May 25, 2006
    Messages:
    2,081
    Appreciate it, thanks.
     
  11. Afforess

    Afforess The White Wizard

    Joined:
    Jul 31, 2007
    Messages:
    12,239
    Location:
    Austin, Texas
    Jdog5000, I've found the cause of a rare-ish CTD, and a possible fix for it. In CvPlayerAI.cpp, in the function "TechTypes CvPlayerAI::AI_bestTech(int iMaxPathLength, bool bIgnoreCost, bool bAsync, TechTypes eIgnoreTech, AdvisorTypes eIgnoreAdvisor) const" There is a section where in rare instances, the formula divides by 0.

    The code in question is this section:
    Code:
    int iNewCapacity = kLoopUnit.getMoves() * kLoopUnit.getCargoSpace();
    int iOldCapacity = GC.getUnitInfo(eExistingUnit).getMoves() * GC.getUnitInfo(eExistingUnit).getCargoSpace();
    [B]iAssaultValue += (800 * (iNewCapacity - iOldCapacity)) / iOldCapacity;[/B]
    In Vanilla BTS, the iOldCapacity is never 0, but in Rise of Mankind (and possibly other mods), there is a promotion that adds an extra cargo space to ships, even to ships without preexisting cargo space. If the AI gave this promotion to a ship without cargo space, the iOldCapacity would be 0, and the function would divide by 0. I fixed this by changing that segment of code into this:
    Code:
    int iNewCapacity = kLoopUnit.getMoves() * kLoopUnit.getCargoSpace();
    int iOldCapacity = GC.getUnitInfo(eExistingUnit).getMoves() * GC.getUnitInfo(eExistingUnit).getCargoSpace();
    [B]if (iOldCapacity <= 0)
    {
    	iAssaultValue += (600 * iNewCapacity);
    }[/B]
    [B]else[/B]
    {
    	iAssaultValue += (800 * (iNewCapacity - iOldCapacity)) / iOldCapacity;
    }
    That fixed the CTD and allow me to go to the next turn. I would appreciate it if this fix made it into the next UP.
     
  12. jdog5000

    jdog5000 Revolutionary

    Joined:
    Nov 25, 2003
    Messages:
    2,601
    Location:
    California
    Man, I love when people find hidden problems like this AND propose a good solution.

    Thanks Afforess!
     
  13. EmperorFool

    EmperorFool Deity

    Joined:
    Mar 2, 2007
    Messages:
    9,633
    Location:
    Mountain View, California
    In looking in the SDK for where exactly the cityAcquiredAndKept event is fired, I found another place where the active player is passed instead of the new owner of the city. That got me thinking: how exactly are modders using the ePlayer parameter passed to the event?

    The cityAcquired event takes a player called eOldOwner. That's nice and descriptive. The AndKept event takes a player called iPlayer. Lovely!

    CvPlayerAI::AI_conquerCity() was changed at the end to pass in getID() instead of the active player:

    Code:
    	if (!bRaze)
    	{
    // BUG - Unofficial Patch - start
    		// EF: was passing getActivePlayer()
    		CvEventReporter::getInstance().cityAcquiredAndKept([B]getID()[/B], pCity);
    // BUG - Unofficial Patch - end
    	}
    
    I don't remember if this is in the UP or just BULL, but here's the other place I found it using the active player: when the popup asking if you want to keep or raze the city appears, sometimes there is the option to liberate it. In that case, CvButtonPopup handles firing the event (lame). Here's the fix:

    Code:
    		else if (pPopupReturn->getButtonClicked() == 2)
    		{
    			CvCity* pCity = GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getCity(info.getData1());
    			if (NULL != pCity)
    			{
    // BUG - Unofficial Patch - start
    				// EF: was passing getActivePlayer()
    				CvEventReporter::getInstance().cityAcquiredAndKept([B](PlayerTypes)info.getData2()[/B], pCity);
    // BUG - Unofficial Patch - end
    			}
    
    			CvMessageControl::getInstance().sendDoTask(info.getData1(), TASK_GIFT, info.getData2(), -1, false, false, false, false);
    		}
    
    I've checked all other calls to CvEventReporter::cityAcquiredAndKept(), and they seem to be passing the appropriate player.
     
  14. EmperorFool

    EmperorFool Deity

    Joined:
    Mar 2, 2007
    Messages:
    9,633
    Location:
    Mountain View, California
    When you hover over a player you see whom they are the worst enemy of. This fix hides those haters if you haven't met them.

    Code:
    void CvGameTextMgr::getOtherRelationsString(CvWStringBuffer& szString, PlayerTypes eThisPlayer, PlayerTypes eOtherPlayer)
    {
    	...
    			if (kTeam.isHasMet(kOtherPlayer.getTeam()))
    			{
    				if (::atWar((TeamTypes) iTeam, kThisPlayer.getTeam()))
    				{
    					szString.append(NEWLINE);
    					szString.append(gDLL->getText(L"TXT_KEY_AT_WAR_WITH", kTeam.getName().GetCString()));
    				}
    
    // BUG - Unofficial Patch - start
    				// EF: don't show enemies that active player hasn't met
    				if (!kTeam.isHuman() && kTeam.AI_getWorstEnemy() == kThisPlayer.getTeam() [B]&& kTeam.isHasMet(GC.getGameINLINE().getActiveTeam())[/B])
    // BUG - Unofficial Patch - end
    				{
    					szString.append(NEWLINE);
    					szString.append(gDLL->getText(L"TXT_KEY_WORST_ENEMY_OF", kTeam.getName().GetCString()));
    				}
    			}
    
    I just wrote this but haven't tested it yet. I'll post again once I've had a chance to test.
     
  15. jdog5000

    jdog5000 Revolutionary

    Joined:
    Nov 25, 2003
    Messages:
    2,601
    Location:
    California
    Hmmm ... I'm not sure about this one. Here's the current chain of events:

    1) Human player captures a city
    2) Event fires saying human acquired city
    3) Human player selects to liberate city to player X
    4) Event fires saying human acquired and kept city
    5) Player X is given city in trade from human player
    6) Event fires saying that Player X acquired city (not acquired and kept since they have no option to raze it)

    That seems right to me.
     
  16. EmperorFool

    EmperorFool Deity

    Joined:
    Mar 2, 2007
    Messages:
    9,633
    Location:
    Mountain View, California
    Yeah, I'm looking into this further. There are six places where the cityAcquiredAndKept event is fired. See this post for the list. I'll verify that the events are fired again after the liberation. If so, what you say makes sense.
     
  17. EmperorFool

    EmperorFool Deity

    Joined:
    Mar 2, 2007
    Messages:
    9,633
    Location:
    Mountain View, California
    So the CityAcquired and CityAcquiredAndKept events are fired twice each during liberation-via-conquest. I retract my latest fix request.
     
  18. Afforess

    Afforess The White Wizard

    Joined:
    Jul 31, 2007
    Messages:
    12,239
    Location:
    Austin, Texas
    On the latest UP code, in the SVN (The RevDCM SVN, but it might be in others too), you made a slight error. In CvGameTextMgr.cpp

    this:

    Code:
    /*************************************************************************************************/
    /** UNOFFICIAL_PATCH                       08/28/09                            jdog5000          */
    /**                                                                                              */
    /** Bugfix                                                                                       */
    /*************************************************************************************************/
    /* original bts code
    		szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_UNIT_HAPPINESS", GC.getCivicInfo(eCivic).getHappyPerMilitaryUnit(), ((GC.getCivicInfo(eCivic).getHappyPerMilitaryUnit() > 0) ? gDLL->getSymbolID(HAPPY_CHAR) : gDLL->getSymbolID(UNHAPPY_CHAR))));
    
    */
    		// Use absolute value with unhappy face
    		szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_UNIT_HAPPINESS", abs(GC.getCivicInfo(eCivic).getHappyPerMilitaryUnit()), ((GC.getCivicInfo(eCivic).getHappyPerMilitaryUnit() > 0) ? gDLL->getSymbolID(HAPPY_CHAR) : gDLL->getSymbolID(UNHAPPY_CHAR))));
    /*************************************************************************************************/
    /** UNOFFICIAL_PATCH                        END                                                  */
    /*************************************************************************************************/
    
    should look like this:

    Code:
    	//	Happiness per military unit
    	if (GC.getCivicInfo(eCivic).getHappyPerMilitaryUnit() != 0)
    	{
    		szHelpText.append(NEWLINE);
    /*************************************************************************************************/
    /** UNOFFICIAL_PATCH                       08/28/09                            jdog5000          */
    /**                                                                                              */
    /** Bugfix                                                                                       */
    /*************************************************************************************************/
    /* original bts code
    		szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_UNIT_HAPPINESS", GC.getCivicInfo(eCivic).getHappyPerMilitaryUnit(), ((GC.getCivicInfo(eCivic).getHappyPerMilitaryUnit() > 0) ? gDLL->getSymbolID(HAPPY_CHAR) : gDLL->getSymbolID(UNHAPPY_CHAR))));
    
    */
    		// Use absolute value with unhappy face
    
    		szHelpText.append(gDLL->getText("TXT_KEY_CIVIC_UNIT_HAPPINESS", abs(GC.getCivicInfo(eCivic).getHappyPerMilitaryUnit()), ((GC.getCivicInfo(eCivic).getHappyPerMilitaryUnit() > 0) ? gDLL->getSymbolID(HAPPY_CHAR) : gDLL->getSymbolID(UNHAPPY_CHAR))));
    
    /*************************************************************************************************/
    /** UNOFFICIAL_PATCH                        END                                                  */
    /*************************************************************************************************/
    	}
    
    Otherwise, every civic on the civic screen shows 0 unhappiness for each military troop. It's a simple error. You accidentally clipped off the condition.
     
  19. jdog5000

    jdog5000 Revolutionary

    Joined:
    Nov 25, 2003
    Messages:
    2,601
    Location:
    California
    Looks like that was only an issue in RevDCM ... thanks!
     
  20. Arian

    Arian No more ghostbusting!!

    Joined:
    May 10, 2008
    Messages:
    2,088
    Location:
    The Netherlands
    @jdog:

    I see there's a small change in CvPlayer.cpp which isn't mentioned in the changelog:

    UP1.1 (line 1045) reads:

    PROFILE_FUNC();

    while UP1.2 reads:

    //PROFILE_FUNC();

    What does this change do?
     

Share This Page