Elemental: Reforged - Data Modding Guide

Elemental: Reforged - Data Modding Guide

This guide covers how to create data mods for Elemental: Reforged. Data mods let you add new units, spells, items, improvements, and more -- or modify and remove existing ones -- using XML files.


1. Getting Started

Mod Folder Location

All mods live under your Documents folder:

Documents\My Games\ElementalReforged\Mods\

The game automatically creates a User subfolder for local mods. You can also create your own named folder.

Mod Folder Structure

Mods/
  YourModName/
    Data/
      GameCore/           <-- Most game definitions go here
        Core Stamps/      <-- Terrain stamps
        Effects/          <-- Particle/visual effects
        Scenarios/        <-- Scenario definitions
      Animations/         <-- Custom animations
      Core Tiles/         <-- Tile designs (recursive)
      Core World/         <-- World data (recursive)
      CutScenes/          <-- Cutscene definitions

Place your XML files in the appropriate subdirectory. The game scans these paths when mods are enabled and merges them with the base game data.

Enabling Your Mod

  1. Launch the game

  2. From the main menu, open the Mod Manager

  3. Enable the User folder (or your custom mod folder)

  4. Adjust load order if you have multiple mods (later mods override earlier ones)

  5. Restart or start a new game


2. XML File Format

All game data is defined in XML files. Here's the basic structure:

<?xml version='1.0' encoding='utf-8'?>
<RootElement>

  <DataType InternalName="MyDefinition">
    <Property1>value</Property1>
    <Property2>value</Property2>
  </DataType>

</RootElement>

Key rules:

  • Every definition needs an InternalName attribute -- this is its unique identifier

  • The root element name varies by file but doesn't affect parsing

  • Text values for player-visible strings should use localization keys (e.g., TXT_MY_MOD_UNIT_NAME), but you can use plain text for testing

  • Boolean values are 0 (false) or 1 (true)

  • Colors are comma-separated: R,G,B or R,G,B,A (0-255)


3. Core Data Types

Here are the most commonly modded data types and the XML tags they use:

Units

<UnitTypes>
  <UnitType InternalName="MyCustomUnit">
    <DisplayName>My Custom Unit</DisplayName>
    <Description>A powerful warrior.</Description>
    <Class>Adventurer</Class>
    <Allegiance>Empire</Allegiance>
    <CreatureType>Champion</CreatureType>
    <RaceType>Race_Type_Men</RaceType>
    <Gender>Male</Gender>
    <IsChampion>1</IsChampion>
    <Unique>0</Unique>
    <CanBeDesigned>0</CanBeDesigned>
    <SpawnRating>1</SpawnRating>

    <!-- Stats at level 1 -->
    <LevelMilestone InternalName="L1">
      <Level>1</Level>
      <UnitStat_HitPoints>30</UnitStat_HitPoints>
      <UnitStat_Accuracy>85</UnitStat_Accuracy>
      <UnitStat_CombatSpeed>24</UnitStat_CombatSpeed>
    </LevelMilestone>

    <!-- Starting equipment (by InternalName) -->
    <AutoCreateEquipment>IronSword</AutoCreateEquipment>
    <Equipment>F_Male_Head_01</Equipment>

    <!-- Starting abilities -->
    <SelectedAbilityBonusOption>Fire1</SelectedAbilityBonusOption>

    <!-- Visual setup -->
    <ModelPath>Gfx\HKB\Units\F_Male_Mesh_01.hkb</ModelPath>
    <SkeletonPath>Gfx\HKB\Units\K_Male_Skeleton_01.hkb</SkeletonPath>
    <AnimationPack>MaleSovereignAnimationPack</AnimationPack>
    <BattleAnimationBehavior>Melee</BattleAnimationBehavior>
    <Color_Skin>180,140,110,255</Color_Skin>
    <Color_Clothing1>60,40,30,255</Color_Clothing1>
    <SoundPack>SoundPack_Generic_Male</SoundPack>
  </UnitType>
</UnitTypes>

Spells

