[BNW] SQL Building to automatically change yields to all other x buildings?

ThanOscar

Chieftain
Joined
Feb 13, 2019
Messages
41
I'm trying to create a world wonder, and while i have all the effects i want and the art ready i wanted to give it a special effect, which would be to give +1 gold for every gold producing building (e.g market, bank) it would be extremely tedious to do by hand for each building so i remembered reading about sql and its benefits but i have no clue how the code works (don't know xml mechanics either, but i can still work with it), anyone has some examples? I looked into the sql for dummies thing but it doesnt help alot in this case, the closest i found was JFD's Topkapi palace in Enlightenment era, which adds +1 faith from every building which adds hp or defense to a city, but i can't quite understand how to modify this for my own use.
 
I think you'll need to use Lua for that effect. Try adding the code under this spoiler to a file:

Spoiler Chunk of Lua code :
Code:
-- replace BUILDING_TO_GOLD_WONDER with the tag of your wonder
local iNewWonder = GameInfoTypes.BUILDING_TO_GOLD_WONDER

-- add this to the database as a dummy building that yields 1 Gold
local iGoldDummy = GameInfoTypes.BUILDING_TO_GOLD_DUMMY

local tGoldBuildings = {}
local iTableNum = 0
for row in DB.Query("SELECT BuildingType FROM Building_YieldChanges WHERE YieldType = 'YIELD_GOLD' UNION SELECT BuildingType FROM Building_ResourceYieldChanges WHERE YieldType = 'YIELD_GOLD' UNION SELECT BuildingType FROM Building_SeaResourceYieldChanges WHERE YieldType = 'YIELD_GOLD'") do
    tGoldBuildings[iTableNum] = row.BuildingType
    iTableNum = iTableNum + 1
end

function WonderIncreasesGold(playerID)
    local pPlayer = Players[playerID]
    if pPlayer:IsAlive() and pPlayer:CountNumBuildings(iNewWonder) > 0 then
        for cCity in pPlayer:Cities() do
            local iNumDummies = 0
            if cCity:IsHasBuilding(iNewWonder) then
                for k, vBuilding in pairs(tGoldBuildings) do
                    if cCity:IsHasBuilding(vBuilding) then
                        iNumDummies = iNumDummies + 1
                    end
                end
            end
            cCity:SetNumRealBuilding(iGoldDummy, iNumDummies)
        end
    end
end

GameEvents.PlayerDoTurn.Add(WonderIncreasesGold)

This code is meant to first create a table of all the Gold-producing buildings in the game, then to run the WonderIncreasesGold function each turn; that function checks to see if the player has the Wonder you're adding, and if so it'll give you Gold for each Gold-producing building in the Wonder's city.[1] I use dummy buildings to grant the actual Gold, since that will show up on the top panel, while just granting the gold with Lua won't.

[1]: If you want the effect to apply to all cities in your empire, remove the line "if cCity:IsHasBuilding(iNewWonder) then" and its corresponding end statement.
 
Code:
<Building_BuildingClassYieldChanges>
	<Row>
		<BuildingType>BUILDING_WONDER_X</BuildingType>
		<BuildingClassType>BUILDINGCLASS_MARKET</BuildingClassType>
		<YieldType>YIELD_GOLD</YieldType>
		<YieldChange>1</YieldChange>
	</Row>
	<Row>
		<BuildingType>BUILDING_WONDER_X</BuildingType>
		<BuildingClassType>BUILDINGCLASS_BANK</BuildingClassType>
		<YieldType>YIELD_GOLD</YieldType>
		<YieldChange>1</YieldChange>
	</Row>
	<Row>
		<BuildingType>BUILDING_WONDER_X</BuildingType>
		<BuildingClassType>BUILDINGCLASS_STOCK_EXCHANGE</BuildingClassType>
		<YieldType>YIELD_GOLD</YieldType>
		<YieldChange>1</YieldChange>
	</Row>
</Building_BuildingClassYieldChanges>
If you aren't attempting to also alter building-class inherent yields of building-classes that aren't part of the base-game, or that have buidings within the class that add a YIELD_GOLD to the various tables mentioned by TopHatPaladin, you don't need anything more complex.
 
Because I could :)

