x2 101 ecs components archetypes - GoldhawkInteractive/X2-Modding GitHub Wiki
Xenonauts 2 uses a custom implementation of the Entity Component System (ECS) pattern called Artitas. Understanding how components and archetypes work is key to effective modding. Before reading this, read up on Archetype.
The XenonautsArchetypes
class is one of the primary sources of documentation for the ECS compositions. This class defines the core archetypes used across all aspects of the game. Some key examples:
// The Campaign archetype, representing a game campaign
public static readonly Archetype Campaign =
Archetype.BaseOn(Singleton)
.ConformingTo(Matcher.All<CampaignTag>()
.All<NameComponent>()
.All<CampaignPlayTimeComponent>()
.All<CampaignStateComponent>())
.ConformingTo(CampaignSettings, true, false)
.ConformingTo(CommonArchetypes.InkStoryPlaybackStorage, true, false)
.ConformingTo(TutorialNotificationStateStorage, true, false);
// The combatant archetype, representing soldiers and aliens
public static readonly Archetype SharedCombatantDefinition =
Archetype.BaseOn(Matcher.BaseOn(CombatantDescription)
.Add(CombatantBaseStats)
.Add(RequiresSightSetup)
.Add(NightVisionFunctionality)
.Add(CanTrackExperience))
.ConformingTo(HasHearing, true, false)
// Many default components...
Different game screens have their own archetype classes:
-
StrategyArchetypes
- Defines archetypes used in the strategy/geoscape layer -
GroundCombatArchetypes
- Defines archetypes used in tactical combat -
AirCombatArchetypes
- Defines archetypes used in air combat
Archetypes can be built through composition, with several methods:
-
BaseOn - Creates a new archetype that inherits all required components from another
Archetype.BaseOn(CombatantDescription)
-
ConformingTo - Adds additional component requirements
.ConformingTo(Matcher.All<InventorySlotTypeComponent>())
-
AddDefault - Specifies default values for components
.AddDefault(new NameComponent {value = "John Doe"})
-
AddFilter - Adds runtime filters for matching entities
.AddFilter<HitPoints>(hp => !hp.AtMinimum())
Entities are created based on archetypes and exist within a World:
// Creating a new entity using an archetype
var entity = World.CreateEntity(XenonautsArchetypes.Campaign);
// Adding a component at runtime
entity.Add(new DescriptionComponent { value = "First Campaign" });
// Checking if an entity matches an archetype
if (XenonautsArchetypes.Combatant.Accepts(entity)) {
// Entity has all components required by the Combatant archetype
}
Singleton archetypes represent unique game elements that should only exist once:
public static readonly Archetype Singleton =
Archetype.ConformingTo(Matcher.All<SingletonGroup>()
.All<NameComponent>()
.All<ComposableFormatterComponent>());
public static readonly Archetype Campaign =
Archetype.BaseOn(Singleton)
// Additional components...
Combatants represent soldiers, aliens, and other units:
public static readonly Archetype CombatantBaseStats =
Matcher.All<HitPoints, TimeUnits, Accuracy, Bravery, Defence, Reflexes, Morale, ResistancesComponent>()
.All<PsionicStrength, Stun, Stress, Strength, Capacity, MedalsComponent, InjuriesComponent>();
These define how items and inventories function:
public static readonly Archetype Inventory =
Archetype.ConformingTo(
Matcher.All<InventoryTaxonomyComponent>()
.All<InventorySlotsLink>());
public static readonly Archetype InventorySlot =
Archetype.ConformingTo(
Matcher.All<InventorySlotTypeComponent, InventorySlotMetaComponent>()
// Other components...
);
Define how maps and missions are structured:
public static readonly Archetype MapMeta =
Archetype.BaseOn(CommonArchetypes.MapMeta)
.ConformingTo(MapMetaProperties)
.ConformingTo(Matcher.All<MapCategory>()
.All<PreferredTimeOfDay>()
.All<PreferredWeather>());
One of the important aspects of archetypes is defining how data transfers between game screens. Specific archetypes define what data is copied:
// Components copied from Strategy to GroundCombat for combatants
public static readonly Archetype CombatantCopiedToGroundCombat =
Matcher.BaseOn(SharedCombatantDefinition)
.All<ProgressComponent, Rank>()
.All<StrategyCombatantMetaComponent>();
// Components copied back from GroundCombat to Strategy
public static readonly Archetype CombatantCopiedToStrategy =
Archetype.BaseOn(CombatantBaseStats)
.ConformingTo(CanTrackExperience)
.ConformingTo(CombatantGCModifications);
These archetypes are used in the serialization systems to ensure proper data transfer between game modes.