Adding yields to terrian via Civic (RESOLVED)

SocialMechanic

Chieftain
Joined
May 11, 2019
Messages
97
So, I'm wanting to make a mod where the mountain tile can be worked by any Civ.
This is working as intended.
Code:
<Terrain_YieldChanges>
        <Row TerrainType="TERRAIN_GRASS_MOUNTAIN" YieldType="YIELD_PRODUCTION" YieldChange="1"/>
        <Row TerrainType="TERRAIN_PLAINS_MOUNTAIN" YieldType="YIELD_PRODUCTION" YieldChange="1"/>
        <Row TerrainType="TERRAIN_DESERT_MOUNTAIN" YieldType="YIELD_PRODUCTION" YieldChange="1"/>
        <Row TerrainType="TERRAIN_TUNDRA_MOUNTAIN" YieldType="YIELD_PRODUCTION" YieldChange="1"/>
        <Row TerrainType="TERRAIN_SNOW_MOUNTAIN" YieldType="YIELD_PRODUCTION" YieldChange="1"/>
    </Terrain_YieldChanges>
    <TraitModifiers>
        <Row TraitType="TRAIT_LEADER_MAJOR_CIV" ModifierId="TRAIT_WORK_GRASS_MOUNTAIN"/>
        <Row TraitType="TRAIT_LEADER_MAJOR_CIV" ModifierId="TRAIT_WORK_PLAINS_MOUNTAIN"/>
        <Row TraitType="TRAIT_LEADER_MAJOR_CIV" ModifierId="TRAIT_WORK_DESERT_MOUNTAIN"/>
        <Row TraitType="TRAIT_LEADER_MAJOR_CIV" ModifierId="TRAIT_WORK_TUNDRA_MOUNTAIN"/>
        <Row TraitType="TRAIT_LEADER_MAJOR_CIV" ModifierId="TRAIT_WORK_SNOW_MOUNTAIN"/>
    </TraitModifiers>
Then, I wanted the Incans to not really change at all with this mod
Code:
<ModifierArguments>
        <Update>
            <Where ModifierId="TRAIT_PRODUCTION_MOUNTAIN" Name="Amount" Value="2"/>
            <Set Value="1"/>
        </Update>
    </ModifierArguments>
Then, I wanted the Ski Resort to be workable and to provide +3 gold.
Code:
<Improvements>
        <Update>
            <Where ImprovementType="IMPROVEMENT_SKI_RESORT"/>
            <Set Workable="true"/>
        </Update>
    </Improvements>
    <Improvement_YieldChanges>
        <Row ImprovementType="IMPROVEMENT_SKI_RESORT" YieldType="YIELD_GOLD" YieldChange="3"/>
    </Improvement_YieldChanges>
All of this works no problem. However, I want mountains to gain a +1 Production bonus once once a certain Civic is discovered.
Code:
<Terrain_BonusYieldChanges>
        <Row Id="1" TerrainType="TERRAIN_GRASS_MOUNTAIN" YieldType="YIELD_PRODUCTION" BonusYieldChange="1" PrereqCivic="CIVIC_CODE_OF_LAWS"/>
        <Row Id="2" TerrainType="TERRAIN_PLAINS_MOUNTAIN" YieldType="YIELD_PRODUCTION" BonusYieldChange="1" PrereqCivic="CIVIC_CODE_OF_LAWS"/>
        <Row Id="3" TerrainType="TERRAIN_DESERT_MOUNTAIN" YieldType="YIELD_PRODUCTION" BonusYieldChange="1" PrereqCivic="CIVIC_CODE_OF_LAWS"/>
        <Row Id="4" TerrainType="TERRAIN_TUNDRA_MOUNTAIN" YieldType="YIELD_PRODUCTION" BonusYieldChange="1" PrereqCivic="CIVIC_CODE_OF_LAWS"/>
        <Row Id="5" TerrainType="TERRAIN_SNOW_MOUNTAIN" YieldType="YIELD_PRODUCTION" BonusYieldChange="1" PrereqCivic="CIVIC_CODE_OF_LAWS"/>
    </Terrain_BonusYieldChanges>