Code:
INSERT INTO Building_BuildingClassYieldChanges(BuildingType, BuildingClassType, YieldType, YieldChange)
    SELECT 'BUILDING_WONDER_X', bc.Type, 'YIELD_GOLD', 1 FROM (
        SELECT DISTINCT Type FROM BuildingClasses WHERE DefaultBuilding IN (
            SELECT BuildingType FROM Building_YieldChanges WHERE YieldType = 'YIELD_GOLD'
        ) AND MaxGlobalInstances = -1 AND MaxTeamInstances = -1 AND MaxPlayerInstances = -1
    ) AS bc;
 
Because I could :)
Code:
INSERT INTO Building_BuildingClassYieldChanges(BuildingType, BuildingClassType, YieldType, YieldChange)
    SELECT 'BUILDING_WONDER_X', bc.Type, 'YIELD_GOLD', 1 FROM (
        SELECT DISTINCT Type FROM BuildingClasses WHERE DefaultBuilding IN (
            SELECT BuildingType FROM Building_YieldChanges WHERE YieldType = 'YIELD_GOLD'
        ) AND MaxGlobalInstances = -1 AND MaxTeamInstances = -1 AND MaxPlayerInstances = -1
    ) AS bc;
Exactly what i meant, thank you a lot.
Code:
<Building_BuildingClassYieldChanges>
    <Row>
        <BuildingType>BUILDING_WONDER_X</BuildingType>
        <BuildingClassType>BUILDINGCLASS_MARKET</BuildingClassType>
        <YieldType>YIELD_GOLD</YieldType>
        <YieldChange>1</YieldChange>
    </Row>
    <Row>
        <BuildingType>BUILDING_WONDER_X</BuildingType>
        <BuildingClassType>BUILDINGCLASS_BANK</BuildingClassType>
        <YieldType>YIELD_GOLD</YieldType>
        <YieldChange>1</YieldChange>
    </Row>
    <Row>
        <BuildingType>BUILDING_WONDER_X</BuildingType>
        <BuildingClassType>BUILDINGCLASS_STOCK_EXCHANGE</BuildingClassType>
        <YieldType>YIELD_GOLD</YieldType>
        <YieldChange>1</YieldChange>
    </Row>
</Building_BuildingClassYieldChanges>
If you aren't attempting to also alter building-class inherent yields of building-classes that aren't part of the base-game, or that have buidings within the class that add a YIELD_GOLD to the various tables mentioned by TopHatPaladin, you don't need anything more complex.
Yes i apologize, i forgot to mention, i was fascinated by the way that it added yields automatically to buildings with x conditions, thanks for your time and your answer! =)

I think you'll need to use Lua for that effect. Try adding the code under this spoiler to a file:

Spoiler Chunk of Lua code :
Code:
-- replace BUILDING_TO_GOLD_WONDER with the tag of your wonder
local iNewWonder = GameInfoTypes.BUILDING_TO_GOLD_WONDER

-- add this to the database as a dummy building that yields 1 Gold
local iGoldDummy = GameInfoTypes.BUILDING_TO_GOLD_DUMMY

local tGoldBuildings = {}
local iTableNum = 0
for row in DB.Query("SELECT BuildingType FROM Building_YieldChanges WHERE YieldType = 'YIELD_GOLD' UNION SELECT BuildingType FROM Building_ResourceYieldChanges WHERE YieldType = 'YIELD_GOLD' UNION SELECT BuildingType FROM Building_SeaResourceYieldChanges WHERE YieldType = 'YIELD_GOLD'") do
    tGoldBuildings[iTableNum] = row.BuildingType
    iTableNum = iTableNum + 1
end

function WonderIncreasesGold(playerID)
    local pPlayer = Players[playerID]
    if pPlayer:IsAlive() and pPlayer:CountNumBuildings(iNewWonder) > 0 then
        for cCity in pPlayer:Cities() do
            local iNumDummies = 0
            if cCity:IsHasBuilding(iNewWonder) then
                for k, vBuilding in pairs(tGoldBuildings) do
                    if cCity:IsHasBuilding(vBuilding) then
                        iNumDummies = iNumDummies + 1
                    end
                end
            end
            cCity:SetNumRealBuilding(iGoldDummy, iNumDummies)
        end
    end
end

GameEvents.PlayerDoTurn.Add(WonderIncreasesGold)

