• We are currently performing site maintenance, parts of civfanatics are currently offline, but will come back online in the coming days. For more updates please see here.

Custom Aqueduct For Tradition

legojoshua12

Chieftain
Joined
Apr 19, 2018
Messages
13
Hi, I am trying to make my custom aqueduct called a bridge work with the tradition policy. For some reason though, it is made on the culture building and not the tradition finisher. My code for replacing the aqueduct is here but doesn't seem to work. Is there a table I missed for replacing the aqueduct that would make this easier or is there a way to make my code work?

Code:
function CheckAqueductsInOregon(iPlayer, iPolicyID)
    local pPlayer = Players[iPlayer]
    if (pPlayer:GetCivilizationType() == CIVILIZATION_OREGON) then
        for pCity in pPlayer:Cities() do
            if (iPolicyID == GameInfos.Policies.POLICY_TRADITION_FINISHER.ID) then
                pCity:SetNumRealBuilding(BUILDING_AQUEDUCT, 0);
                pCity:SetNumRealBuilding(BUILDING_CITY_BRIDGE, 0);
            end
        end
    end
end
 
You need to make the City Bridge a unique building for the Oregon civ - see my "Unique Building - Cistern" mod for an example
 
I made the oregon bridge already, and after checking through your cistern example, it does not actually work. I want the bridge to replace the aqueduct when you adopt the tradition finisher. In your example and my code as well, the finisher to tradition gives an aqueduct, regardless of the unique building.
 
Code:
function CheckAqueductsInOregon(iPlayer, iPolicyID)
    local pPlayer = Players[iPlayer]
    if (pPlayer:GetCivilizationType() == CIVILIZATION_OREGON) then
        for pCity in pPlayer:Cities() do
            if (iPolicyID == GameInfos.Policies.POLICY_TRADITION_FINISHER.ID) then
                pCity:SetNumRealBuilding(BUILDING_AQUEDUCT, 0);
                pCity:SetNumRealBuilding(BUILDING_CITY_BRIDGE, 0);
            end
        end
    end
end
Unless you are defining CIVILIZATION_OREGON, BUILDING_AQUEDUCT, and BUILDING_CITY_BRIDGE as lua variables elsewhere in your code, your lua does not work because the game's lua system does not work off of XML tag-names. So for pPlayer:GetCivilizationType()
Code:
 (pPlayer:GetCivilizationType() == CIVILIZATION_OREGON)
will always evaluate to being a false statement since pPlayer:GetCivilizationType() returns an integer value and CIVILIZATION_OREGON would be interpretted as being an undefined lua variable. Undefined lua variables are always assigned a value of "nil". "nil" can never be equal to an integer value. You want
Code:
(pPlayer:GetCivilizationType() == GameInfoTypes.CIVILIZATION_OREGON)
GameInfoTypes.CIVILIZATION_OREGON grabs the proper integer ID # for CIVILIZATION_OREGON from the <Civilizations> table, which is what the lua method pPlayer:GetCivilizationType() grabs for the given player (ie, the ID # from table <Civilizations> that is being used by "pPlayer").

For pCity:SetNumRealBuilding(iBuildingID, iNumberBuildings) you want
Code:
                pCity:SetNumRealBuilding(GameInfoTypes.BUILDING_AQUEDUCT, 0);
                pCity:SetNumRealBuilding(GameInfoTypes.BUILDING_CITY_BRIDGE, 1);
You need the integer '1' in the second pCity:SetNumRealBuilding(args) line in order to add the desired building to the city. '0' removes the Building, whether it was already present in the city or not.

You also need to ensure that if BUILDING_CITY_BRIDGE is defined as belonging to the BUILDINGCLASS_AQUEDUCT class of buildings, that none of the column-settings you are using within that database definition of the building will be refused by the game when BUILDING_CITY_BRIDGE is not defined as a unique replacement for BUILDINGCLASS_AQUEDUCT for CIVILIZATION_OREGON . See the link in my sig re Dummy Buildings & Building-Class Structure Issues. The issues re replacement buildings not defined as belonging to a particular civilization apply regardless of whether or not a building is a dummy.

Also, if function CheckAqueductsInOregon is hooked as a listener to PlayerAdoptPolicy, you will never get this line to be evaluated as true
Code:
 if (iPolicyID == GameInfos.Policies.POLICY_TRADITION_FINISHER.ID) then
From some old documentation I had laying around:
Like Policy Branch Openers, the GameEvents.PlayerAdoptPolicy(PlayerID, policyID) does not fire for the free policy given for finishing a policy branch.
Even if it did, you'd never get the line to be evaluated as "true" since you need "GameInfo" instead of "GameInfos"

----------------------------

And as I recall (perhaps not quite correctly) the issue with the Aqueduct not being replaced with a unique replacement by the game engine had to do with the <FoodKept> column and the game looking for the building with the highest setting of <FoodKept>.
 
Last edited:
Code:
function CheckAqueductsInOregon(iPlayer, iPolicyID)
    local pPlayer = Players[iPlayer]
    if (pPlayer:GetCivilizationType() == CIVILIZATION_OREGON) then
        for pCity in pPlayer:Cities() do
            if (iPolicyID == GameInfos.Policies.POLICY_TRADITION_FINISHER.ID) then
                pCity:SetNumRealBuilding(BUILDING_AQUEDUCT, 0);
                pCity:SetNumRealBuilding(BUILDING_CITY_BRIDGE, 0);
            end
        end
    end