<Spells>
  <SpellDef InternalName="MyFireball">
    <DisplayName>Fireball</DisplayName>
    <Description>Hurls a ball of fire at the target.</Description>
    <Image>T_Fireball_Painting.png</Image>
    <IconFG>T_Fireball_Icon.png</IconFG>
    <SpellType>Tactical</SpellType>
    <SpellClass>Offensive</SpellClass>
    <SpellSubClass>Damage</SpellSubClass>
    <SpellTargetType>EnemyUnit</SpellTargetType>
    <SpellBookSortCategory>Attack</SpellBookSortCategory>

    <!-- Prerequisites -->
    <Prereq>
      <Type>AbilityBonusOption</Type>
      <Attribute>FireAdept1</Attribute>
    </Prereq>

    <!-- Casting cost -->
    <SpellResourceCost>
      <Resource>Mana</Resource>
      <Amount>12</Amount>
    </SpellResourceCost>

    <!-- Damage effect (see GameModifier section) -->
    <GameModifier>
      <ModType>Unit</ModType>
      <Attribute>AdjustUnitStat</Attribute>
      <StrVal>CurHealth</StrVal>
      <Value>-15</Value>
    </GameModifier>

    <!-- Visual effect -->
    <SpellDefEffect>
      <EffectName>T_Fireball_Particle</EffectName>
      <EffectScale>1.0</EffectScale>
      <SnapToTerrain>1</SnapToTerrain>
    </SpellDefEffect>

    <HitSoundFX>Spell_Fire_01</HitSoundFX>
  </SpellDef>
</Spells>

Improvements (City Buildings)

<ImprovementTypes>
  <ImprovementType InternalName="MyLibrary">
    <DisplayName>Grand Library</DisplayName>
    <Description>A center of learning.</Description>
    <RequiresCity>1</RequiresCity>
    <RequiresForceUnlock>1</RequiresForceUnlock>
    <LaborToBuild>0</LaborToBuild>

    <!-- Required tech or building -->
    <RequiredImprovement>Conclave</RequiredImprovement>

    <!-- Terrain restrictions -->
    <BarredTerrain>River</BarredTerrain>
    <BarredTerrain>SwampTerrain</BarredTerrain>
    <PreferredTerrain>City</PreferredTerrain>

    <!-- Effects -->
    <GameModifier>
      <ModType>Player</ModType>
      <Attribute>AbilityBonus</Attribute>
      <StrVal>A_Research</StrVal>
      <Value>15</Value>
      <Provides>+15 Research</Provides>
    </GameModifier>

    <!-- AI priority -->
    <AIData AIPersonality="AI_General">
      <AIPriority>14</AIPriority>
      <AITag>Study</AITag>
    </AIData>

    <ArtDef>Art_Academy</ArtDef>
  </ImprovementType>
</ImprovementTypes>

Resources

<ResourceTypes>
  <ResourceType InternalName="MyResource">
    <DisplayName>Moonstone</DisplayName>
    <Description>A rare crystalline mineral.</Description>
    <Type>Material</Type>
    <Icon>Gfx//Icons//Res_Icon_Moonstone.png</Icon>
    <Worth>5</Worth>
    <Global>0</Global>
    <Rarity>0.3</Rarity>
    <Shared>0</Shared>
    <TradedByCaravans>1</TradedByCaravans>
    <ShownInGlobalDisplay>1</ShownInGlobalDisplay>
    <IconColor>180,200,255</IconColor>
    <ModelColor>180,200,255</ModelColor>
  </ResourceType>
</ResourceTypes>

Terrain Types

<TerrainTypes>
  <TerrainType InternalName="MyTerrain">
    <DisplayName>Crystalline Wastes</DisplayName>
    <MaxHeight>60</MaxHeight>
    <MinHeight>50</MinHeight>
    <MovementCost>12</MovementCost>
    <Category>Land</Category>
    <IsBaseTerrain>0</IsBaseTerrain>
    <IsTerrainFeature>1</IsTerrainFeature>
    <PassableByLandUnits>1</PassableByLandUnits>
    <PassableByWaterUnits>0</PassableByWaterUnits>
    <PassableByAirUnits>1</PassableByAirUnits>
    <Indestructable>0</Indestructable>

    <!-- Yield bonus -->
    <GameModifier InternalName="CrystalYield">
      <ModType>Resource</ModType>
      <Attribute>TileYieldMaterial</Attribute>
      <Value>2</Value>
      <PerTurn>1</PerTurn>
    </GameModifier>
  </TerrainType>
