From 0948d49886c7e43aa1c40804596c57d76bd03537 Mon Sep 17 00:00:00 2001 From: Luis Gonzalez Date: Wed, 10 Jun 2026 17:45:33 -0700 Subject: [PATCH] Combat: ability archetype byte (MC-6 dispatch spike) byte Archetype on AbilityDefBlob (AbilityArchetype enum: Projectile/Hitscan/Cone/Aoe), authored on AbilityDefinition + baked in AbilityDatabaseAuthoring, read at dispatch in AbilityFireSystem -- NOT folded through EffectiveAbilityStats/StatRecomputeSystem (static identity, not a tunable stat; MC-4 review BURST-1). All current abilities are Projectile (0) -> zero behaviour change; the dispatch read-point is the de-risk spike for MC-6 hitscan/cone/aoe. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../Authoring/Combat/AbilityDatabaseAuthoring.cs | 1 + .../Scripts/Authoring/Combat/AbilityDefinition.cs | 2 ++ .../Scripts/Simulation/Combat/AbilityDatabaseBlob.cs | 11 +++++++++++ .../Scripts/Simulation/Combat/AbilityFireSystem.cs | 9 +++++++++ 4 files changed, 23 insertions(+) diff --git a/Assets/_Project/Scripts/Authoring/Combat/AbilityDatabaseAuthoring.cs b/Assets/_Project/Scripts/Authoring/Combat/AbilityDatabaseAuthoring.cs index cee311511..295529497 100644 --- a/Assets/_Project/Scripts/Authoring/Combat/AbilityDatabaseAuthoring.cs +++ b/Assets/_Project/Scripts/Authoring/Combat/AbilityDatabaseAuthoring.cs @@ -47,6 +47,7 @@ namespace ProjectM.Authoring ProjectileSpeed = def.ProjectileSpeed, Range = def.Range, AutoTargetRange = def.AutoTargetRange, + Archetype = (byte)def.Archetype, AutoTargetConeRadians = math.radians(def.AutoTargetConeDegrees), CooldownTicks = def.CooldownTicks, Name = def.DisplayName, diff --git a/Assets/_Project/Scripts/Authoring/Combat/AbilityDefinition.cs b/Assets/_Project/Scripts/Authoring/Combat/AbilityDefinition.cs index d56ca909e..c66ecf6a3 100644 --- a/Assets/_Project/Scripts/Authoring/Combat/AbilityDefinition.cs +++ b/Assets/_Project/Scripts/Authoring/Combat/AbilityDefinition.cs @@ -13,6 +13,8 @@ namespace ProjectM.Authoring public class AbilityDefinition : ScriptableObject { public AbilityId Id = AbilityId.Primary; + [Tooltip("Ability kind for the fire-dispatch. Only Projectile is wired today; the rest are the MC-6 spike.")] + public AbilityArchetype Archetype = AbilityArchetype.Projectile; public string DisplayName = "Ability"; [Header("Combat")] diff --git a/Assets/_Project/Scripts/Simulation/Combat/AbilityDatabaseBlob.cs b/Assets/_Project/Scripts/Simulation/Combat/AbilityDatabaseBlob.cs index fb6cec2ac..64dfec962 100644 --- a/Assets/_Project/Scripts/Simulation/Combat/AbilityDatabaseBlob.cs +++ b/Assets/_Project/Scripts/Simulation/Combat/AbilityDatabaseBlob.cs @@ -3,10 +3,21 @@ using Unity.Entities; namespace ProjectM.Simulation { + /// Ability KIND for the AbilityFireSystem dispatch (MC-4 spike for MC-6). Backed by byte so the + /// baked blob stores a byte (the Burst cross-assembly enum rule); the runtime switch compares the byte value. + public enum AbilityArchetype : byte + { + Projectile = 0, // today's path: spawn a projectile ghost + Hitscan = 1, // MC-6 + Cone = 2, // MC-6 (melee-style cone via the ability system) + Aoe = 3, // MC-6 + } + /// One authored ability definition, baked immutable into the AbilityDatabase blob. public struct AbilityDefBlob { public byte Id; // AbilityId + public byte Archetype; // AbilityArchetype (0 = Projectile); read at dispatch in AbilityFireSystem (MC-6 spike) public float Damage; public float ProjectileSpeed; public float Range; diff --git a/Assets/_Project/Scripts/Simulation/Combat/AbilityFireSystem.cs b/Assets/_Project/Scripts/Simulation/Combat/AbilityFireSystem.cs index 8fb148cdb..4b1545a76 100644 --- a/Assets/_Project/Scripts/Simulation/Combat/AbilityFireSystem.cs +++ b/Assets/_Project/Scripts/Simulation/Combat/AbilityFireSystem.cs @@ -60,6 +60,7 @@ namespace ProjectM.Simulation // Per-ability projectile ghost prefabs live on the AbilityDatabase singleton's companion buffer. var dbEntity = SystemAPI.GetSingletonEntity(); var abilityPrefabs = SystemAPI.GetBuffer(dbEntity); + var abilityDb = SystemAPI.GetSingleton(); bool isServer = state.WorldUnmanaged.IsServer(); @@ -99,6 +100,14 @@ namespace ProjectM.Simulation continue; // still cooling down } + // MC-4 spike for MC-6: dispatch on the authored ability ARCHETYPE byte (baked in the blob, read here -- NOT + // folded through EffectiveAbilityStats; it is static identity, not a tunable stat). All current + // abilities are Projectile (0); hitscan/cone/aoe archetypes plug in at this point in MC-6. + ref var adb = ref abilityDb.Value.Value; + byte archetype = adb.TryGetAbility(abilityRef.ValueRO.Id, out var adef) ? adef.Archetype : (byte)AbilityArchetype.Projectile; + if (archetype != (byte)AbilityArchetype.Projectile) + continue; + // Resolve the projectile ghost prefab for this player's selected ability id. Entity prefab = Entity.Null; for (int i = 0; i < abilityPrefabs.Length; i++)