Content Type Reference
This page documents every auto-discovered content type that does not involve player actions (interactions, policies, edicts are covered in Interactions; scripted events are covered in Events).
Each section includes a property table, overridable methods, and a working code example.
Traits (UTrait)#
Traits are permanent or temporary character modifiers that affect stats, behaviour, and events.
Properties
TraitNameFTextDescriptionFTextIconKeyFNameSortOrderintTacticsfloatAuthorityfloatCunningfloatLoyaltyfloatGovernancefloatConstitutionfloatHonourDreadfloatLuxurySlotModifierint32HeritabilityfloatProbabilityfloatbCanBeGainedboolbIsTemporaryboolMinDurationDaysint32MaxDurationDaysint32ConflictingTraitsTArray<TSubclassOf<UTrait>>GainedEventFTraitEvent.Title, .Message, .Option fields.LostEventFTraitEventGainedEvent.TraitDataClassTSubclassOf<UTraitData>Overridable Methods
bool CanBeGained(UPerson Character) consttrue if the character is eligible to gain this trait.bool CanBeLost(UPerson Character) consttrue if the character should lose this trait.void Apply(UPerson Character)void Remove(UPerson Character)Apply().Example
UCLASS()
class UBattleHardened : UTrait
{
UBattleHardened()
{
ConflictingTraits.Add(UTimid::StaticClass());
ConflictingTraits.Add(UCowardly::StaticClass());
}
default TraitName = Localization::GetText("MyMod", "BattleHardened_Name");
default Description = Localization::GetText("MyMod", "BattleHardened_Description");
default SortOrder = 12;
default IconKey = n"BattleHardened";
default Heritability = 0.0f;
default Probability = 0.0f; // Never randomly generated
default bCanBeGained = true;
default Tactics = 10.0f;
default Authority = 5.0f;
default Constitution = 5.0f;
default Loyalty = 0.0f;
default Cunning = 0.0f;
default Governance = -5.0f;
default GainedEvent.Title = Localization::GetText("MyMod", "BattleHardened_GainedTitle");
default GainedEvent.Message = Localization::GetText("MyMod", "BattleHardened_GainedMessage");
default GainedEvent.Option = Localization::GetText("MyMod", "BattleHardened_GainedOption");
UFUNCTION(BlueprintOverride)
bool CanBeGained(UPerson Character) const
{
return Character.Stats.GetTactics() > 70.0f;
}
UFUNCTION(BlueprintOverride)
bool CanBeLost(UPerson Character) const
{
return false;
}
}Tips
- Stat modifiers stack additively. A trait with
Authority = 10.0fadds 10 to the character's base authority. - Set
Probability = 0.0ffor traits that should only be gained through gameplay conditions, never randomly. ConflictingTraitsis bidirectional -- if A conflicts with B, B should also list A.- Use
HonourDreadsparingly. Values typically range from -0.1 to 0.1.
Buildings (UBuilding)#
Buildings are constructed in settlements and provide economic, military, or cultural effects.
Enums
// Building type (affects military/naval logic)
enum EBuildingType { Military, Wall, Other, Naval }
// Building category (affects UI grouping)
enum EBuildingCategory { Economic, Military, Infrastructure, Cultural, Defensive, Naval, Administrative, Other }
// Build button state
enum EBuildButtonState { Visible, GreyedOut, Hidden }Properties
NameFTextDescriptionFTextDefaultEffectsFTextAssetKeyFNamePriceint32BuildTimefloatMaxLevelintUpkeepint32BuildingTypeEBuildingTypeOtherCategoryEBuildingCategoryOtherResourceCostTMap<FName, float>n"Iron", n"Wood"). Set in constructor.AvailableToCultureGroupsTSet<FName>CanBeDevelopedIntoTArray<TSubclassOf<UBuilding>>DevelopedFromTSubclassOf<UBuilding>bReplacesParentboolRequiredBuildingsTArray<TSubclassOf<UBuilding>>ProcessingRecipeFProcessingRecipeBaseProcessingCapacityfloatOverridable Methods
void OnAdd(APopulationCentre Settlement)void OnRemove(APopulationCentre Settlement)FText GetEffectsText() constLevel).FBuildRequirementResult CanBuild(APopulationCentre Settlement) constFBuildButtonInfo GetBuildButtonInfo(APopulationCentre Settlement) constExample
class UGranary : UBuilding
{
UGranary()
{
Name = Localization::GetText("MyMod", "Granary_Name");
AssetKey = n"Granary";
BuildTime = 45.0f;
Price = 200;
MaxLevel = 3;
Upkeep = 2;
BuildingType = EBuildingType::Other;
Category = EBuildingCategory::Economic;
ResourceCost.Add(n"Wood", 25.0f);
Description = Localization::GetText("MyMod", "Granary_Description");
DefaultEffects = Localization::GetText("MyMod", "Granary_DefaultEffects");
}
UFUNCTION(BlueprintOverride)
FText GetEffectsText() const
{
float Bonus = Level * 15.0f;
return FText::FromString(
Localization::GetText("MyMod", "Granary_Effects").ToString()
.Replace("{Bonus}", "" + Bonus)
);
}
UFUNCTION(BlueprintOverride)
void OnAdd(APopulationCentre Settlement)
{
Settlement.Modifiers.FoodProduction += Level * 0.15f;
}
UFUNCTION(BlueprintOverride)
void OnRemove(APopulationCentre Settlement)
{
Settlement.Modifiers.FoodProduction -= Level * 0.15f;
}
UFUNCTION(BlueprintOverride)
FBuildButtonInfo GetBuildButtonInfo(const APopulationCentre Settlement) const
{
FBuildButtonInfo Info;
if (Settlement.Population < 1000)
{
Info.State = EBuildButtonState::GreyedOut;
Info.Reason = FText::FromString(
Localization::GetText("MyMod", "Granary_NeedPop").ToString()
.Replace("{Population}", "1000")
);
}
return Info;
}
}Tips
- Set
AvailableToCultureGroupsto restrict the building to certain cultures. Leave it empty for universal availability. - The
Levelproperty (inherited fromUSettlementEffect) starts at 1 and increments with each upgrade, up toMaxLevel. OnAdd()andOnRemove()must be symmetrical -- whatever you add inOnAdd(), subtract inOnRemove().- Use
GetBuildButtonInfo()to hide the build button when a mutually exclusive building is present, or grey it out when prerequisites are not met. ResourceCostkeys must match resource FNames registered in the game (e.g.,n"Wood",n"Iron",n"Clothes",n"Weapons",n"PreciousMetals",n"Horses").
Army Units (UArmyUnit)#
Army units are military units that can be recruited at settlements and deployed in armies.
Enums
enum EArmyUnitType { Infantry, Ranged, Cavalry, Siege, Special }
enum EMilitaryUnitTier { Tier1, Tier2, Tier3, Tier4, Tier5 }Properties
Properties are split between UArmyUnit and its parent UMilitaryUnit.
UnitNameFStringDescriptionFStringUnitTypeEArmyUnitTypeTierEMilitaryUnitTierPriceint32BuildTimefloatUpkeepint32FoodConsumptionfloatMaxStrengthint32Strengthint32MaxStrength.SpeedfloatRangefloat0.0 = melee.WeightfloatSiegePowerfloatPierceDamagefloatCrushDamagefloatSlashDamagefloatPierceArmourfloatCrushArmourfloatSlashArmourfloatResourceUsageTMap<FName, float>n"Iron", n"Weapons"). Set in constructor.BattleActionsTArray<TSubclassOf<UBattleAction>>bImmuneToSnowAttritionboolbImmuneToDesertAttritionboolExample
class UDesertRaiders : UArmyUnit
{
UDesertRaiders()
{
UnitName = Localization::GetText("MyMod", "DesertRaiders_Name").ToString();
Description = Localization::GetText("MyMod", "DesertRaiders_Description").ToString();
ResourceUsage.Add(n"Iron", 10);
ResourceUsage.Add(n"Weapons", 15);
ResourceUsage.Add(n"Horses", 20);
BattleActions.Add(UChargeAction::StaticClass());
}
default Tier = EMilitaryUnitTier::Tier2;
default UnitType = EArmyUnitType::Cavalry;
default Upkeep = 12;
default FoodConsumption = 3.0;
default MaxStrength = 60;
default Strength = 60;
default Range = 0.0;
default Speed = 240.0;
default Price = 800;
default BuildTime = 50.0;
default Weight = 5.0;
default SiegePower = 1.0;
default PierceDamage = 12.0;
default CrushDamage = 8.0;
default SlashDamage = 14.0;
default PierceArmour = 4.0;
default CrushArmour = 3.0;
default SlashArmour = 5.0;
default bImmuneToDesertAttrition = true;
}Tips
UnitNameandDescriptionareFString, notFText. Use.ToString()when assigning fromLocalization::GetText().- The combat system uses three damage types (pierce, crush, slash) and three corresponding armour types. Damage reduction is calculated per-type.
- Units are linked to cultures through the culture's unit lists. To make your unit recruitable, you need to either create a new culture that includes it, or modify an existing culture's unit DataTable.
Strengthshould usually equalMaxStrength-- it represents the unit's starting troop count.
Cultures (UCulture)#
Cultures define naming conventions, titles, available units, visual styles, and gameplay flags for factions and characters.
Properties
CultureNameFTextDescriptionFTextGroupFNamen"Rephsian", n"Neutarnic"). Extensible by mods.GroupDisplayNameFTextGroupColourFLinearColorColourFLinearColorIconKeyFStringbUsesLevySystemboolbCanRaidboolDefaultVassalTypeint32RebelLeaderTitleFString"Usurper"RebelFactionNameFormatFStringNamingDataTableUDataTable*PhenotypeDatabaseUPhenotypeDatabase*ClothingDatabaseUClothingDatabase*BuildingSetUBuildingSet*UnitPortraitTableUDataTable*NavyUnitPortraitTableUDataTable*Naming Data (FCultureNamingData)
The naming DataTable uses the FCultureNamingData row struct with these fields:
FirstNamesTArray<FString>LastNamesTArray<FString>MiddleNamesTArray<FString>FemaleFirstNamesTArray<FString>FemaleMiddleNamesTArray<FString>FemaleLastNamesTArray<FString>EpithetsTArray<FString>RulerTitleFStringVassalRulerTitleFStringGovernorTitleFStringHeirTitleFStringConsortTitleFStringGeneralTitleFStringAdmiralTitleFStringFemaleRulerTitleFStringFemaleVassalRulerTitleFStringFemaleHeirTitleFStringFemaleGovernorTitleFStringMaleConsortTitleFStringRulerChildTitleFStringFemaleRulerChildTitleFStringRulerSiblingTitleFStringRegnalNamesTArray<FString>ArmyNameFormatFStringArmyNameSuffixesTArray<FString>FleetNameFormatFStringFleetNameSuffixesTArray<FString>RebelFactionNamesTArray<FString>RebelArmyNamesTArray<FString>Overridable Methods
FString FormatPersonName(UPerson Person, ENameDisplayFormat Format) constTips
- Culture groups use extensible
FNamevalues. You can create entirely new culture groups (e.g.,n"MyCustomGroup") without modifying engine code. - When creating a new culture, you will need to create a
NamingDataTableasset and import it. This requires PAK packaging for distribution. - The existing culture groups are:
n"Rephsian",n"Neutarnic",n"Svaranic",n"Tarhanic",n"Gwenedic",n"Imerassian",n"Shabarim",n"Shakharin".
Religions (UReligion)#
Religions provide stat bonuses and economic/military modifiers to characters and factions that follow them.
Properties
ReligionNameFStringDescriptionFStringReligionGroupFNamen"Borgutian", n"Pagan", n"Mystery"). Extensible by mods.ReligionLeaderTitleFString"Master of Religion"ColourFLinearColorIconKeyFStringMajorDeitiesTArray<FString>MinorDeitiesTArray<FString>RelicsTArray<FString>TacticsBonusfloatAuthorityBonusfloatCunningBonusfloatGovernanceBonusfloatTaxEfficiencyModifierfloatDevelopmentSpeedModifierfloatArmyMoraleBonusfloatRecruitmentSpeedModifierfloatSettlementGrowthModifierfloatUnrestModifierfloatExample
UCLASS()
class UCultOfTheDeep : UReligion
{
default ReligionName = "Cult of the Deep";
default Description = "Followers revere the unfathomable depths of the ocean and the creatures that dwell within.";
default ReligionGroup = n"Mystery";
default ReligionLeaderTitle = "Depth Speaker";
default IconKey = "CultOfTheDeep";
UCultOfTheDeep()
{
MajorDeities.Add("The Leviathan");
MajorDeities.Add("The Drowned One");
MinorDeities.Add("The Tidecaller");
Relics.Add("Pearl of the Abyss");
}
default CunningBonus = 5.0f;
default TaxEfficiencyModifier = 0.05f;
default ArmyMoraleBonus = -5.0f;
default SettlementGrowthModifier = 0.03f;
}Tips
- Religion groups use extensible
FNamevalues. The base game groups aren"Borgutian",n"Pagan", andn"Mystery". ReligionNameandDescriptionareFString, notFText. For production mods, wrap them withLocalization::GetText().ToString().- Stat bonuses on religions apply to all characters of that religion. Keep values modest -- they stack with trait bonuses.
Diseases (UDisease)#
Diseases are epidemics that spread between settlements, affecting population, economy, and characters.
Properties
DiseaseNameFStringDescriptionFTextAssetKeyFNameMapColourFLinearColorBaseTransmissionChancefloatSeaTransmissionMultiplierfloatPopulationDensityMultiplierfloatBaseMortalityRatefloatBaseUnrestContributionfloatFoodProductionPenaltyfloatResourceProductionPenaltyfloatTaxPenaltyfloatMinDurationDaysint32MaxDurationDaysint32BurnoutPopulationThresholdfloatCharacterInfectionChancefloatAfflictionTraitClassTSubclassOf<UTrait>MinPopulationForSpawnint32SpawnChancePerDayfloatbRequiresPortboolbRequiresFoodShortageboolSeasonalMultipliersTMap<ESeason, float>Example
UCLASS()
class URedPox : UDisease
{
default DiseaseName = "Red Pox";
default Description = Localization::GetText("MyMod", "RedPox_Description");
default AssetKey = n"RedPox";
default MapColour = FLinearColor(0.8f, 0.1f, 0.1f, 1.0f);
// Spread
default BaseTransmissionChance = 0.15f;
default SeaTransmissionMultiplier = 0.5f;
default PopulationDensityMultiplier = 1.2f;
// Effects
default BaseMortalityRate = 0.02f;
default BaseUnrestContribution = 5.0f;
default FoodProductionPenalty = 0.1f;
default ResourceProductionPenalty = 0.15f;
default TaxPenalty = 0.1f;
// Duration
default MinDurationDays = 60;
default MaxDurationDays = 180;
default BurnoutPopulationThreshold = 0.7f;
// Characters
default CharacterInfectionChance = 0.05f;
// Spawn conditions
default MinPopulationForSpawn = 5000;
default SpawnChancePerDay = 0.001f;
default bRequiresPort = false;
default bRequiresFoodShortage = false;
URedPox()
{
AfflictionTraitClass = UPoxAfflicted::StaticClass();
SeasonalMultipliers.Add(ESeason::Summer, 1.5f);
SeasonalMultipliers.Add(ESeason::Winter, 0.5f);
}
}Tips
- Keep
BaseMortalityRatelow (0.01--0.05). Even small values cause significant population loss over an epidemic's duration. - The
AfflictionTraitClassshould be a separate trait you define. Create a temporary trait withbIsTemporary = truethat represents the character being sick. BurnoutPopulationThresholdof 0.7 means the disease burns out when population drops to 70% of its pre-epidemic level.SeasonalMultipliersmodify the transmission chance. A summer multiplier of 1.5 means 50% more spread during summer.
Battle Actions (UBattleAction)#
Battle actions are special abilities that army units can use during combat, activated by commanders who meet stat requirements.
Properties
ActionNameFStringDescriptionFStringIconKeyFNameRequiredTacticsint32RequiredAuthorityint32DamageMultiplierfloatDamageTakenMultiplierfloatArmourMultiplierfloatMoraleModifierfloatSpeedMultiplierfloatOverridable Methods
bool CanUseAction(AMilitary Army) constExample
UCLASS()
class UShieldWall : UBattleAction
{
default ActionName = Localization::GetText("MyMod", "ShieldWall_Name").ToString();
default Description = Localization::GetText("MyMod", "ShieldWall_Description").ToString();
default IconKey = n"ShieldWall";
default RequiredTactics = 40;
default RequiredAuthority = 0;
default DamageMultiplier = 0.7f; // Deal 30% less damage
default DamageTakenMultiplier = 0.5f; // Take 50% less damage
default ArmourMultiplier = 1.5f; // 50% more armour
default MoraleModifier = 10.0f; // Morale boost
default SpeedMultiplier = 0.5f; // Half speed (formation is slow)
}Tips
- Battle actions are assigned to unit types via the unit's
BattleActionsarray. A single action can be shared across multiple unit types. - The commander's stats are checked against
RequiredTacticsandRequiredAuthorityat activation time. If the commander doesn't meet the requirements, the action is unavailable. - Multipliers of 1.0 mean no change. Design trade-offs: a powerful defensive action should reduce damage dealt or speed.
ActionNameandDescriptionareFString. Use.ToString()when assigning fromLocalization::GetText().
Next Steps#
- Interactions -- Diplomacy, espionage, character, and power bloc interactions
- Events -- Scripted event system with context slots and chains
- Assets & Packaging -- Icons, DataTables, localisation, and distribution