</TerrainTypes>

4. The GameModifier System

GameModifiers are the backbone of effects in Elemental. They're used everywhere: spells, items, improvements, terrain, abilities, and more. A single definition can contain multiple GameModifier blocks.

Basic Structure

<GameModifier InternalName="OptionalName">
  <ModType>Unit</ModType>
  <Attribute>AdjustUnitStat</Attribute>
  <StrVal>CurHealth</StrVal>
  <Value>10</Value>
  <Provides>+10 HP</Provides>
</GameModifier>

ModType Values

ModType

Applies to

Unit

Individual units (stats, abilities)

Player

Player-wide bonuses (research, gold income)

Resource

Resource yields and production

Map

Terrain and tile effects

Common Attributes

XML Tag

Description

ModType

What the modifier targets

Attribute

The specific attribute to modify

Value

Numeric value of the effect

StrVal / StrVal2

String parameters (e.g., stat name, unit class)

Provides

Player-visible description of the effect

Duration

How many turns the effect lasts

DurationOnTile

Duration while on a specific tile

Radius

Area of effect radius

Multiplier

Multiplicative factor (default: 1.0)

BonusValue

Additional bonus amount

MinValue / MaxValue

Random range (if both set, value is randomized between them).

Conditional Modifiers

XML Tag

Description

PerTurn

Apply every turn (boolean)

PerLevel

Scale with unit level (boolean)

PerStamina

Scale with stamina (boolean)

Cumulative

Stacks with itself (boolean)

vsDamaged

Only applies vs damaged targets

vsLower

Only applies vs lower-stat targets

vsHigher

Only applies vs higher-stat targets

vsOtherAllegiance

Only applies vs different allegiance

WhenUnderPercentHitPoints

Activates when HP below threshold (0-100)

WhenUnderArmySize

Activates when army size is under N

WhenOverArmySize

Activates when army size is over N

Application Timing

XML Tag

Description

xActions

Apply at battle start

ApplyAtBattleEnd

Apply when battle ends

ApplyDuringConstruction

Apply while building is under construction

ApplyFromTileAtTacticalTurnStart

Apply from tile at each tactical turn

RemoveWhenTargetLeavesTile

Remove effect when unit leaves the tile

IsPreHitSpellModifier

Apply before hit resolution

ApplyIfSpellTargetKilled

Apply only if the spell kills the target

Targeting

XML Tag

Description

AffectedUnits

Filter which units are affected

UnitClass

Filter by unit class

TerrainType

Filter by terrain type

ApplyToCaster

Apply to the caster instead of the target

ApplyToPlayer

Apply to the player instead of a unit

ApplyToTile

Apply to the tile instead of a unit

ApplyToSpellRadiusCenterOnly

Only affect center tile of AoE


5. The Calculate System (Variable Expressions)

For dynamic values that depend on game state (unit stats, shard counts, etc.), use Calculate blocks inside a GameModifier:

<GameModifier>
  <ModType>Unit</ModType>
  <Attribute>CurHealth</Attribute>

  <Calculate InternalName="ShardBonus" ValueOwner="CastingUnit">
    <Expression><![CDATA[[UnitOwner_GetNumLifeShards] * 2]]></Expression>
  </Calculate>

  <Calculate InternalName="BaseHeal" ValueOwner="CastingUnit">
    <Expression><![CDATA[[ShardBonus] + 8]]></Expression>
  </Calculate>

  <Calculate InternalName="Value">
    <Expression><![CDATA[[BaseHeal]]]></Expression>
  </Calculate>
</GameModifier>

How It Works

  • Each Calculate block has an InternalName and an <Expression>

  • Variables are referenced with square brackets: [VariableName]

  • Variables can reference other Calculate blocks by InternalName, or properties from the ValueOwner

  • The system links calculators together: child calculators feed into parent calculators

  • The final result must be in a calculator named Value

  • Use ValueForFormattedDescription for the value shown in UI descriptions

