Increasing Strategic Resources when a Building is Completed

sman1975

Emperor
Joined
Aug 27, 2016
Messages
1,370
Location
Dallas, TX
Greetings,

Here is a bit of a headache in a mod I'm working on at the moment. Situation:

1. A player can construct a "Foundry" building - which provides 2 units of Iron.
2. The player later builds the "Ironworks" national wonder.
3. Would like for the existing Foundry buildings to now provide 4 units of Iron, i.e. change the number of strategic resources these Foundries provide - for both current and future built Foundries.

Have played around with several possible solutions, but always seem to have problems - what happens when selling the building, can't set arbitrary resource amounts, etc. After several hours my brain is just fried.

Appreciate it.
 
Assuming that you're using BNW, make a dummy building separate from the foundry that gives 2 extra iron (let's call it BUILDING_FOUNDRY_DUMMY), and then use this Lua:

Code:
GameEvents.CityConstructed.Add(
function(iPlayer, iCity, iBuilding)
    local pPlayer = Players[iPlayer]
    if (iBuilding == GameInfoTypes.BUILDING_IRONWORKS) then
        for pCity in pPlayer:Cities() do
            if (pCity:IsHasBuilding(iBuilding) == true) then
                pCity:SetNumRealBuilding(iBuilding, 1)
            end
        end
    elseif (iBuilding == GameInfoTypes.BUILDING_FOUNDRY) then
        pPlayer:GetCityByID(iCity):SetNumRealBuilding(iBuilding, 1)
    else return end
end)

GameEvents.CitySoldBuilding.Add(
function(iPlayer, iCity, iBuilding)
    local pPlayer = Players[iPlayer]
    if (iBuilding == GameInfoTypes.BUILDING_IRONWORKS) then
        if (pPlayer:CountNumBuildings(iBuilding) < 1) then
            for pCity in pPlayer:Cities() do
                pCity:SetNumRealBuilding(GameInfoTypes.BUILDING_FOUNDRY_DUMMY, 0)
            end
        end
    elseif (iBuilding == GameInfoTypes.BUILDING_FOUNDRY) then
        pPlayer:GetCityByID(iCity):SetNumRealBuilding(iBuilding, 0)
    else return end
end)

Note that this code only removes the dummy building if the Ironworks or foundy is sold, but not by any other means - although it could easily be expanded or repurposed to remove the dummy building under all circumstances.

Out of curiosity, what have you tried so far that hasn't worked?
 
Thanks AW! I used Iron as an example for ease of explanation. What I'm actually doing is adding a new strat resource (Camels!), that initially were created when a certain building (Camel Market) was created. After the building of a new national wonder (Souk al Jamal), the Camel Market which originally provided 2 Camels now were supposed to provide 4. Am using buildings initially to create the resource, then when/if I get time later, to create a new model to add Camels to the map like other strat resources.

I was using LUA to manually control the number of strat resources by getting the number of Camel Markets, checking for the existence of the Souk, then adjusting the numbers available. Then I checked on the number of units in existence, then decremented the numbers accordingly. This worked fine, but the TopPanel number was always wrong.

After a couple of hours messing with that with no success, I experimented with adding a dummy policy and a dummy technology, ReplacementBuildingClass, and a few other tweaks but quickly saw this couldn't safely/properly manage the resource number. I could adjust Yields when the Souk was built with no problems, but not resources.

I toyed around using dummy buildings, but wasn't sure how to handle the "build/delete/rebuild" and "what happens if city with Ironworks is destroyed" problem - which it looks like your code tackles. I suppose I was crawling towards your solution's direction yesterday, but after about 6 hours of spitballing with no success, I just gave up, and cried for help like a little.... Well, anyway...
 