This code is meant to first create a table of all the Gold-producing buildings in the game, then to run the WonderIncreasesGold function each turn; that function checks to see if the player has the Wonder you're adding, and if so it'll give you Gold for each Gold-producing building in the Wonder's city.[1] I use dummy buildings to grant the actual Gold, since that will show up on the top panel, while just granting the gold with Lua won't.

[1]: If you want the effect to apply to all cities in your empire, remove the line "if cCity:IsHasBuilding(iNewWonder) then" and its corresponding end statement.
Thanks for your reply, i will use the sql posted by whoward, but this code will surely be useful in the future, as i plan to create more buildings, and i'm learning lua so its a good example, thanks =)
 
Because I could :)

Code:
INSERT INTO Building_BuildingClassYieldChanges(BuildingType, BuildingClassType, YieldType, YieldChange)
    SELECT 'BUILDING_WONDER_X', bc.Type, 'YIELD_GOLD', 1 FROM (
        SELECT DISTINCT Type FROM BuildingClasses WHERE DefaultBuilding IN (
            SELECT BuildingType FROM Building_YieldChanges WHERE YieldType = 'YIELD_GOLD'
        ) AND MaxGlobalInstances = -1 AND MaxTeamInstances = -1 AND MaxPlayerInstances = -1
    ) AS bc;

hey, thanks for the code again, would this be correct for a trigger to catch all the new gold yielding buildings?
Code:
CREATE TRIGGER EmpireStateEffectChange
AFTER INSERT ON Building_YieldChanges
WHEN New.YieldType= 'YIELD_GOLD'
BEGIN
    INSERT INTO Building_BuildingClassYieldChanges(BuildingType, BuildingClassType, YieldType, YieldChange)
    VALUES  'BUILDING_EMPIRESTATE', New.BuildingClass, 'YIELD_GOLD', 1
END;
 
Yeah i had seen that, sql logic still evades me but i think its working, not sure how to test load order but i made a separate mod that made Granary give +1 gold and it gave +1 gold to granary so i guess it works?
Code:
CREATE TRIGGER EmpireStateEffectChange
AFTER INSERT ON Building_YieldChanges
WHEN New.YieldType= 'YIELD_GOLD'
BEGIN
    INSERT INTO Building_BuildingClassYieldChanges(BuildingType, BuildingClassType, YieldType, YieldChange)
    SELECT  'BUILDING_EMPIRESTATE', New.Type, 'YIELD_GOLD', 1 FROM (
    SELECT DISTINCT Type From BuildingClasses WHERE DefaultBuilding = 'New.BuildingType' )
END;

Edit: code above is wrong, load order in civ v is weird (??)
 
Last edited:
See https://forums.civfanatics.com/thre...d-order-issues-with-database-triggers.521961/

Then test it. Set up the trigger and then manually insert something into that table and see if you get the correct entry in the other
Hi sorry to bump this but can you help me more in detail?
It seemed to work initially but after assuming it worked it seems like the trigger fails to catch mods loaded after this one, but if i add something to the table in the same mod which has the trigger then it is detected and given +10 culture
Code:
INSERT INTO Policy_BuildingClassCultureChanges(PolicyType, BuildingClassType, CultureChange)
    SELECT 'POLICY_CULTURAL_CENTERS', bc.Type, 1 FROM (
        SELECT DISTINCT Type FROM BuildingClasses WHERE DefaultBuilding IN (
            SELECT BuildingType FROM Building_YieldChanges WHERE YieldType = 'YIELD_CULTURE'
        ) AND MaxGlobalInstances = -1 AND MaxPlayerInstances = -1
    ) AS bc;
   
CREATE TRIGGER PolicyCultureChange_Trigger
AFTER INSERT ON Building_YieldChanges
WHEN New.YieldType = 'YIELD_CULTURE'
BEGIN
    INSERT INTO Policy_BuildingClassCultureChanges(PolicyType, BuildingClassType, CultureChange)
        SELECT 'POLICY_CULTURAL_CENTERS', afterinsert.type, 10 FROM (
                    SELECT DISTINCT Type From BuildingClasses WHERE DefaultBuilding = New.BuildingType AND MaxGlobalInstances = -1 AND MaxTeamInstances = -1 AND MaxPlayerInstances = -1
                ) As afterinsert;
END;
 
Top Bottom