Skip to content

tutorials Creating a Narrative Event

ghost-ng edited this page Jan 28, 2026 · 1 revision

Tutorial: Creating a Narrative Event

This tutorial walks through creating a complete narrative event (pop-up event) for Civilization VII, including triggers, choices, rewards, and localization.

What You'll Learn

  • Understanding the parent-child event structure
  • Creating activation and completion requirements
  • Adding choices with different outcomes
  • Attaching rewards using modifiers
  • Adding reward icons and dynamic text

Example: The Merchant's Dilemma

We'll create an event that triggers when a player has 3 cities with markets. It presents a choice between gold or culture bonuses.

File Structure

my-merchant-event/
├── data/
│   └── events.xml
├── text/
│   └── text.xml
└── my-merchant-event.modinfo

Step 1: Create the .modinfo File

my-merchant-event.modinfo

<?xml version="1.0" encoding="utf-8"?>
<Mod id="my-merchant-event" version="1" xmlns="ModInfo">
    <Properties>
        <Name>Merchant's Dilemma Event</Name>
        <Description>Adds a narrative event for prosperous trade cities.</Description>
        <Authors>Your Name</Authors>
        <AffectsSavedGames>1</AffectsSavedGames>
    </Properties>
    <Dependencies>
    </Dependencies>
    <ActionCriteria>
        <Criteria id="antiquity-age">
            <AgeInUse>AGE_ANTIQUITY</AgeInUse>
        </Criteria>
    </ActionCriteria>
    <ActionGroups>
        <ActionGroup id="antiquity-game" scope="game" criteria="antiquity-age">
            <Actions>
                <UpdateDatabase>
                    <Item>data/events.xml</Item>
                </UpdateDatabase>
                <UpdateText>
                    <Item>text/text.xml</Item>
                </UpdateText>
            </Actions>
        </ActionGroup>
    </ActionGroups>
</Mod>

Step 2: Understand Event Structure

Narrative events in Civ VII use a parent-child structure:

EVENT_MY_POPUP (Parent - the pop-up itself)
├── EVENT_MY_CHOICE_A (Child - first button)
└── EVENT_MY_CHOICE_B (Child - second button)
  • Parent Event: Defines the pop-up title, body text, and trigger conditions
  • Child Events: Each button is a separate event, linked to the parent

Step 3: Create the Event Database

data/events.xml

<?xml version="1.0" encoding="utf-8"?>
<GameEffects xmlns="GameEffects">
    <!-- ================================================
         REQUIREMENT SETS
         ================================================ -->

    <!-- Activation check: Only for certain civilizations (optional) -->
    <RequirementSet id="REQSET_MERCHANT_ACTIVATION" type="REQUIREMENTSET_TEST_ALL">
        <!-- No requirements = all players can get this event -->
    </RequirementSet>

    <!-- Trigger condition: Player has 3+ cities with markets -->
    <RequirementSet id="REQSET_MERCHANT_TRIGGER" type="REQUIREMENTSET_TEST_ALL">
        <Requirement type="REQUIREMENT_PLAYER_HAS_AT_LEAST_NUM_CITIES_WITH_CONSTRUCTIBLE">
            <Argument name="ConstructibleType">BUILDING_MARKET</Argument>
            <Argument name="Amount">3</Argument>
        </Requirement>
    </RequirementSet>

    <!-- ================================================
         REWARD MODIFIERS
         ================================================ -->

    <!-- Choice A: +150 Gold -->
    <Modifier id="MOD_MERCHANT_GOLD_REWARD"
              collection="COLLECTION_OWNER"
              effect="EFFECT_PLAYER_GRANT_YIELD"
              permanent="true">
        <Argument name="YieldType">YIELD_GOLD</Argument>
        <Argument name="Amount">150</Argument>
    </Modifier>

    <!-- Choice B: +100 Culture -->
    <Modifier id="MOD_MERCHANT_CULTURE_REWARD"
              collection="COLLECTION_OWNER"
              effect="EFFECT_PLAYER_GRANT_YIELD"
              permanent="true">
        <Argument name="YieldType">YIELD_CULTURE</Argument>
        <Argument name="Amount">100</Argument>
    </Modifier>