logic error here:
Code:
GameEvents.CityConstructed.Add(
function(iPlayer, iCity, iBuilding)
    local pPlayer = Players[iPlayer]
    if (iBuilding == GameInfoTypes.BUILDING_IRONWORKS) then
        for pCity in pPlayer:Cities() do
            if (pCity:IsHasBuilding(iBuilding) == true) then
                pCity:SetNumRealBuilding(iBuilding, 1)
            end
        end
    elseif (iBuilding == GameInfoTypes.BUILDING_FOUNDRY) then
        pPlayer:GetCityByID(iCity):SetNumRealBuilding(iBuilding, 1)
    else return end
end)
  1. When either of BUILDING_IRONWORKS or BUILDING_FOUNDRY is constructed in a city, the code will simply set the number of these buildings in the city to 1, which the city already has.
  2. Once the error with reusing variable iBuilding for both the just-constructed building as well as the dummy building is corrected, when the BUILDING_IRONWORKS is constructed, only its city will get the dummy added. No other city with a foundry will get the dummy building.
  3. Whenever a Foundry is created by any player, they will get the dummy in that city because there is no check in this case for whether or not the player has BUILDING_IRONWORKS constructed anywhere.

As insurance I would likely add a PlayerDoTurn to run through all the player's cities and cure or clean up any outstanding issues with regards to having the wrong building in a city. This would also tend to cure the issues regarding city capture.
 
Last edited:
Code:
local iIronWorks = GameInfoTypes.BUILDING_IRONWORKS
local iFoundry = GameInfoTypes.BUILDING_FOUNDRY
local iTwoMoreIron = GameInfoTypes.BUILDING_FOUNDRY_DUMMY

function GiveAStrategicFromNationalWonders(iPlayer, iCity, iBuilding)
    local pPlayer = Players[iPlayer]
    if (iBuilding == iIronWorks) then
        for pCity in pPlayer:Cities() do
            if pCity:IsHasBuilding(iFoundry) then
                pCity:SetNumRealBuilding(iTwoMoreIron, 1)
            end
        end
    elseif (iBuilding == iFoundry) then
	if (pPlayer:CountNumBuildings(iIronWorks) > 0) then
        	pPlayer:GetCityByID(iCity):SetNumRealBuilding(iTwoMoreIron, 1)
	end
    else return end
end
GameEvents.CityConstructed.Add(GiveAStrategicFromNationalWonders)
 
Code:
local tNationalWonderStrategics = {
[GameInfoTypes.BUILDING_IRONWORKS] = {Building = GameInfoTypes.BUILDING_FOUNDRY, Dummy = GameInfoTypes.BUILDING_FOUNDRY_DUMMY},
[GameInfoTypes.BUILDING_WEST_POINT] = {Building = GameInfoTypes.BUILDING_MILITARY_ACADEMY, Dummy = GameInfoTypes.BUILDING_MILITARY_ACADEMY_DUMMY}
}
-------------------------------------------------------------------------------
-- no changes from here
-------------------------------------------------------------------------------
local tNormalBuildings = {}
for iNationalWonder,DataTable in pairs(tNationalWonderStrategics) do
	tNormalBuildings[DataTable.Building] = {NationalWonder = iNationalWonder, Dummy = DataTable.Dummy }
end

function GiveAStrategicFromNationalWonders(iPlayer, iCity, iBuilding)
    local pPlayer = Players[iPlayer]
    if tNationalWonderStrategics[iBuilding] then
        for pCity in pPlayer:Cities() do
            if pCity:IsHasBuilding(tNationalWonderStrategics[iBuilding].Building) then
                pCity:SetNumRealBuilding(tNationalWonderStrategics[iBuilding].Dummy, 1)
            end
        end
    elseif tNormalBuildings[iBuilding] then
	if (pPlayer:CountNumBuildings(tNormalBuildings[iBuilding].NationalWonder) > 0) then
        	pPlayer:GetCityByID(iCity):SetNumRealBuilding(tNormalBuildings[iBuilding].Dummy, 1)
	end
    else return end
end
GameEvents.CityConstructed.Add(GiveAStrategicFromNationalWonders)
This version sets up a table with corresponds between the National Wonder, the "real" building, and the "dummy" building.

I just used the foundry example AW was using, and added an example for a West Point and Military Academy set to show how the table being expanded is automatically accounted for in the rest of the code.

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

It also is not written to handle unique replacements for the "real" building, but could be expanded to account for that by stating BUILDINGCLASS here
Code:
Building = GameInfoTypes.BUILDING_FOUNDRY
And then having the code run through all buildings that are correct for that BUILDINGCLASS and adding them to a new master table which is then used instead of the one in the example. And the table tNormalBuildings would then be re-structured in its construction to account for these unique replacements as well.
 
Top Bottom