However, I couldn't find an actual "Terrain_BonusYieldChanges" table, so I used the "Improvement_BonusYieldChanges" table as a reference. Of course, I got an error letting me know that "Terrain_BonusYieldChanges" isn't an actual table, so I have to create it myself.
Looking at LeeS's PDF file, it appears that I can't make a table in XML, which is what I'm used to. So, I looked in the schemas directory in the SQL files to create my own table. This is what I made.
Code:
CREATE TABLE "Terrain_BonusYieldChanges" (
        "Id" INTEGER NOT NULL DEFAULT 0,
        "TerrainType" TEXT NOT NULL,
        "YieldType" TEXT NOT NULL,
        "BonusYieldChange" INTEGER NOT NULL,
        "PrereqTech" TEXT,
        "PrereqCivic" TEXT,
        PRIMARY KEY(Id, TerrainType, YieldType),
        FOREIGN KEY (PrereqTech) REFERENCES Technologies(TechnologyType) ON DELETE CASCADE ON UPDATE CASCADE,
        FOREIGN KEY (PrereqCivic) REFERENCES Civics(CivicType) ON DELETE CASCADE ON UPDATE CASCADE,
        FOREIGN KEY (TerrainType) REFERENCES Terrains(TerrainType) ON DELETE CASCADE ON UPDATE CASCADE,
        FOREIGN KEY (YieldType) REFERENCES Yields(YieldType) ON DELETE CASCADE ON UPDATE CASCADE);