Supported Operators

Operator

Description

+

Addition

-

Subtraction

*

Multiplication

/

Division

%

Modulo

^

Exponentiation

<

Less than (returns 0 or 1)

>

Greater than (returns 0 or 1)

Calculate Tags

Tag

Description

Expression

The math expression (wrap in <![CDATA[...]]> for safety)

Min

Minimum value the result can be

Max

Maximum value the result can be

ValueOwner

Where to look up variable values (CastingUnit, TargetUnit, etc.)

Common Variable Names

Variables available depend on the ValueOwner. Common ones include:

  • [UnitOwner_GetNumLifeShards], [UnitOwner_GetNumFireShards], etc.

  • [UnitStat_HitPoints], [UnitStat_Accuracy], [UnitStat_CombatSpeed]

  • [Unit_GetHPCurrent], [Unit_GetLevel]

  • [A_Diplomacy], [TradeIncome] (for treaty calculations)

  • Any float property exposed by the ValueOwner's GetFloatProperty() method


6. Overriding Existing Definitions

The IfExists Attribute

When your mod defines something with the same InternalName as a base game definition, you can control what happens using the IfExists attribute:

<UnitType InternalName="Champion_Craul" IfExists="ClearIfExists">
  <!-- This completely replaces Craul's definition -->
</UnitType>

IfExists Value

Behavior

Update

Merge your values on top of the existing definition (partial override)

ClearIfExists

Wipe the existing definition completely, then read your new values (full replacement)

ClearChildren

Clear child collections (e.g., level milestones) but keep parent data

Ignore

Skip this definition if it already exists

Duplicate

Always create a new entry (no duplicate check)

If you don't specify IfExists, each data type has a default behavior. Most types default to Update, meaning your values merge on top.

Practical Examples

Buff an existing unit's HP:

<!-- Update mode (default) - only changes what you specify -->
<UnitType InternalName="Champion_Craul">
  <LevelMilestone InternalName="L1">
    <UnitStat_HitPoints>50</UnitStat_HitPoints>
  </LevelMilestone>
</UnitType>

Completely replace a spell:

<SpellDef InternalName="Aid" IfExists="ClearIfExists">
  <!-- Your entire new spell definition here -->
  <DisplayName>Greater Aid</DisplayName>
  <!-- ... all fields must be specified ... -->
</SpellDef>

7. Removing Definitions (RemoveDef)

The Smart Modding system lets you surgically remove base game content. Place a <RemoveDef> block in any XML file in your mod:

Remove All Definitions of a Type

<RemoveDef>
  <RemoveAllCoreDefsOfType>UnitType</RemoveAllCoreDefsOfType>
</RemoveDef>

This removes every core UnitType, letting your mod provide all units from scratch.

Remove Specific Definitions by Name

<RemoveDef>
  <UnitType InternalName="Champion_Craul"/>
  <SpellDef InternalName="Aid"/>
  <ImprovementType InternalName="Academy"/>
</RemoveDef>

Skip Parsing Entire Files

<RemoveDef>
  <SkipParsingFile>CoreUnitProps.xml</SkipParsingFile>
  <SkipParsingFile>CoreMonsters.xml</SkipParsingFile>
</RemoveDef>

This prevents the game from loading those files at all, so your mod can provide complete replacements.

Combining Approaches

You can combine these in a single RemoveDef block:

<RemoveDef>
  <!-- Remove all core factions -->
  <RemoveAllCoreDefsOfType>RaceConfig</RemoveAllCoreDefsOfType>

  <!-- Remove a specific spell -->
  <SpellDef InternalName="Aid"/>

  <!-- Skip loading the base monster file entirely -->
  <SkipParsingFile>CoreMonsters.xml</SkipParsingFile>
</RemoveDef>

Important: RemoveDef only affects core definitions. It won't remove definitions added by other mods loaded before yours. Load order matters.


8. Load Order