</GameEffects>

Now add the database entries using standard Database XML:

data/events-db.xml (or append to events.xml using <Database> root)

<?xml version="1.0" encoding="utf-8"?>
<Database>
    <!-- ================================================
         REGISTER TYPES
         ================================================ -->
    <Types>
        <Row Type="EVENT_MERCHANT_DILEMMA" Kind="KIND_NARRATIVE_STORY"/>
        <Row Type="EVENT_MERCHANT_GOLD" Kind="KIND_NARRATIVE_STORY"/>
        <Row Type="EVENT_MERCHANT_CULTURE" Kind="KIND_NARRATIVE_STORY"/>
        <Row Type="REWARD_MERCHANT_GOLD" Kind="KIND_NARRATIVE_REWARD"/>
        <Row Type="REWARD_MERCHANT_CULTURE" Kind="KIND_NARRATIVE_REWARD"/>
    </Types>

    <!-- ================================================
         NARRATIVE STORIES
         ================================================ -->
    <NarrativeStories>
        <!-- PARENT EVENT: The Pop-up -->
        <Row
            NarrativeStoryType="EVENT_MERCHANT_DILEMMA"
            Name="LOC_EVENT_MERCHANT_DILEMMA_NAME"
            Description="LOC_EVENT_MERCHANT_DILEMMA_DESCRIPTION"
            Completion="LOC_EVENT_MERCHANT_DILEMMA_COMPLETION"
            StoryTitle="LOC_EVENT_MERCHANT_DILEMMA_STORYTITLE"
            Age="AGE_ANTIQUITY"
            Activation="REQUISITE"
            ActivationRequirementSetId="REQSET_MERCHANT_ACTIVATION"
            RequirementSetId="REQSET_MERCHANT_TRIGGER"
            UIActivation="STANDARD"
            IsQuest="FALSE"
            Hidden="FALSE"
        />

        <!-- CHILD EVENT: Gold Choice -->
        <Row
            NarrativeStoryType="EVENT_MERCHANT_GOLD"
            Name="LOC_EVENT_MERCHANT_GOLD_NAME"
            Description="LOC_EVENT_MERCHANT_GOLD_DESCRIPTION"
            Completion="LOC_EVENT_MERCHANT_GOLD_COMPLETION"
            Age="AGE_ANTIQUITY"
            Activation="LINKED"
            RequirementSetId="Met"
            UIActivation="STANDARD"
            IsQuest="FALSE"
            Hidden="FALSE"
        />

        <!-- CHILD EVENT: Culture Choice -->
        <Row
            NarrativeStoryType="EVENT_MERCHANT_CULTURE"
            Name="LOC_EVENT_MERCHANT_CULTURE_NAME"
            Description="LOC_EVENT_MERCHANT_CULTURE_DESCRIPTION"
            Completion="LOC_EVENT_MERCHANT_CULTURE_COMPLETION"
            Age="AGE_ANTIQUITY"
            Activation="LINKED"
            RequirementSetId="Met"
            UIActivation="STANDARD"
            IsQuest="FALSE"
            Hidden="FALSE"
        />
    </NarrativeStories>

    <!-- ================================================
         LINK EVENTS (Parent to Children)
         ================================================ -->
    <NarrativeStory_Links>
        <Row
            FromNarrativeStoryType="EVENT_MERCHANT_DILEMMA"
            ToNarrativeStoryType="EVENT_MERCHANT_GOLD"
            Name="LOC_EVENT_MERCHANT_GOLD_NAME"
            Description="LOC_EVENT_MERCHANT_GOLD_DESCRIPTION"
        />
        <Row
            FromNarrativeStoryType="EVENT_MERCHANT_DILEMMA"
            ToNarrativeStoryType="EVENT_MERCHANT_CULTURE"
            Name="LOC_EVENT_MERCHANT_CULTURE_NAME"
            Description="LOC_EVENT_MERCHANT_CULTURE_DESCRIPTION"
        />
    </NarrativeStory_Links>

    <!-- ================================================
         REWARDS
         ================================================ -->
    <NarrativeRewards>
        <Row NarrativeRewardType="REWARD_MERCHANT_GOLD" ModifierID="MOD_MERCHANT_GOLD_REWARD"/>
        <Row NarrativeRewardType="REWARD_MERCHANT_CULTURE" ModifierID="MOD_MERCHANT_CULTURE_REWARD"/>
    </NarrativeRewards>

    <NarrativeStory_Rewards>
        <Row
            NarrativeStoryType="EVENT_MERCHANT_GOLD"
            NarrativeRewardType="REWARD_MERCHANT_GOLD"
            Activation="COMPLETE"
        />
        <Row
            NarrativeStoryType="EVENT_MERCHANT_CULTURE"
            NarrativeRewardType="REWARD_MERCHANT_CULTURE"
            Activation="COMPLETE"
        />
    </NarrativeStory_Rewards>

    <!-- ================================================
         REWARD ICONS
         ================================================ -->
    <NarrativeRewardIcons>
        <Row NarrativeStoryType="EVENT_MERCHANT_GOLD" RewardIconType="YIELD_GOLD"/>
        <Row NarrativeStoryType="EVENT_MERCHANT_CULTURE" RewardIconType="YIELD_CULTURE"/>
    </NarrativeRewardIcons>