INSERT INTO NavigationProperties("BaseTable", "PropertyName", "TargetTable", "IsCollection", "Query") VALUES("Terrains", "BonusYieldChanges", "Terrain_BonusYieldChanges", 1,"SELECT T1.rowid from Terrain_BonusYieldChanges as T1 inner join Terrains as T2 on T2.TerrainType = T1.TerrainType where T2.rowid = ? ORDER BY T1.rowid ASC");
INSERT INTO NavigationProperties("BaseTable", "PropertyName", "TargetTable", "IsCollection", "Query") VALUES("Terrain_BonusYieldChanges", "TerrainReference", "Terrains", 0,"SELECT T1.rowid from Terrains as T1 inner join Terrain_BonusYieldChanges as T2 on T2.TerrainType = T1.TerrainType where T2.rowid = ? ORDER BY T1.rowid ASC LIMIT 1");
INSERT INTO NavigationProperties("BaseTable", "PropertyName", "TargetTable", "IsCollection", "Query") VALUES("Terrain_BonusYieldChanges", "PrereqCivicReference", "Civics", 0,"SELECT T1.rowid from Civics as T1 inner join Terrain_BonusYieldChanges as T2 on T2.PrereqCivic = T1.CivicType where T2.rowid = ? ORDER BY T1.rowid ASC LIMIT 1");
INSERT INTO NavigationProperties("BaseTable", "PropertyName", "TargetTable", "IsCollection", "Query") VALUES("Terrain_BonusYieldChanges", "PrereqTechReference", "Technologies", 0,"SELECT T1.rowid from Technologies as T1 inner join Terrain_BonusYieldChanges as T2 on T2.PrereqTech = T1.TechnologyType where T2.rowid = ? ORDER BY T1.rowid ASC LIMIT 1");
INSERT INTO NavigationProperties("BaseTable", "PropertyName", "TargetTable", "IsCollection", "Query") VALUES("Terrain_BonusYieldChanges", "YieldReference", "Yields", 0,"SELECT T1.rowid from Yields as T1 inner join Terrain_BonusYieldChanges as T2 on T2.YieldType = T1.YieldType where T2.rowid = ? ORDER BY T1.rowid ASC LIMIT 1");
INSERT INTO NavigationProperties("BaseTable", "PropertyName", "TargetTable", "IsCollection", "Query") VALUES("Yields", "TerrainChange_Refs", "Terrain_BonusYieldChanges", 1,"SELECT T1.rowid from Terrain_BonusYieldChanges as T1 inner join Yields as T2 on T2.YieldType = T1.YieldType where T2.rowid = ? ORDER BY T1.rowid ASC");
Basically, I took the "Improvement_BonusYieldChanges" table as a reference.
I'm pretty sure that this code is wrong but I have zero clue how to fix it.
I then created a new "UpdateDatabase" action in ModBuddy and put the SQL file in there. I made the LoadOrder "-1" (from what I remember when I was reading LeeS's PDF, you have to do this when you make tables).
Of course, this didn't work and the mountain isn't gaining the production when I finish Codes of Law.
 
iirc there is an "EFFECT_ADJUST_PLOT_YIELD" that I used for my own ski resort mod. You could use that for a ModifierType and then attach it via CivicModifiers.
I'm sorry, but I'm not sure what you mean. Do you mean like this?
Code:
<CivicModifiers>
        <Row CivicType="CIVIC_CODE_OF_LAWS" ModifierId="SM_CIVIC_MOUNT_PROD_BONUS"/>
    </CivicModifiers>
    <Modifiers>
        <Row ModifierId="SM_CIVIC_MOUNT_PROD_BONUS" ModifierType="MODIFIER_PLAYER_ADJUST_PLOT_YIELD" SubjectRequirementSetId="SM_CIVIC_MOUNT_SETREQ"/>
    </Modifiers>
    <ModifierArguments>
        <Row ModifierId="SM_CIVIC_MOUNT_PROD_BONUS" Name="YieldType" Value="YIELD_PRODUCTION"/>
        <Row ModifierId="SM_CIVIC_MOUNT_PROD_BONUS" Name="Amount" Value="4"/>
    </ModifierArguments>
    <RequirementSets>
        <Row RequirementSetId="SM_CIVIC_MOUNT_SETREQ" RequirementSetType="REQUIREMENTSET_TEST_ALL"/>
    </RequirementSets>
    <RequirementSetRequirements>
        <Row RequirementSetId="SM_CIVIC_MOUNT_SETREQ" RequirementId="SM_CIVIC_MOUNT_SETREQID"/>
    </RequirementSetRequirements>
    <Requirements>
        <Row RequirementId="SM_CIVIC_MOUNT_SETREQID" RequirementType="REQUIREMENT_PLOT_TERRAIN_TYPE_MATCHES"/>
    </Requirements>
    <RequirementArguments>
        <Row RequirementId="SM_CIVIC_MOUNT_SETREQID" TerrainClassType="TERRAIN_CLASS_MOUNTAIN"/>
    </RequirementArguments>

EDIT: Or this?
Code:
    <CivicModifiers>
        <Row CivicType="CIVIC_CODE_OF_LAWS" ModifierId="SM_CIVIC_MOUNT_PROD_BONUS"/>
    </CivicModifiers>
    <Modifiers>
        <Row ModifierId="SM_CIVIC_MOUNT_PROD_BONUS" ModifierType="MODIFIER_PLAYER_ADJUST_PLOT_YIELD" SubjectRequirementSetId="REQUIREMENTS_PLOT_IS_MOUNTAIN"/>
    </Modifiers>
    <ModifierArguments>
        <Row ModifierId="SM_CIVIC_MOUNT_PROD_BONUS" Name="YieldType" Value="YIELD_PRODUCTION"/>
        <Row ModifierId="SM_CIVIC_MOUNT_PROD_BONUS" Name="Amount" Value="4"/>
    </ModifierArguments>

EDIT: Oh holy **** that second one worked!!! However, the Civic itself doesn't have one of those Star symbols that tell you something will change (like if does for other periodic improvement modifiers)
 
Last edited:
However, the Civic itself doesn't have one of those Star symbols that tell you something will change (like if does for other periodic improvement modifiers)
You'd need to add a text description (in the Civics & LocalizedText tables) for the Civic for that to show that.
 
We can create new game-tables in either of XML or SQL, but when we do so the table and any rows we add to it are merely inert text placed within the game's database. Each table provided by Firaxis is specifically and individually hooked-up to the rest of the game's systems within the code of the game's controlling DLL source-code. The DLL code is not dynamic in the sense of seeing a new table has been added to the database and automatically implementing the effects of the table. When we add a new table to the database we have to make other code (usually via lua) to implement the intended effect of the table.

The same restriction applies to adding new columns or altering the definitions of existing columns within the database. The game's source-code will not dynamically recognize these additions and/or changes and implement anything for them.

Sometimes mod-makers will add a new table to the game's database merely to simplify processing of complex SQL statements. When we do this, however, we are not directly implementing any effects for this new table: we are merely grabbing the data from the table and doing "post-processing" SQL manipulations on other game-tables that are already hooked-up and functional within the game's DLL source-code.
 
Back
Top Bottom