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

[BNW] [HELP] Adding War Weariness like in Civ VI

Discussion in 'Civ5 - SDK / LUA' started by Harkodos, Apr 4, 2019.

  1. Harkodos

    Harkodos Warlord

    Joined:
    Feb 9, 2016
    Messages:
    178
    Hello all, I'm currently working on a Mod where one of the features implemented is adding in a War Weariness-like effect ala-Civ VI. It's sort of working, but also not, so I decided to come here and see if anyone could potentially help fix it up proper.

    There are two parts to this code:
    Code:
    local iAtWarTurns = 0
    
    function AtWarCheck(iPlayer)
        local pPlayer = Players[iPlayer];
        if pPlayer:IsAlive() then
            local pTheirCapital = pPlayer:GetCapitalCity()
            pTheirCapital:SetNumRealBuilding(GameInfoTypes["BUILDING_HK_RCY_AT_WAR_DUMMYBUILDING"], ((Teams[pPlayer:GetTeam()]:GetAtWarCount(true) > 0) and 1 or 0))
            iAtWarTurns = iAtWarTurns + 1;
        end
    end
    GameEvents.PlayerDoTurn.Add(AtWarCheck)
    This code checks to see whether or not the player is at War and then adds a +1 to an ongoing counter. This seems to be buggy, but more on that with the next code snippet:
    Code:
    local iWarWeariness = 0
    
    function WarWearyCitizens(PlayerID, cityID)
        local pPlayer = Players[PlayerID];
        local iCities = pPlayer:GetNumCities();
        local pTheirCapital = pPlayer:GetCapitalCity()
        if pPlayer:IsAlive() then
            if iCities > 1 then
                if pPlayer:GetCivilizationType() == CIVILIZATION_HUNS then -- Checking for The Huns
                    for pCity in pPlayer:Cities() do
                        if (pCity:GetNumBuilding(GameInfoTypes["BUILDING_HK_RCY_AT_WAR_DUMMYBUILDING"]) > 0) then
                            local strCityName = pCity:GetName();  
                            print("Spawning War Weariness Dummybuilding in " .. strCityName)
                            iWarWeariness = (iWarWeariness + iAtWarTurns) / 10 + 1
                            pTheirCapital:SetNumRealBuilding(GameInfoTypes["BUILDING_HK_RCY_WAR_WEARINESS_DUMMYBUILDING"], iWarWeariness);
                        else
                            if iWarWeariness >= 2 then
                                iWarWeariness = iWarWeariness - 2
                                pTheirCapital:SetNumRealBuilding(GameInfoTypes["BUILDING_HK_RCY_WAR_WEARINESS_DUMMYBUILDING"], iWarWeariness);
                            else
                                iWarWeariness = 0
                                pTheirCapital:SetNumRealBuilding(GameInfoTypes["BUILDING_HK_RCY_WAR_WEARINESS_DUMMYBUILDING"], iWarWeariness);
                            end
                        end  
                    end
                else -- Checking for everyone else
                    for pCity in pPlayer:Cities() do
                        if (pCity:GetNumBuilding(GameInfoTypes["BUILDING_HK_RCY_AT_WAR_DUMMYBUILDING"]) > 0) then
                            local strCityName = pCity:GetName();  
                            print("Spawning War Weariness Dummybuilding in " .. strCityName)
                            iWarWeariness = (iWarWeariness + iAtWarTurns) / 10 + 2
                            pTheirCapital:SetNumRealBuilding(GameInfoTypes["BUILDING_HK_RCY_WAR_WEARINESS_DUMMYBUILDING"], iWarWeariness);
                        else
                            if pPlayer:GetCivilizationType() == CIVILIZATION_DENMARK then -- Checking for Denmark
                                if iWarWeariness >= 4 then
                                    iWarWeariness = iWarWeariness - 4
                                    pTheirCapital:SetNumRealBuilding(GameInfoTypes["BUILDING_HK_RCY_WAR_WEARINESS_DUMMYBUILDING"], iWarWeariness);
                                else
                                    iWarWeariness = 0
                                    pTheirCapital:SetNumRealBuilding(GameInfoTypes["BUILDING_HK_RCY_WAR_WEARINESS_DUMMYBUILDING"], iWarWeariness);
                                end
                            else -- Checking for everyone else
                                if iWarWeariness >= 2 then
                                    iWarWeariness = iWarWeariness - 2
                                    pTheirCapital:SetNumRealBuilding(GameInfoTypes["BUILDING_HK_RCY_WAR_WEARINESS_DUMMYBUILDING"], iWarWeariness);
                                else
                                    iWarWeariness = 0
                                    pTheirCapital:SetNumRealBuilding(GameInfoTypes["BUILDING_HK_RCY_WAR_WEARINESS_DUMMYBUILDING"], iWarWeariness);
                                end
                            end
                        end  
                    end
                end
            else -- Don't accumulate more War Weariness because they've only got 1 City!
                for pCity in pPlayer:Cities() do
                    if (pCity:GetNumBuilding(GameInfoTypes["BUILDING_HK_RCY_AT_WAR_DUMMYBUILDING"]) > 0) then
                        local strCityName = pCity:GetName();  
                        print("Spawning War Weariness Dummybuilding in " .. strCityName)
                        iWarWeariness = iWarWeariness
                        pTheirCapital:SetNumRealBuilding(GameInfoTypes["BUILDING_HK_RCY_WAR_WEARINESS_DUMMYBUILDING"], iWarWeariness);
                    else
                        if pPlayer:GetCivilizationType() == CIVILIZATION_DENMARK then -- Checking for Denmark
                            if iWarWeariness >= 4 then
                                iWarWeariness = iWarWeariness - 4
                                pTheirCapital:SetNumRealBuilding(GameInfoTypes["BUILDING_HK_RCY_WAR_WEARINESS_DUMMYBUILDING"], iWarWeariness);
                            else
                                iWarWeariness = 0
                                pTheirCapital:SetNumRealBuilding(GameInfoTypes["BUILDING_HK_RCY_WAR_WEARINESS_DUMMYBUILDING"], iWarWeariness);
                            end
                        else -- Checking for everyone else
                            if iWarWeariness >= 2 then
                                iWarWeariness = iWarWeariness - 2
                                pTheirCapital:SetNumRealBuilding(GameInfoTypes["BUILDING_HK_RCY_WAR_WEARINESS_DUMMYBUILDING"], iWarWeariness);
                            else
                                iWarWeariness = 0
                                pTheirCapital:SetNumRealBuilding(GameInfoTypes["BUILDING_HK_RCY_WAR_WEARINESS_DUMMYBUILDING"], iWarWeariness);
                            end
                        end
                    end  
                end
            end
        end
    end
    GameEvents.PlayerDoTurn.Add(WarWearyCitizens);
    This code does several things. First it should add a number of War Weariness Dummybuildings to the player's Capital City based on numerous factors. It should add 2 Dummybuildings every turn (which each increase Unhappiness in non-occupied Cities by 5%, equaling a 10% increase), but getting that work has been irritating (for some reason it likes multiplying the right amount of buildings by 10). Also the Huns as a new addition to their UA should only receive 1 of these buildings per turn. Also, if a Civilization only has 1 City, then they should not receive additional War Weariness Dummybuildings (if they even have any accumulated). Finally, when a Civ is no longer at War, the number of War Weariness Dummybuildings should degrade at a rate of 2 per turn (4 per turn for Denmark, who have that added as a part of their UA).

    The above code does work for a few of these variables, but the coding I've had to use to implement it has been clunky, such as having to divide any values input by 10 (the counter that adds +1 each turn seems to be a culprit, but without that, the code just adds a base 2 War Weariness Dummybuildings and then never bothers again afterward, even though with my understanding, it should continue to add these buildings). Also, the code does not want to retain any of the War Weariness Dummybuildings when the player has returned to Peace, so that code does nothing at present.

    -EDIT-
    Upon further thought into the subject, I deduced that the need to divide certain values by 10 resulted from the code being called whenever a player (not just the human player) took their turn. The 10 is a direct result from there being 4 civilizations and 6 city-states whenever I was testing the mod for bugs.

    If anyone could help me rework this code so that it operates as desired, I'd be very grateful.
     
    Last edited: Apr 5, 2019
  2. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    6,451
    Location:
    Illinois, USA
    1. It's been long enough that I cannot remember whether the Team:GetAtWarCount(true) method will also ignore Barbarians
    2. Since PlayerDoTurn executes for every player in the game, including City-States and Barbarians, your variable iAtWarTurns is incremented by +1 for every player in the game who is still alive, including city-states and barbarians.
    3. PlayerDoTurn events don't fire for players that have been eliminated from the game, so this conditional doesn't do anything for you
      Code:
      if pPlayer:IsAlive() then
    4. I would redraft to account for and track each player individually and I would do so by the "BUILDING_HK_RCY_AT_WAR_DUMMYBUILDING" rather than an lua variable
    5. If "BUILDING_HK_RCY_AT_WAR_DUMMYBUILDING" has any actual in-game effects I would re-write its XML code so that all it does is act as a counter
    6. Taking these two things into account I would re-draft the first function as:
      Code:
      local iWarBuildingDummy = GameInfoTypes["BUILDING_HK_RCY_AT_WAR_DUMMYBUILDING"]
      
      function AtWarCheck(iPlayer)
      	local pPlayer = Players[iPlayer];
      	if (pPlayer:IsBarbarian() == false) and (pPlayer:IsMinorCiv() == false) then
      		local pTheirCapital = pPlayer:GetCapitalCity()
      		if pTheirCapital ~= nil then
      			local iNumCurrentDummy = pTheirCapital:GetNumRealBuilding(iWarBuildingDummy)
      			if (Teams[pPlayer:GetTeam()]:GetAtWarCount(true) > 0) then
      				pTheirCapital:SetNumRealBuilding(iWarBuildingDummy, iNumCurrentDummy + 1)
      			else
      				if (iNumCurrentDummy > 0) then
      					pTheirCapital:SetNumRealBuilding(iWarBuildingDummy, 0)
      				end
      				--note that you could also do a slow cool-down like pTheirCapital:SetNumRealBuilding(iWarBuildingDummy, iNumCurrentDummy - 1)
      			end
      		end
      	end
      end
      GameEvents.PlayerDoTurn.Add(AtWarCheck)
    7. You don't need to worry about issues of game-saving and reloading saved games because the dummy building now acts as the data for how many turns a player has been at war
    8. However, this still leaves the issue of city-capture in cases where a player loses their capital city.
    It's getting late enough I'll have to leave advice at that for tonight and try to remember to look back on this thread when I get home from work tomorrow.
     
  3. Harkodos

    Harkodos Warlord

    Joined:
    Feb 9, 2016
    Messages:
    178
    Ahhh, after the few days that I hadn't received any replies, I had kind of already given up on that method and just changed it to a flat modifier. Though I can say this is a pleasant surprise! I may have to rework what I have now to use this instead, but even if I don't use it for this, the code you've provided may work nicely elsewhere.

    I thank you good sir!
     

Share This Page