When multiple mods are enabled, the game loads them in the order shown in the Mod Manager. This matters because:

  1. Later mods win. If two mods define the same InternalName, the later one's values take precedence (in Update mode, the later mod's values overwrite the earlier mod's for any overlapping fields).

  2. RemoveDef applies to core only. RemoveDef blocks remove base game definitions during the counting phase, before any mod definitions are parsed.

  3. Recommended practice: If your mod depends on another mod, document that it should be loaded after the dependency.


9. AI Data

Most data types support an <AIData> block that tells the AI how to evaluate and use the definition:

<AIData AIPersonality="AI_General">
  <AIPriority>15</AIPriority>
  <AITag>Study</AITag>

  <!-- Optional: calculated value for AI decisions -->
  <ValueCalcWrapper>
    <ValueType>IsTargetWorthy</ValueType>
    <Calculate InternalName="Calc" ValueOwner="TargetUnit">
      <Expression><![CDATA[[Unit_GetHPCurrent]]]></Expression>
    </Calculate>
    <Calculate InternalName="Value">
      <Expression><![CDATA[[Calc] < 30]]></Expression>
    </Calculate>
  </ValueCalcWrapper>
</AIData>

Higher AIPriority values make the AI favor that option more. The ValueCalcWrapper provides dynamic evaluation for context-sensitive decisions.


10. Reference: Moddable Data Types

Here are the major data types you can define in XML. Use the corresponding tag name as your XML element:

XML Tag

Description

Example File

UnitType

Units, champions, monsters

CoreUnits.xml

SpellDef

Spell definitions

CoreSpells.xml

ImprovementType

City buildings and improvements

CoreImprovements.xml

ResourceType

Resources (gold, mana, materials)

CoreResources.xml

TerrainType

Terrain types and features

TerrainTypes.xml

GameItemType

Equipment and items

CoreItems.xml

RaceConfig

Faction configurations

CoreRaceConfigs.xml

RaceType

Race type definitions

CoreRaceTypes.xml

TechDef

Technology definitions

CoreTechs.xml

TechTree

Technology tree layout

TechTree_Amarian.xml

QuestDef

Quest definitions

CoreQuests.xml

QuestLocation

Quest locations on the map

CoreQuestLocations.xml

AbilityBonus

Ability/trait definitions

CoreAbilities.xml

RecipeType

Crafting recipes

CoreRecipes.xml

DungeonType

Dungeon definitions

(in GameCore)

GoodieHut

Goodie hut encounters

CoreGoodieHuts.xml

GameTrigger

Event triggers

CoreGameEvents.xml

FlavorText

Random flavor text

CoreFlavorText.xml

NamePool

Name generation pools

CoreNamePools.xml

FactionConfig

Faction setup and colors

CoreRaceConfigs.xml

DifficultyLevel

Difficulty settings

CoreDifficultyLevels.xml

Treaty

Diplomacy treaty types

Treaties.xml

MapSettings

Map generation settings

CoreMaps.xml

RandomEvent

Random event definitions

CoreRandomEvents.xml

UnitStatType

Unit stat definitions

CoreUnitStats.xml

UnitQualityType

Unit quality tiers

CoreUnitQualityTypes.xml

MusicLayerGroup

Music definitions

CoreLayeredMusic.xml

SoundPack

Sound effect packs

UnitSoundPacks.xml

Tip: The best way to learn any data type's available fields is to look at the corresponding core XML file in Elemental-LH/Game/data/GameCore/.


11. Tips and Best Practices

  • Start small. Override one unit or one spell to make sure your mod folder is set up correctly before building something large.

  • Use Update mode (the default) for small tweaks. Only use ClearIfExists when you need to completely replace a definition.

  • Keep your InternalNames unique for new content. Prefix them with your mod name to avoid conflicts: MyMod_FireGolem instead of FireGolem.

  • Test with the Spawn Object tool in-game (Ctrl+Alt+S or tilde key) to quickly spawn and inspect your modded objects.

  • Back up your mod folder before making large changes.

  • Check load order if your changes aren't appearing -- your mod might be loading before another mod that overrides the same definitions.

  • Localization keys (e.g., TXT_MY_MOD_UNIT_NAME) can be defined in localization XML files, but plain text strings work fine for testing and small mods.

615 views 0 replies | Pinned