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

Harkodos

Warlord
Joined
Feb 9, 2016
Messages
195
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:
  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.
 
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!
 
Top Bottom