</Database>

Key Columns Explained

Column Purpose
NarrativeStoryType Unique identifier for the event
Name Button text for child events (required but can be dummy for parents)
Description Tooltip text (required but can be dummy for parents)
Completion Body text shown in the pop-up
StoryTitle Title at top of pop-up (parent events only)
Activation REQUISITE for triggers, LINKED for buttons
ActivationRequirementSetId One-time eligibility check
RequirementSetId Trigger condition (or Met for always-available)
UIActivation STANDARD or DISCOVERY style

Step 4: Add Localization

text/text.xml

<?xml version="1.0" encoding="utf-8"?>
<Database>
    <LocalizedText>
        <!-- Parent Event -->
        <Row Tag="LOC_EVENT_MERCHANT_DILEMMA_NAME" Language="en_US">
            <Text>Merchant's Dilemma</Text>
        </Row>
        <Row Tag="LOC_EVENT_MERCHANT_DILEMMA_DESCRIPTION" Language="en_US">
            <Text>A choice about trade prosperity</Text>
        </Row>
        <Row Tag="LOC_EVENT_MERCHANT_DILEMMA_STORYTITLE" Language="en_US">
            <Text>The Merchant's Dilemma</Text>
        </Row>
        <Row Tag="LOC_EVENT_MERCHANT_DILEMMA_COMPLETION" Language="en_US">
            <Text>The guild masters of your trading cities have gathered to discuss the future of commerce. Your markets have flourished, and now a decision must be made: should the profits be reinvested in expanding trade, or spent on cultural pursuits that will bring prestige to your civilization?</Text>
        </Row>

        <!-- Gold Choice -->
        <Row Tag="LOC_EVENT_MERCHANT_GOLD_NAME" Language="en_US">
            <Text>Expand Trade Networks</Text>
        </Row>
        <Row Tag="LOC_EVENT_MERCHANT_GOLD_DESCRIPTION" Language="en_US">
            <Text>+150[icon:YIELD_GOLD] Gold</Text>
        </Row>
        <Row Tag="LOC_EVENT_MERCHANT_GOLD_COMPLETION" Language="en_US">
            <Text>The merchants rejoice as new trade routes are established, bringing wealth from distant lands.</Text>
        </Row>

        <!-- Culture Choice -->
        <Row Tag="LOC_EVENT_MERCHANT_CULTURE_NAME" Language="en_US">
            <Text>Patronize the Arts</Text>
        </Row>
        <Row Tag="LOC_EVENT_MERCHANT_CULTURE_DESCRIPTION" Language="en_US">
            <Text>+100[icon:YIELD_CULTURE] Culture</Text>
        </Row>
        <Row Tag="LOC_EVENT_MERCHANT_CULTURE_COMPLETION" Language="en_US">
            <Text>Artists and philosophers are sponsored by the merchant guilds, enriching your cultural heritage.</Text>
        </Row>
    </LocalizedText>