end
Unless you are defining CIVILIZATION_OREGON, BUILDING_AQUEDUCT, and BUILDING_CITY_BRIDGE as lua variables elsewhere in your code, your lua does not work because the game's lua system does not work off of XML tag-names. So for pPlayer:GetCivilizationType()
Code:
 (pPlayer:GetCivilizationType() == CIVILIZATION_OREGON)
will always evaluate to being a false statement since pPlayer:GetCivilizationType() returns an integer value and CIVILIZATION_OREGON would be interpretted as being an undefined lua variable. Undefined lua variables are always assigned a value of "nil". "nil" can never be equal to an integer value. You want
Code:
(pPlayer:GetCivilizationType() == GameInfoTypes.CIVILIZATION_OREGON)
GameInfoTypes.CIVILIZATION_OREGON grabs the proper integer ID # for CIVILIZATION_OREGON from the <Civilizations> table, which is what the lua method pPlayer:GetCivilizationType() grabs for the given player (ie, the ID # from table <Civilizations> that is being used by "pPlayer").

For pCity:SetNumRealBuilding(iBuildingID, iNumberBuildings) you want
Code:
                pCity:SetNumRealBuilding(GameInfoTypes.BUILDING_AQUEDUCT, 0);
                pCity:SetNumRealBuilding(GameInfoTypes.BUILDING_CITY_BRIDGE, 1);
You need the integer '1' in the second pCity:SetNumRealBuilding(args) line in order to add the desired building to the city. '0' removes the Building, whether it was already present in the city or not.

You also need to ensure that if BUILDING_CITY_BRIDGE is defined as belonging to the BUILDINGCLASS_AQUEDUCT class of buildings, that none of the column-settings you are using within that database definition of the building will be refused by the game when BUILDING_CITY_BRIDGE is not defined as a unique replacement for BUILDINGCLASS_AQUEDUCT for CIVILIZATION_OREGON . See the link in my sig re Dummy Buildings & Building-Class Structure Issues. The issues re replacement buildings not defined as belonging to a particular civilization apply regardless of whether or not a building is a dummy.

Also, if function CheckAqueductsInOregon is hooked as a listener to PlayerAdoptPolicy, you will never get this line to be evaluated as true
Code:
 if (iPolicyID == GameInfos.Policies.POLICY_TRADITION_FINISHER.ID) then
From some old documentation I had laying around:Even if it did, you'd never get the line to be evaluated as "true" since you need "GameInfo" instead of "GameInfos"

----------------------------

And as I recall (perhaps not quite correctly) the issue with the Aqueduct not being replaced with a unique replacement by the game engine had to do with the <FoodKept> column and the game looking for the building with the highest setting of <FoodKept>.
I apologize if necrobumps aren't appreciated on this forum. I was able to get a rudimentary Lua script up to replace the Aqueduct with my Unique Building for my own mod.*

*The issue is that
XML:
pCity:SetNumRealBuilding(GameInfoTypes.BUILDING_AQUEDUCT, 0)
did not remove the Aqueducts (is it because they're free?), and
XML:
pCity:SetNumRealBuilding(GameInfoTypes.BUILDING_MY_BUILDING, 1)
only seems to give non-free copies of the Building. I've checked the modding wiki's Lua documentation and couldn't find any methods which could rectify these issues. Help would be greatly appreciated.

Also, you are correct in your assertion that the engine chooses what "Aqueduct" to grant for the Tradition finisher based on what has the highest
XML:
<FoodKept>
value. I was elated to try this and have it work flawlessly (at the expense of breaking the balance of the building), only to become horrified when testing and seeing my custom Building being granted to ALL Civs completing Tradition.
 
I encountered this problem few years ago with my Kalbids mod that has an Aqueduct UB.

A workaround you can use is to code an additional "subtraction" building, that is a building having the effects of your UB minus the effects of base Aqueduct.

Then you add a function that prevents your civ to build the aqueduct UB when there is already a free aqueduct in the city.
Code:
function Jar_AqueductFix(iPlayer, iCity, BuildingType)
    local pPlayer = Players[iPlayer]
    local pCity =    pPlayer:GetCityByID(iCity)
    if pPlayer:GetCivilizationType() == GameInfoTypes.CIVILIZATION_YOURCIV and BuildingType == GameInfoTypes.BUILDING_MY_BUILDING then
        if pCity:GetNumFreeBuilding(GameInfoTypes.BUILDING_AQUEDUCT) > 0 then
            return false
        end
    end
    return true
end
GameEvents.CityCanConstruct.Add(Jar_AqueductFix)

Then to cities with a free aqueduct you manually add the "subtraction" building (and remove any copy of the UB to avoid duplication)
Code:
function Jar_AqueductFix2(iPlayer)
    local pPlayer = Players[iPlayer]
    if (pPlayer:GetCivilizationType() == GameInfoTypes.CIVILIZATION_YOURCIV and pPlayer:IsAlive()) then
        for pCity in pPlayer:Cities() do            
            if pCity:GetNumFreeBuilding(GameInfoTypes.BUILDING_AQUEDUCT) > 0 and pCity:GetNumRealBuilding(GameInfoTypes.BUILDING_SUBTRACTION_BUILDING) < 1 then
                pCity:SetNumRealBuilding(GameInfoTypes.BUILDING_MY_BUILDING, 0)
                pCity:SetNumRealBuilding(GameInfoTypes.BUILDING_SUBTRACTION_BUILDING, 1)
            end
        end
    end
end
GameEvents.PlayerDoTurn.Add(Jar_AqueductFix2)

Important: the subtraction building should have its own buildingclass and needs to have Cost = -1 so it cannot be built by anyone.
 
Back
Top Bottom