</Database>

Step 5: Install and Test

  1. Copy your mod folder to:

    • Windows: %LOCALAPPDATA%\Firaxis Games\Sid Meier's Civilization VII\Mods\
  2. Enable the mod in Additional Content

  3. Start an Antiquity game

  4. Build Markets in 3 cities

  5. The event should trigger on the next turn

Advanced: Conditional Choices

Make a choice only appear under certain conditions:

<NarrativeStories>
    <Row
        NarrativeStoryType="EVENT_SPECIAL_CHOICE"
        Name="LOC_EVENT_SPECIAL_CHOICE_NAME"
        Description="LOC_EVENT_SPECIAL_CHOICE_DESCRIPTION"
        Age="AGE_ANTIQUITY"
        Activation="LINKED_REQUISITE"
        ActivationRequirementSetId="REQSET_HAS_WONDER"
        RequirementSetId="Met"
        UIActivation="STANDARD"
    />
</NarrativeStories>

Use LINKED_REQUISITE instead of LINKED - the choice only appears if ActivationRequirementSetId is met.

Advanced: Quest Events

Create multi-step quests:

<NarrativeStories>
    <!-- Quest Start -->
    <Row
        NarrativeStoryType="EVENT_QUEST_START"
        ...
        IsQuest="TRUE"
        Imperative="LOC_QUEST_OBJECTIVE"
    />

    <!-- Quest Completion -->
    <Row
        NarrativeStoryType="EVENT_QUEST_COMPLETE"
        ...
        Activation="LINKED"
        RequirementSetId="REQSET_QUEST_COMPLETE"
    />
</NarrativeStories>

<!-- Link them -->
<NarrativeStory_Links>
    <Row
        FromNarrativeStoryType="EVENT_QUEST_START"
        ToNarrativeStoryType="EVENT_QUEST_COMPLETE"
        ...
    />
</NarrativeStory_Links>

Advanced: Dynamic Text Replacements

Insert dynamic content like city names:

<NarrativeStory_TextReplacements>
    <Row
        NarrativeStoryType="EVENT_MERCHANT_DILEMMA"
        NarrativeStoryTextType="BODY"
        NarrativeTextReplacementType="CAPITAL"
        Priority="1"
    />
</NarrativeStory_TextReplacements>

In your text, use {1} for the first replacement:

<Row Tag="LOC_EVENT_COMPLETION" Language="en_US">
    <Text>The merchants of {1} have prospered!</Text>
</Row>

Replacement Types

Type Inserts
CAPITAL Player's capital city name
CIVILIZATION Player's civilization name
CIVILIZATION_ADJ Civilization adjective
INDEPENDENT Nearby independent name
REWARD Auto-generated reward text

Troubleshooting

Issue Solution
Event never triggers Check RequirementSetId conditions are achievable
No choices appear Verify NarrativeStory_Links connects parent to children
Reward not given Check NarrativeStory_Rewards has Activation="COMPLETE"
Wrong age Ensure Age column matches your ActionCriteria
Missing text Verify LOC_ tags match exactly between files

Common Requirement Types

Requirement Use Case
REQUIREMENT_PLAYER_HAS_AT_LEAST_NUM_CITIES City count threshold
REQUIREMENT_PLAYER_HAS_AT_LEAST_NUM_CITIES_WITH_CONSTRUCTIBLE Cities with specific building
REQUIREMENT_PLAYER_CIVILIZATION_TYPE_MATCHES Civ-specific event
REQUIREMENT_PLAYER_HAS_TECHNOLOGY Tech requirement
REQUIREMENT_PLAYER_HAS_AT_LEAST_NUM_GOSSIPS Flexible gossip-based

Next Steps

Clone this wiki locally