diff --git a/Assets/_Project/Prefabs/TrainingDummy.prefab b/Assets/_Project/Prefabs/TrainingDummy.prefab
deleted file mode 100644
index 89718ede0..000000000
--- a/Assets/_Project/Prefabs/TrainingDummy.prefab
+++ /dev/null
@@ -1,147 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!1 &6681740481886397972
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 3040602402374479956}
- - component: {fileID: 9111625462373738953}
- - component: {fileID: 6113974662432286332}
- - component: {fileID: 5080357267889081991}
- - component: {fileID: 3549493811897787778}
- - component: {fileID: 1198698002335808414}
- m_Layer: 0
- m_Name: TrainingDummy
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &3040602402374479956
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 6681740481886397972}
- serializedVersion: 2
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 2, z: 1}
- m_ConstrainProportionsScale: 0
- m_Children: []
- m_Father: {fileID: 0}
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!33 &9111625462373738953
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 6681740481886397972}
- m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
---- !u!23 &6113974662432286332
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 6681740481886397972}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_StaticShadowCaster: 0
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RayTracingMode: 2
- m_RayTraceProcedural: 0
- m_RayTracingAccelStructBuildFlagsOverride: 0
- m_RayTracingAccelStructBuildFlags: 1
- m_SmallMeshCulling: 1
- m_ForceMeshLod: -1
- m_MeshLodSelectionBias: 0
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: f8df9cd33fb974460a903e35a6fce3c9, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_ReceiveGI: 1
- m_PreserveUVs: 1
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 1
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_GlobalIlluminationMeshLod: 0
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
- m_MaskInteraction: 0
- m_AdditionalVertexStreams: {fileID: 0}
---- !u!114 &5080357267889081991
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 6681740481886397972}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: c32aebeb7bfbb464898dfee8e6e87e6c, type: 3}
- m_Name:
- m_EditorClassIdentifier: ProjectM.Authoring::ProjectM.Authoring.TrainingDummyAuthoring
- MaxHealth: 60
- HitRadius: 0.8
---- !u!114 &3549493811897787778
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 6681740481886397972}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: c16549610bfe4458aa9389201d072bb6, type: 3}
- m_Name:
- m_EditorClassIdentifier: Unity.Entities.Hybrid::Unity.Entities.Hybrid.Baking.LinkedEntityGroupAuthoring
---- !u!114 &1198698002335808414
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 6681740481886397972}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 7c79d771cedb4794bf100ce60df5f764, type: 3}
- m_Name:
- m_EditorClassIdentifier: Unity.NetCode.Authoring.Hybrid::Unity.NetCode.GhostAuthoringComponent
- HasOwner: 0
- SupportAutoCommandTarget: 0
- TrackInterpolationDelay: 0
- GhostGroup: 0
- UsePreSerialization: 0
- UseSingleBaseline: 0
- RollbackPredictedSpawnedGhostState: 0
- RollbackPredictionOnStructuralChanges: 1
- DefaultGhostMode: 0
- SupportedGhostModes: 3
- OptimizationMode: 0
- Importance: 1
- MaxSendRate: 0
- prefabId:
diff --git a/Assets/_Project/Prefabs/TrainingDummy.prefab.meta b/Assets/_Project/Prefabs/TrainingDummy.prefab.meta
deleted file mode 100644
index 3ce851656..000000000
--- a/Assets/_Project/Prefabs/TrainingDummy.prefab.meta
+++ /dev/null
@@ -1,7 +0,0 @@
-fileFormatVersion: 2
-guid: 9ee6032b77c444d07a1dc9dfbf5abd68
-PrefabImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/Assets/_Project/Prefabs/UpgradePickup.prefab b/Assets/_Project/Prefabs/UpgradePickup.prefab
deleted file mode 100644
index 7c97ef47d..000000000
--- a/Assets/_Project/Prefabs/UpgradePickup.prefab
+++ /dev/null
@@ -1,181 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!1 &803404312977859260
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 544753127400808733}
- - component: {fileID: 8071270979468917903}
- - component: {fileID: 4362678855125273864}
- m_Layer: 0
- m_Name: Model
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &544753127400808733
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 803404312977859260}
- serializedVersion: 2
- m_LocalRotation: {x: 0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0.4, z: 0}
- m_LocalScale: {x: 1.3, y: 1.3, z: 1.3}
- m_ConstrainProportionsScale: 0
- m_Children: []
- m_Father: {fileID: 3572766465862231365}
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!33 &8071270979468917903
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 803404312977859260}
- m_Mesh: {fileID: 4300000, guid: a52e2d101bf32694d9012060774e97fd, type: 3}
---- !u!23 &4362678855125273864
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 803404312977859260}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_StaticShadowCaster: 0
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RayTracingMode: 2
- m_RayTraceProcedural: 0
- m_RayTracingAccelStructBuildFlagsOverride: 0
- m_RayTracingAccelStructBuildFlags: 1
- m_SmallMeshCulling: 1
- m_ForceMeshLod: -1
- m_MeshLodSelectionBias: 0
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: 71e41e43b459a244abaf5acca76b89ee, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_ReceiveGI: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 1
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_GlobalIlluminationMeshLod: 0
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
- m_MaskInteraction: 0
- m_AdditionalVertexStreams: {fileID: 0}
---- !u!1 &3885353946372160549
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 3572766465862231365}
- - component: {fileID: 6410754845414010269}
- - component: {fileID: 9053853372340598254}
- - component: {fileID: 6834786618115927220}
- m_Layer: 0
- m_Name: UpgradePickup
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &3572766465862231365
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 3885353946372160549}
- serializedVersion: 2
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_ConstrainProportionsScale: 0
- m_Children:
- - {fileID: 544753127400808733}
- m_Father: {fileID: 0}
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!114 &6410754845414010269
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 3885353946372160549}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 07e6d40378fcb43c5be706ef96cb4bb2, type: 3}
- m_Name:
- m_EditorClassIdentifier: ProjectM.Authoring::ProjectM.Authoring.UpgradePickupAuthoring
- Target: 0
- Op: 0
- Value: 10
- HitRadius: 1.2
---- !u!114 &9053853372340598254
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 3885353946372160549}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: c16549610bfe4458aa9389201d072bb6, type: 3}
- m_Name:
- m_EditorClassIdentifier: Unity.Entities.Hybrid::Unity.Entities.Hybrid.Baking.LinkedEntityGroupAuthoring
---- !u!114 &6834786618115927220
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 3885353946372160549}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 7c79d771cedb4794bf100ce60df5f764, type: 3}
- m_Name:
- m_EditorClassIdentifier: Unity.NetCode.Authoring.Hybrid::Unity.NetCode.GhostAuthoringComponent
- HasOwner: 0
- SupportAutoCommandTarget: 1
- TrackInterpolationDelay: 0
- GhostGroup: 0
- UsePreSerialization: 0
- UseSingleBaseline: 0
- RollbackPredictedSpawnedGhostState: 0
- RollbackPredictionOnStructuralChanges: 1
- DefaultGhostMode: 0
- SupportedGhostModes: 3
- OptimizationMode: 0
- Importance: 1
- MaxSendRate: 0
- prefabId:
diff --git a/Assets/_Project/Prefabs/UpgradePickup.prefab.meta b/Assets/_Project/Prefabs/UpgradePickup.prefab.meta
deleted file mode 100644
index bb9a1a5a4..000000000
--- a/Assets/_Project/Prefabs/UpgradePickup.prefab.meta
+++ /dev/null
@@ -1,7 +0,0 @@
-fileFormatVersion: 2
-guid: d7dd0078c7b1f4cf995ca3a4b1155569
-PrefabImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/Assets/_Project/Scripts/Authoring/Combat/TrainingDummyAuthoring.cs b/Assets/_Project/Scripts/Authoring/Combat/TrainingDummyAuthoring.cs
deleted file mode 100644
index c5562c923..000000000
--- a/Assets/_Project/Scripts/Authoring/Combat/TrainingDummyAuthoring.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using ProjectM.Simulation;
-using Unity.Entities;
-using UnityEngine;
-
-namespace ProjectM.Authoring
-{
- ///
- /// Authoring for the training-dummy enemy prefab. Bakes a stationary, damageable auto-target
- /// candidate: marks it for the ability auto-target cone,
- /// and make it a valid projectile hit target, and a
- /// buffer receives server-authoritative hits. Dummies are NOT ghosts and
- /// carry no GhostOwner, so projectiles never treat them as the firing owner.
- /// GetEntity(TransformUsageFlags.Dynamic) ensures a runtime LocalTransform for hit tests
- /// and spawn placement.
- ///
- public class TrainingDummyAuthoring : MonoBehaviour
- {
- [Min(0f), Tooltip("Starting and maximum health for the dummy.")]
- public float MaxHealth = 60f;
-
- [Min(0f), Tooltip("World-unit radius used by the projectile hit test.")]
- public float HitRadius = 0.8f;
-
- private class TrainingDummyBaker : Baker
- {
- public override void Bake(TrainingDummyAuthoring authoring)
- {
- var entity = GetEntity(authoring, TransformUsageFlags.Dynamic);
-
- AddComponent(entity);
- AddComponent(entity, new Health
- {
- Current = authoring.MaxHealth,
- Max = authoring.MaxHealth
- });
- AddComponent(entity, new HitRadius { Value = authoring.HitRadius });
- AddBuffer(entity);
- }
- }
- }
-}
diff --git a/Assets/_Project/Scripts/Authoring/Combat/TrainingDummyAuthoring.cs.meta b/Assets/_Project/Scripts/Authoring/Combat/TrainingDummyAuthoring.cs.meta
deleted file mode 100644
index abd5135ec..000000000
--- a/Assets/_Project/Scripts/Authoring/Combat/TrainingDummyAuthoring.cs.meta
+++ /dev/null
@@ -1,2 +0,0 @@
-fileFormatVersion: 2
-guid: c32aebeb7bfbb464898dfee8e6e87e6c
\ No newline at end of file
diff --git a/Assets/_Project/Scripts/Authoring/Combat/TrainingDummySpawnerAuthoring.cs b/Assets/_Project/Scripts/Authoring/Combat/TrainingDummySpawnerAuthoring.cs
deleted file mode 100644
index 3930f87cc..000000000
--- a/Assets/_Project/Scripts/Authoring/Combat/TrainingDummySpawnerAuthoring.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-using ProjectM.Simulation;
-using Unity.Entities;
-using UnityEngine;
-
-namespace ProjectM.Authoring
-{
- ///
- /// Authoring for the baked singleton. Place this on a single
- /// GameObject in the gameplay subscene; at runtime the server-only
- /// TrainingDummySpawnSystem reads the singleton, instantiates dummies
- /// laid out along +X from at intervals, then destroys
- /// the singleton so it fires exactly once. The entity itself carries no transform
- /// (TransformUsageFlags.None); only the referenced needs a
- /// runtime-mutable LocalTransform (TransformUsageFlags.Dynamic).
- ///
- public class TrainingDummySpawnerAuthoring : MonoBehaviour
- {
- [Tooltip("Training dummy prefab to instantiate. Must carry TrainingDummyAuthoring.")]
- public GameObject DummyPrefab;
-
- [Min(0)]
- [Tooltip("How many dummies to spawn.")]
- public int Count = 3;
-
- [Min(0f)]
- [Tooltip("World-unit spacing between consecutive dummies along +X.")]
- public float Spacing = 3f;
-
- [Tooltip("World-space position of the first dummy.")]
- public Vector3 Origin = new Vector3(0, 0, 8);
-
- private class TrainingDummySpawnerBaker : Baker
- {
- public override void Bake(TrainingDummySpawnerAuthoring authoring)
- {
- var entity = GetEntity(authoring, TransformUsageFlags.None);
-
- AddComponent(entity, new TrainingDummySpawner
- {
- Prefab = GetEntity(authoring.DummyPrefab, TransformUsageFlags.Dynamic),
- Count = authoring.Count,
- Spacing = authoring.Spacing,
- Origin = authoring.Origin
- });
- }
- }
- }
-}
diff --git a/Assets/_Project/Scripts/Authoring/Combat/TrainingDummySpawnerAuthoring.cs.meta b/Assets/_Project/Scripts/Authoring/Combat/TrainingDummySpawnerAuthoring.cs.meta
deleted file mode 100644
index 4b93198fe..000000000
--- a/Assets/_Project/Scripts/Authoring/Combat/TrainingDummySpawnerAuthoring.cs.meta
+++ /dev/null
@@ -1,2 +0,0 @@
-fileFormatVersion: 2
-guid: 51cc543c146d84239ba6dc219221df18
\ No newline at end of file
diff --git a/Assets/_Project/Scripts/Authoring/Combat/UpgradePickupAuthoring.cs b/Assets/_Project/Scripts/Authoring/Combat/UpgradePickupAuthoring.cs
deleted file mode 100644
index e6497da0c..000000000
--- a/Assets/_Project/Scripts/Authoring/Combat/UpgradePickupAuthoring.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-using ProjectM.Simulation;
-using Unity.Entities;
-using UnityEngine;
-
-namespace ProjectM.Authoring
-{
- ///
- /// Authoring for an upgrade pickup ghost prefab: a world object that grants one stat modifier to the
- /// first player that overlaps it (server-authoritative, applied by UpgradePickupSystem) and
- /// then despawns. Bake the prefab as an interpolated ghost (add a GhostAuthoringComponent) so clients
- /// see it appear and despawn. GetEntity(TransformUsageFlags.Dynamic) gives it a world transform.
- ///
- public class UpgradePickupAuthoring : MonoBehaviour
- {
- [Tooltip("Which stat the granted modifier targets.")]
- public StatTarget Target = StatTarget.Damage;
-
- [Tooltip("How the granted modifier combines.")]
- public ModOp Op = ModOp.Flat;
-
- [Tooltip("Modifier magnitude: flat amount, or fractional percent (0.1 = +10%).")]
- public float Value = 10f;
-
- [Tooltip("Overlap radius (world units) for the player pickup test.")]
- [Min(0f)] public float HitRadius = 1f;
-
- private class UpgradePickupBaker : Baker
- {
- public override void Bake(UpgradePickupAuthoring authoring)
- {
- var entity = GetEntity(authoring, TransformUsageFlags.Dynamic);
- AddComponent(entity, new UpgradePickup
- {
- Target = (byte)authoring.Target,
- Op = (byte)authoring.Op,
- Value = authoring.Value,
- SourceId = 0u,
- });
- AddComponent(entity, new HitRadius { Value = authoring.HitRadius });
- }
- }
- }
-}
diff --git a/Assets/_Project/Scripts/Authoring/Combat/UpgradePickupAuthoring.cs.meta b/Assets/_Project/Scripts/Authoring/Combat/UpgradePickupAuthoring.cs.meta
deleted file mode 100644
index dbd44fab0..000000000
--- a/Assets/_Project/Scripts/Authoring/Combat/UpgradePickupAuthoring.cs.meta
+++ /dev/null
@@ -1,2 +0,0 @@
-fileFormatVersion: 2
-guid: 07e6d40378fcb43c5be706ef96cb4bb2
\ No newline at end of file
diff --git a/Assets/_Project/Scripts/Authoring/Combat/UpgradePickupSpawnerAuthoring.cs b/Assets/_Project/Scripts/Authoring/Combat/UpgradePickupSpawnerAuthoring.cs
deleted file mode 100644
index 3fa94b3f5..000000000
--- a/Assets/_Project/Scripts/Authoring/Combat/UpgradePickupSpawnerAuthoring.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-using ProjectM.Simulation;
-using Unity.Entities;
-using UnityEngine;
-
-namespace ProjectM.Authoring
-{
- ///
- /// Authoring for the baked singleton (mirrors
- /// TrainingDummySpawnerAuthoring). Place on a single GameObject in the gameplay subscene; the
- /// server-only UpgradePickupSpawnSystem reads it, spawns pickups along +X
- /// from at intervals, then destroys the singleton so it
- /// fires exactly once. The entity carries no transform; only the prefab needs a runtime transform.
- ///
- public class UpgradePickupSpawnerAuthoring : MonoBehaviour
- {
- [Tooltip("Upgrade pickup prefab to instantiate. Must carry UpgradePickupAuthoring.")]
- public GameObject PickupPrefab;
-
- [Min(0)]
- [Tooltip("How many pickups to spawn.")]
- public int Count = 2;
-
- [Min(0f)]
- [Tooltip("World-unit spacing between consecutive pickups along +X.")]
- public float Spacing = 3f;
-
- [Tooltip("World-space position of the first pickup.")]
- public Vector3 Origin = new Vector3(-4f, 0f, 6f);
-
- private class UpgradePickupSpawnerBaker : Baker
- {
- public override void Bake(UpgradePickupSpawnerAuthoring authoring)
- {
- var entity = GetEntity(authoring, TransformUsageFlags.None);
-
- AddComponent(entity, new UpgradePickupSpawner
- {
- Prefab = authoring.PickupPrefab != null
- ? GetEntity(authoring.PickupPrefab, TransformUsageFlags.Dynamic)
- : Entity.Null,
- Count = authoring.Count,
- Spacing = authoring.Spacing,
- Origin = authoring.Origin,
- });
- }
- }
- }
-}
diff --git a/Assets/_Project/Scripts/Authoring/Combat/UpgradePickupSpawnerAuthoring.cs.meta b/Assets/_Project/Scripts/Authoring/Combat/UpgradePickupSpawnerAuthoring.cs.meta
deleted file mode 100644
index bcc91b7b9..000000000
--- a/Assets/_Project/Scripts/Authoring/Combat/UpgradePickupSpawnerAuthoring.cs.meta
+++ /dev/null
@@ -1,2 +0,0 @@
-fileFormatVersion: 2
-guid: e367eb55e2c2248f18be10d6c3c9ad67
\ No newline at end of file
diff --git a/Assets/_Project/Scripts/Client/Building/BuildSendSystem.cs b/Assets/_Project/Scripts/Client/Building/BuildSendSystem.cs
index cfc4a88c1..14370a22d 100644
--- a/Assets/_Project/Scripts/Client/Building/BuildSendSystem.cs
+++ b/Assets/_Project/Scripts/Client/Building/BuildSendSystem.cs
@@ -16,14 +16,13 @@ namespace ProjectM.Client
/// ), so the place-click never also fires. Build mode is suspended while
/// the pause overlay is open, and the frame a palette button changes the selection never also places.
/// (2) keyboard hotkeys (fallback, suppressed in palette mode): B/V/F place at the local player's cell.
- /// Editor-only statics (PlaceStructure / PlaceHarvester / ...) drive the same RPC path from execute_code for
+ /// Editor-only statics (PlaceStructure / PlaceTurret / ...) drive the same RPC path from execute_code for
/// headless validation. Managed SystemBase; UnityEngine.InputSystem types are fully qualified to avoid the
/// ProjectM.Simulation.PlayerInput name collision. The server re-validates legality + cost authoritatively.
///
[WorldSystemFilter(WorldSystemFilterFlags.ClientSimulation)]
public partial class BuildSendSystem : SystemBase
{
- static byte s_ConveyorDir; // key-flow pending conveyor facing (0=+X,1=-X,2=+Z,3=-Z)
// Dev hotkey fallback: key -> buildable (Conveyor uses s_ConveyorDir for facing).
static readonly (UnityEngine.InputSystem.Key Key, byte Type)[] s_BuildHotkeys =
@@ -62,18 +61,9 @@ namespace ProjectM.Client
/// EDITOR / execute_code hook: queue a wall placement at a specific cell.
public static void PlaceWall(int cellX, int cellZ) => PlaceStructure(StructureType.Wall, cellX, cellZ);
- /// EDITOR / execute_code hook: queue a pylon placement at a specific cell.
- public static void PlacePylon(int cellX, int cellZ) => PlaceStructure(StructureType.Pylon, cellX, cellZ);
-
- /// EDITOR / execute_code hook: queue a harvester placement at a specific cell.
- public static void PlaceHarvester(int cellX, int cellZ) => PlaceStructure(StructureType.Harvester, cellX, cellZ);
-
/// EDITOR / execute_code hook: queue a fabricator placement at a specific cell.
public static void PlaceFabricator(int cellX, int cellZ) => PlaceStructure(StructureType.Fabricator, cellX, cellZ);
- /// EDITOR / execute_code hook: queue a conveyor placement facing direction (0=+X,1=-X,2=+Z,3=-Z).
- public static void PlaceConveyor(int cellX, int cellZ, byte direction) => PlaceStructure(StructureType.Conveyor, cellX, cellZ, direction);
-
#endif
protected override void OnCreate()
@@ -106,14 +96,9 @@ namespace ProjectM.Client
// Hotkey fallback (suppressed while the palette build mode is active).
if (keyboard != null && !BuildPaletteState.Active)
{
- if (keyboard.leftBracketKey.wasPressedThisFrame)
- s_ConveyorDir = (byte)((s_ConveyorDir + 3) % 4);
- if (keyboard.rightBracketKey.wasPressedThisFrame)
- s_ConveyorDir = (byte)((s_ConveyorDir + 1) % 4);
-
foreach (var (key, type) in s_BuildHotkeys)
if (keyboard[key].wasPressedThisFrame && TryGetLocalPlayerCell(out int2 cell))
- SendBuild(connection, type, cell.x, cell.y, type == StructureType.Conveyor ? s_ConveyorDir : (byte)0);
+ SendBuild(connection, type, cell.x, cell.y, (byte)0);
}
#if UNITY_EDITOR
diff --git a/Assets/_Project/Scripts/Client/Presentation/FeelConfig.cs b/Assets/_Project/Scripts/Client/Presentation/FeelConfig.cs
index e2ecd9da8..d132e2bf3 100644
--- a/Assets/_Project/Scripts/Client/Presentation/FeelConfig.cs
+++ b/Assets/_Project/Scripts/Client/Presentation/FeelConfig.cs
@@ -45,8 +45,6 @@ namespace ProjectM.Client
public static float HitStopRefDamage;
/// Tint for the (deferred) enemy material hit-flash — exposed now, wired in the ShaderGraph slice.
public static Color HitFlashColor;
- /// Duration (ms) of the deferred enemy hit-flash.
- public static float HitFlashDurationMs;
/// Master gate for the (deferred) true freeze-frame hit-stop. FALSE for v1 (camera-punch only).
public static bool HitStopFreezeEnabled;
@@ -130,8 +128,6 @@ namespace ProjectM.Client
public static float RumbleHit;
/// Rumble strength on a kill.
public static float RumbleKill;
- /// Rumble strength on dash / local death (the heaviest).
- public static float RumbleHeavy;
/// Seconds a rumble pulse lasts before it auto-stops.
public static float RumbleDurationSec;
@@ -190,7 +186,6 @@ namespace ProjectM.Client
HitStopMaxFrames = 2; // C4: a 2-frame (~33ms) camera hold reads as crunch, not a lag-y stutter
HitStopRefDamage = 30f;
HitFlashColor = new Color(1f, 0.85f, 0.55f, 1f);
- HitFlashDurationMs = 80f;
HitStopFreezeEnabled = true; // C4: enable the finisher hit-stop hold (presentation-only camera freeze, bounded below)
// Feature 1/2 death
@@ -239,7 +234,6 @@ namespace ProjectM.Client
RumbleEnabled = true;
RumbleHit = 0.25f;
RumbleKill = 0.45f;
- RumbleHeavy = 0.6f;
RumbleDurationSec = 0.12f;
// Deferred-items pass (2026-06)
diff --git a/Assets/_Project/Scripts/Client/UI/HudUi.cs b/Assets/_Project/Scripts/Client/UI/HudUi.cs
index 3bd2bb1fe..646c166aa 100644
--- a/Assets/_Project/Scripts/Client/UI/HudUi.cs
+++ b/Assets/_Project/Scripts/Client/UI/HudUi.cs
@@ -146,8 +146,6 @@ namespace ProjectM.Client
return e;
}
- /// True when the theme is loaded and a sprite is present (callers choose icon vs text fallback).
-
///
/// An input-prompt chip: the Synty key/button glyph (left untinted to keep its printed face) when present,
@@ -170,7 +168,5 @@ namespace ProjectM.Client
return cap;
}
- /// Apply a uniform 9-slice (horizontal / vertical source-texture px) to a skinned element.
-
}
}
diff --git a/Assets/_Project/Scripts/Server/Combat/HealthApplyDamageSystem.cs b/Assets/_Project/Scripts/Server/Combat/HealthApplyDamageSystem.cs
index 9334c83d7..b878a8e5b 100644
--- a/Assets/_Project/Scripts/Server/Combat/HealthApplyDamageSystem.cs
+++ b/Assets/_Project/Scripts/Server/Combat/HealthApplyDamageSystem.cs
@@ -13,7 +13,7 @@ namespace ProjectM.Server
/// this tick), subtracts the summed amount from , then clears the buffer so
/// each hit is applied exactly once. Entities that carry character stats (players) clamp to their
/// data-driven ceiling; others (training dummies)
- /// clamp at zero. A dead is destroyed; player death is deferred.
+ /// clamp at zero. A dead is destroyed; player death is deferred.
/// Health.Current is a [GhostField], so the new value replicates to clients for display.
///
/// Runs server-only () inside the prediction
@@ -156,7 +156,7 @@ namespace ProjectM.Server
if (SystemAPI.HasComponent(entity)) SystemAPI.SetComponentEnabled(entity, false);
}
}
- else if (SystemAPI.HasComponent(entity) || SystemAPI.HasComponent(entity) || SystemAPI.HasComponent(entity))
+ else if (SystemAPI.HasComponent(entity) || SystemAPI.HasComponent(entity))
ecb.DestroyEntity(entity);
}
}
diff --git a/Assets/_Project/Scripts/Server/Combat/TrainingDummySpawnSystem.cs b/Assets/_Project/Scripts/Server/Combat/TrainingDummySpawnSystem.cs
deleted file mode 100644
index ef3b4e0dd..000000000
--- a/Assets/_Project/Scripts/Server/Combat/TrainingDummySpawnSystem.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using ProjectM.Simulation;
-using Unity.Burst;
-using Unity.Collections;
-using Unity.Entities;
-using Unity.Mathematics;
-using Unity.Transforms;
-
-namespace ProjectM.Server
-{
- ///
- /// Server-only, one-shot dummy spawner. On its first update it reads the baked
- /// singleton and instantiates Count training-dummy
- /// ghosts in a row, spaced Spacing world-units apart along +X starting at Origin.
- /// It then destroys the spawner singleton entity so RequireForUpdate
- /// is no longer satisfied and the system stops running (idempotent: dummies are spawned exactly once).
- /// Runs in the default (NOT the prediction loop) since spawning is
- /// a non-predicted, server-authoritative event; the dummies replicate to clients as interpolated ghosts.
- /// All structural changes are batched through an .
- ///
- [BurstCompile]
- [WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]
- public partial struct TrainingDummySpawnSystem : ISystem
- {
- [BurstCompile]
- public void OnCreate(ref SystemState state)
- {
- state.RequireForUpdate();
- }
-
- [BurstCompile]
- public void OnUpdate(ref SystemState state)
- {
- // Grab both the singleton entity (to destroy when done) and its baked config.
- var spawnerEntity = SystemAPI.GetSingletonEntity();
- var spawner = SystemAPI.GetComponent(spawnerEntity);
-
- var ecb = new EntityCommandBuffer(Allocator.Temp);
-
- for (int i = 0; i < spawner.Count; i++)
- {
- var dummy = ecb.Instantiate(spawner.Prefab);
- var position = spawner.Origin + new float3(i * spawner.Spacing, 0f, 0f);
- ecb.SetComponent(dummy, LocalTransform.FromPosition(position));
- }
-
- // One-shot: remove the spawner so RequireForUpdate fails and the system idles.
- ecb.DestroyEntity(spawnerEntity);
-
- ecb.Playback(state.EntityManager);
- }
- }
-}
diff --git a/Assets/_Project/Scripts/Server/Combat/TrainingDummySpawnSystem.cs.meta b/Assets/_Project/Scripts/Server/Combat/TrainingDummySpawnSystem.cs.meta
deleted file mode 100644
index e74f5b35c..000000000
--- a/Assets/_Project/Scripts/Server/Combat/TrainingDummySpawnSystem.cs.meta
+++ /dev/null
@@ -1,2 +0,0 @@
-fileFormatVersion: 2
-guid: 7673acbc74f7a4bddbca0679122511ea
\ No newline at end of file
diff --git a/Assets/_Project/Scripts/Server/Combat/UpgradePickupSpawnSystem.cs b/Assets/_Project/Scripts/Server/Combat/UpgradePickupSpawnSystem.cs
deleted file mode 100644
index 26887825e..000000000
--- a/Assets/_Project/Scripts/Server/Combat/UpgradePickupSpawnSystem.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-using ProjectM.Simulation;
-using Unity.Burst;
-using Unity.Collections;
-using Unity.Entities;
-using Unity.Mathematics;
-using Unity.Transforms;
-
-namespace ProjectM.Server
-{
- ///
- /// Server-only, one-shot upgrade-pickup spawner (mirrors TrainingDummySpawnSystem). On its first
- /// update it reads the baked singleton and instantiates
- /// Count pickup ghosts in a row, spaced Spacing world-units apart along +X starting at
- /// Origin, then destroys the singleton so the system idles (spawned exactly once). Runs in the
- /// default (NOT the prediction loop); pickups replicate to clients
- /// as interpolated ghosts. Structural changes are batched through an .
- ///
- [BurstCompile]
- [WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]
- public partial struct UpgradePickupSpawnSystem : ISystem
- {
- [BurstCompile]
- public void OnCreate(ref SystemState state)
- {
- state.RequireForUpdate();
- }
-
- [BurstCompile]
- public void OnUpdate(ref SystemState state)
- {
- var spawnerEntity = SystemAPI.GetSingletonEntity();
- var spawner = SystemAPI.GetComponent(spawnerEntity);
-
- var ecb = new EntityCommandBuffer(Allocator.Temp);
-
- if (spawner.Prefab != Entity.Null)
- {
- // Preserve the prefab's baked scale/rotation (FromPosition would reset Scale to 1).
- var baseXform = SystemAPI.GetComponent(spawner.Prefab);
- for (int i = 0; i < spawner.Count; i++)
- {
- var pickup = ecb.Instantiate(spawner.Prefab);
- var position = spawner.Origin + new float3(i * spawner.Spacing, 0f, 0f);
- var xform = baseXform;
- xform.Position = position;
- ecb.SetComponent(pickup, xform);
- }
- }
-
- // One-shot: remove the spawner so RequireForUpdate fails and the system idles.
- ecb.DestroyEntity(spawnerEntity);
-
- ecb.Playback(state.EntityManager);
- }
- }
-}
diff --git a/Assets/_Project/Scripts/Server/Combat/UpgradePickupSpawnSystem.cs.meta b/Assets/_Project/Scripts/Server/Combat/UpgradePickupSpawnSystem.cs.meta
deleted file mode 100644
index 7b0ffc0b7..000000000
--- a/Assets/_Project/Scripts/Server/Combat/UpgradePickupSpawnSystem.cs.meta
+++ /dev/null
@@ -1,2 +0,0 @@
-fileFormatVersion: 2
-guid: 602544c80ca5649258a9d6ca9ad74f79
\ No newline at end of file
diff --git a/Assets/_Project/Scripts/Server/Combat/UpgradePickupSystem.cs b/Assets/_Project/Scripts/Server/Combat/UpgradePickupSystem.cs
deleted file mode 100644
index 835d4d97a..000000000
--- a/Assets/_Project/Scripts/Server/Combat/UpgradePickupSystem.cs
+++ /dev/null
@@ -1,78 +0,0 @@
-using ProjectM.Simulation;
-using Unity.Burst;
-using Unity.Collections;
-using Unity.Entities;
-using Unity.Mathematics;
-using Unity.Transforms;
-
-namespace ProjectM.Server
-{
- ///
- /// Server-authoritative upgrade pickup grant. When a player overlaps an
- /// (planar XZ distance within the pickup's ), appends the pickup's modifier to
- /// the player's replicated buffer (which replicates to the predicting
- /// owner, so StatRecomputeSystem folds identical effective stats on both worlds) and destroys the
- /// pickup. Runs in the default (NOT the prediction loop) since the
- /// grant is a non-predicted server event. The buffer append + pickup destroy are batched through an
- /// played back immediately — so a plain-world EditMode test needs no
- /// separate ECB system.
- ///
- [BurstCompile]
- [WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]
- public partial struct UpgradePickupSystem : ISystem
- {
- [BurstCompile]
- public void OnCreate(ref SystemState state)
- {
- state.RequireForUpdate();
- }
-
- [BurstCompile]
- public void OnUpdate(ref SystemState state)
- {
- // Snapshot modifiable players (carrying the modifier buffer + a transform) once this tick.
- var playerEntities = new NativeList(Allocator.Temp);
- var playerPositions = new NativeList(Allocator.Temp);
- foreach (var (xform, e) in
- SystemAPI.Query>()
- .WithAll()
- .WithEntityAccess())
- {
- playerEntities.Add(e);
- playerPositions.Add(xform.ValueRO.Position);
- }
-
- var ecb = new EntityCommandBuffer(Allocator.Temp);
-
- foreach (var (xform, radius, pickup, pickupEntity) in
- SystemAPI.Query, RefRO, RefRO>()
- .WithEntityAccess())
- {
- float2 pp = new float2(xform.ValueRO.Position.x, xform.ValueRO.Position.z);
- float r = radius.ValueRO.Value;
-
- for (int i = 0; i < playerEntities.Length; i++)
- {
- float2 cp = new float2(playerPositions[i].x, playerPositions[i].z);
- if (math.distancesq(pp, cp) > r * r)
- continue;
-
- ecb.AppendToBuffer(playerEntities[i], new StatModifier
- {
- Target = pickup.ValueRO.Target,
- Op = pickup.ValueRO.Op,
- Value = pickup.ValueRO.Value,
- SourceId = pickup.ValueRO.SourceId,
- });
- ecb.DestroyEntity(pickupEntity);
- break; // granted to the first overlapping player, then despawns
- }
- }
-
- ecb.Playback(state.EntityManager);
- ecb.Dispose();
- playerEntities.Dispose();
- playerPositions.Dispose();
- }
- }
-}
diff --git a/Assets/_Project/Scripts/Server/Combat/UpgradePickupSystem.cs.meta b/Assets/_Project/Scripts/Server/Combat/UpgradePickupSystem.cs.meta
deleted file mode 100644
index 5906cc7f1..000000000
--- a/Assets/_Project/Scripts/Server/Combat/UpgradePickupSystem.cs.meta
+++ /dev/null
@@ -1,2 +0,0 @@
-fileFormatVersion: 2
-guid: c3d9ef25fbc464e52aa342b531d6f35e
\ No newline at end of file
diff --git a/Assets/_Project/Scripts/Server/World/RegionTransitSystem.cs b/Assets/_Project/Scripts/Server/World/RegionTransitSystem.cs
deleted file mode 100644
index e32069e92..000000000
--- a/Assets/_Project/Scripts/Server/World/RegionTransitSystem.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-using ProjectM.Simulation;
-using Unity.Burst;
-using Unity.Collections;
-using Unity.Entities;
-using Unity.NetCode;
-using Unity.Transforms;
-
-namespace ProjectM.Server
-{
- ///
- /// Server-authoritative handler for RPCs. Resolves the sender's player
- /// (via the source connection's -> ), flips its
- /// to the requested region, and teleports it to that region's origin
- /// (, centered on the base via ).
- /// Runs in the default server SimulationSystemGroup (NOT the prediction loop) so the transit applies once;
- /// the next snapshot reconciles the owner-predicted client and re-scopes
- /// which region's ghosts the connection receives. Mirrors the RPC shape.
- ///
- [BurstCompile]
- [WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]
- public partial struct RegionTransitSystem : ISystem
- {
- [BurstCompile]
- public void OnCreate(ref SystemState state)
- {
- state.RequireForUpdate();
-
- var builder = new EntityQueryBuilder(Allocator.Temp)
- .WithAll();
- state.RequireForUpdate(state.GetEntityQuery(builder));
- }
-
- [BurstCompile]
- public void OnUpdate(ref SystemState state)
- {
- var baseCenter = BaseGridMath.PlotCenter(SystemAPI.GetSingleton());
-
- // Map connection NetworkId -> player entity.
- var playerByConn = new NativeHashMap(8, Allocator.Temp);
- foreach (var (owner, entity) in
- SystemAPI.Query>().WithAll().WithEntityAccess())
- {
- playerByConn[owner.ValueRO.NetworkId] = entity;
- }
-
- var ecb = new EntityCommandBuffer(Allocator.Temp);
-
- foreach (var (request, receive, requestEntity) in
- SystemAPI.Query, RefRO>().WithEntityAccess())
- {
- var connEntity = receive.ValueRO.SourceConnection;
- if (SystemAPI.HasComponent(connEntity))
- {
- int connId = SystemAPI.GetComponent(connEntity).Value;
- if (playerByConn.TryGetValue(connId, out var player))
- {
- byte target = request.ValueRO.TargetRegion;
- SystemAPI.GetComponentRW(player).ValueRW.Region = target;
- SystemAPI.GetComponentRW(player).ValueRW.Position =
- RegionMath.RegionOrigin(target, baseCenter);
- }
- }
-
- ecb.DestroyEntity(requestEntity);
- }
-
- ecb.Playback(state.EntityManager);
- playerByConn.Dispose();
- }
- }
-}
diff --git a/Assets/_Project/Scripts/Server/World/RegionTransitSystem.cs.meta b/Assets/_Project/Scripts/Server/World/RegionTransitSystem.cs.meta
deleted file mode 100644
index 24e0f66ef..000000000
--- a/Assets/_Project/Scripts/Server/World/RegionTransitSystem.cs.meta
+++ /dev/null
@@ -1,2 +0,0 @@
-fileFormatVersion: 2
-guid: 44d6ce89f189d984c83cd213d86d4b02
\ No newline at end of file
diff --git a/Assets/_Project/Scripts/Simulation/Combat/AbilityFireSystem.cs b/Assets/_Project/Scripts/Simulation/Combat/AbilityFireSystem.cs
index 699062bd0..e597b1fcc 100644
--- a/Assets/_Project/Scripts/Simulation/Combat/AbilityFireSystem.cs
+++ b/Assets/_Project/Scripts/Simulation/Combat/AbilityFireSystem.cs
@@ -80,7 +80,7 @@ namespace ProjectM.Simulation
if (isServer)
{
foreach (var (tx, th, te) in
- SystemAPI.Query, RefRO>().WithAny().WithEntityAccess())
+ SystemAPI.Query, RefRO>().WithAll().WithEntityAccess())
{
if (th.ValueRO.Current <= 0f) continue; // B3: corpses are neither aim magnets nor cleave targets
candidatePositions.Add(tx.ValueRO.Position);
diff --git a/Assets/_Project/Scripts/Simulation/Combat/Destructible.cs b/Assets/_Project/Scripts/Simulation/Combat/Destructible.cs
index 8f4eae4ae..d0a483e38 100644
--- a/Assets/_Project/Scripts/Simulation/Combat/Destructible.cs
+++ b/Assets/_Project/Scripts/Simulation/Combat/Destructible.cs
@@ -4,7 +4,7 @@ namespace ProjectM.Simulation
{
///
/// EB-1 — opt-in marker for an entity that DESTROYS when
- /// its hits 0 (alongside TrainingDummyTag/EnemyTag). Baked ONLY on the
+ /// its hits 0 (alongside EnemyTag). Baked ONLY on the
/// player-built structure ghosts (Turret/Wall/Pylon) so "machines can die". DELIBERATELY a distinct tag rather
/// than gating on bare : that identity is SHARED by the reserved M7 automation
/// machines (Harvester/Fabricator/Conveyor) whose teardown would silently drop in-flight conveyor cargo — the
diff --git a/Assets/_Project/Scripts/Simulation/Combat/Health.cs b/Assets/_Project/Scripts/Simulation/Combat/Health.cs
index 43c65bc08..5037f4cc2 100644
--- a/Assets/_Project/Scripts/Simulation/Combat/Health.cs
+++ b/Assets/_Project/Scripts/Simulation/Combat/Health.cs
@@ -7,7 +7,7 @@ namespace ProjectM.Simulation
/// Hit points for any damageable ghost (players, training dummies). Server-authoritative:
/// only server systems write ; clients receive it via the [GhostField]
/// for display and prediction reconciliation. is baked identically on both
- /// worlds and is not replicated. Added by PlayerBaker / TrainingDummyBaker.
+ /// worlds and is not replicated. Added by PlayerBaker.
///
public struct Health : IComponentData
{
diff --git a/Assets/_Project/Scripts/Simulation/Combat/TrainingDummySpawner.cs b/Assets/_Project/Scripts/Simulation/Combat/TrainingDummySpawner.cs
deleted file mode 100644
index cbd3937d5..000000000
--- a/Assets/_Project/Scripts/Simulation/Combat/TrainingDummySpawner.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using Unity.Entities;
-using Unity.Mathematics;
-
-namespace ProjectM.Simulation
-{
- ///
- /// Baked singleton describing the training-dummy field to spawn at world start. Consumed once by
- /// the server-only TrainingDummySpawnSystem, which instantiates dummies from
- /// and then destroys this singleton so the spawn runs exactly once. Not
- /// replicated — dummies are spawned authoritatively on the server and reach clients as ghosts.
- ///
- public struct TrainingDummySpawner : IComponentData
- {
- /// Baked entity prefab to instantiate for each dummy.
- public Entity Prefab;
-
- /// Number of dummies to spawn.
- public int Count;
-
- /// World-unit gap between consecutive dummies along the spawn line (X axis).
- public float Spacing;
-
- /// World-space position of the first dummy; subsequent dummies offset by .
- public float3 Origin;
- }
-}
diff --git a/Assets/_Project/Scripts/Simulation/Combat/TrainingDummySpawner.cs.meta b/Assets/_Project/Scripts/Simulation/Combat/TrainingDummySpawner.cs.meta
deleted file mode 100644
index 5e9c0d120..000000000
--- a/Assets/_Project/Scripts/Simulation/Combat/TrainingDummySpawner.cs.meta
+++ /dev/null
@@ -1,2 +0,0 @@
-fileFormatVersion: 2
-guid: a8f27601fb20640718aaed2c48d1d016
\ No newline at end of file
diff --git a/Assets/_Project/Scripts/Simulation/Combat/TrainingDummyTag.cs b/Assets/_Project/Scripts/Simulation/Combat/TrainingDummyTag.cs
deleted file mode 100644
index 1a54bea75..000000000
--- a/Assets/_Project/Scripts/Simulation/Combat/TrainingDummyTag.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using Unity.Entities;
-
-namespace ProjectM.Simulation
-{
- ///
- /// Zero-size marker identifying a training-dummy enemy. Server auto-target collects
- /// entities as candidates, and the damage/death path destroys
- /// a dummy when its Health.Current reaches zero. Added by TrainingDummyBaker.
- ///
- public struct TrainingDummyTag : IComponentData { }
-}
diff --git a/Assets/_Project/Scripts/Simulation/Combat/TrainingDummyTag.cs.meta b/Assets/_Project/Scripts/Simulation/Combat/TrainingDummyTag.cs.meta
deleted file mode 100644
index af101fb92..000000000
--- a/Assets/_Project/Scripts/Simulation/Combat/TrainingDummyTag.cs.meta
+++ /dev/null
@@ -1,2 +0,0 @@
-fileFormatVersion: 2
-guid: ebe9114e40db748669d89ef861415bac
\ No newline at end of file
diff --git a/Assets/_Project/Scripts/Simulation/Combat/UpgradePickup.cs b/Assets/_Project/Scripts/Simulation/Combat/UpgradePickup.cs
deleted file mode 100644
index 6353f408b..000000000
--- a/Assets/_Project/Scripts/Simulation/Combat/UpgradePickup.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using Unity.Entities;
-
-namespace ProjectM.Simulation
-{
- ///
- /// A world pickup that, on player overlap, grants one StatModifier (server-authoritative) and is then
- /// destroyed. Mirrors a single StatModifier payload (Target/Op as bytes). The pickup is an
- /// interpolated ghost so clients see and despawn it; the grant is applied by UpgradePickupSystem.
- ///
- public struct UpgradePickup : IComponentData
- {
- public byte Target; // StatTarget
- public byte Op; // ModOp
- public float Value;
- public uint SourceId;
- }
-}
diff --git a/Assets/_Project/Scripts/Simulation/Combat/UpgradePickup.cs.meta b/Assets/_Project/Scripts/Simulation/Combat/UpgradePickup.cs.meta
deleted file mode 100644
index eb8500a00..000000000
--- a/Assets/_Project/Scripts/Simulation/Combat/UpgradePickup.cs.meta
+++ /dev/null
@@ -1,2 +0,0 @@
-fileFormatVersion: 2
-guid: a0d34f4d0b12241c7b0f0b1d002142f3
\ No newline at end of file
diff --git a/Assets/_Project/Scripts/Simulation/Combat/UpgradePickupSpawner.cs b/Assets/_Project/Scripts/Simulation/Combat/UpgradePickupSpawner.cs
deleted file mode 100644
index 7c697e1d4..000000000
--- a/Assets/_Project/Scripts/Simulation/Combat/UpgradePickupSpawner.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using Unity.Entities;
-using Unity.Mathematics;
-
-namespace ProjectM.Simulation
-{
- ///
- /// Singleton describing how many upgrade pickups to spawn and where (mirrors TrainingDummySpawner).
- /// Consumed once by the server's UpgradePickupSpawnSystem.
- ///
- public struct UpgradePickupSpawner : IComponentData
- {
- public Entity Prefab;
- public float3 Origin;
- public int Count;
- public float Spacing;
- }
-}
diff --git a/Assets/_Project/Scripts/Simulation/Combat/UpgradePickupSpawner.cs.meta b/Assets/_Project/Scripts/Simulation/Combat/UpgradePickupSpawner.cs.meta
deleted file mode 100644
index da7997914..000000000
--- a/Assets/_Project/Scripts/Simulation/Combat/UpgradePickupSpawner.cs.meta
+++ /dev/null
@@ -1,2 +0,0 @@
-fileFormatVersion: 2
-guid: 059368b62be834614ae3a110a51d42da
\ No newline at end of file
diff --git a/Assets/_Project/Scripts/Simulation/Heartbeat.cs b/Assets/_Project/Scripts/Simulation/Heartbeat.cs
deleted file mode 100644
index 2d4d5f113..000000000
--- a/Assets/_Project/Scripts/Simulation/Heartbeat.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using Unity.Entities;
-
-namespace ProjectM.Simulation
-{
- ///
- /// Trivial unmanaged component used by the setup smoke test to prove the ECS
- /// compile + source-gen + tick path works. Safe to delete once real gameplay exists.
- ///
- public struct Heartbeat : IComponentData
- {
- public int Tick;
- }
-}
diff --git a/Assets/_Project/Scripts/Simulation/Heartbeat.cs.meta b/Assets/_Project/Scripts/Simulation/Heartbeat.cs.meta
deleted file mode 100644
index bf809efa1..000000000
--- a/Assets/_Project/Scripts/Simulation/Heartbeat.cs.meta
+++ /dev/null
@@ -1,2 +0,0 @@
-fileFormatVersion: 2
-guid: a0347bd6d99db438f85ec1985b7f81e1
\ No newline at end of file
diff --git a/Assets/_Project/Scripts/Simulation/HeartbeatSystem.cs b/Assets/_Project/Scripts/Simulation/HeartbeatSystem.cs
deleted file mode 100644
index 11bf4c9c1..000000000
--- a/Assets/_Project/Scripts/Simulation/HeartbeatSystem.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using Unity.Burst;
-using Unity.Entities;
-
-namespace ProjectM.Simulation
-{
- ///
- /// Smoke-test system: increments every once per tick.
- /// Default (no [WorldSystemFilter]) so it runs in the SimulationSystemGroup of
- /// every world. Burst-compiled and unmanaged () per DOTS convention.
- ///
- [BurstCompile]
- public partial struct HeartbeatSystem : ISystem
- {
- [BurstCompile]
- public void OnUpdate(ref SystemState state)
- {
- foreach (var heartbeat in SystemAPI.Query>())
- {
- heartbeat.ValueRW.Tick++;
- }
- }
- }
-}
diff --git a/Assets/_Project/Scripts/Simulation/HeartbeatSystem.cs.meta b/Assets/_Project/Scripts/Simulation/HeartbeatSystem.cs.meta
deleted file mode 100644
index e742fdef4..000000000
--- a/Assets/_Project/Scripts/Simulation/HeartbeatSystem.cs.meta
+++ /dev/null
@@ -1,2 +0,0 @@
-fileFormatVersion: 2
-guid: 78349f49733934f348acb488689fc9ec
\ No newline at end of file
diff --git a/Assets/_Project/Scripts/Simulation/Player/MeleeComboSystem.cs b/Assets/_Project/Scripts/Simulation/Player/MeleeComboSystem.cs
index 9f611448d..3e7219d73 100644
--- a/Assets/_Project/Scripts/Simulation/Player/MeleeComboSystem.cs
+++ b/Assets/_Project/Scripts/Simulation/Player/MeleeComboSystem.cs
@@ -174,7 +174,7 @@ namespace ProjectM.Simulation
var enemyPositions = new NativeList(Allocator.Temp);
foreach (var (xform, health, enemyEntity) in
SystemAPI.Query, RefRO>()
- .WithAny()
+ .WithAll()
.WithEntityAccess())
{
if (health.ValueRO.Current <= 0f)
diff --git a/Assets/_Project/Scripts/Simulation/Tuning.cs b/Assets/_Project/Scripts/Simulation/Tuning.cs
index 629e84764..c72acfb08 100644
--- a/Assets/_Project/Scripts/Simulation/Tuning.cs
+++ b/Assets/_Project/Scripts/Simulation/Tuning.cs
@@ -12,7 +12,6 @@ namespace ProjectM.Simulation
///
/// Values that already live in a clear, public, semantically-named home (NOT duplicated here):
///
- /// - / — cycle phase durations.
/// - — base→expedition world-space offset.
/// - Per-ability/character stats — authored in ScriptableObjects, baked to the AbilityDatabase blob (M3).
///
diff --git a/Assets/_Project/Scripts/Simulation/World/CycleComponents.cs b/Assets/_Project/Scripts/Simulation/World/CycleComponents.cs
index 31e371821..4f5813b7c 100644
--- a/Assets/_Project/Scripts/Simulation/World/CycleComponents.cs
+++ b/Assets/_Project/Scripts/Simulation/World/CycleComponents.cs
@@ -39,22 +39,6 @@ namespace ProjectM.Simulation
/// The base is under assault by a Husk wave (event-triggered; ends when the wave is cleared).
public const byte Siege = 1;
- // ---- Deprecated aliases (kept so HUD/audio/tests keep compiling through the cut-over; cleaned up later). ----
-
- /// DEPRECATED alias of .
- public const byte Expedition = 0;
-
- /// DEPRECATED alias of .
- public const byte Defend = 1;
-
- /// DEPRECATED, unreachable — the timed Build phase is retired.
- public const byte Build = 2;
-
- /// DEPRECATED — the forced Expedition timer is retired (the loop is player-driven). Kept so existing crefs resolve.
- public const uint ExpeditionTicks = 3600;
-
- /// DEPRECATED — the forced Build timer is retired. Kept so existing crefs resolve.
- public const uint BuildTicks = 1200;
}
///
diff --git a/Assets/_Project/Scripts/Simulation/World/RegionTransitRequest.cs b/Assets/_Project/Scripts/Simulation/World/RegionTransitRequest.cs
deleted file mode 100644
index a60848951..000000000
--- a/Assets/_Project/Scripts/Simulation/World/RegionTransitRequest.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using Unity.NetCode;
-
-namespace ProjectM.Simulation
-{
- ///
- /// Client -> server request to move the sender's player between world regions (base <-> expedition).
- /// A one-off action, so an RPC (not a per-tick predicted input), mirroring .
- /// TargetRegion is a byte (see ) to keep the generated serializer trivial. The
- /// server teleports the sender's player to the region origin and flips its , which
- /// re-scopes GhostRelevancy so the client gains the target region's ghosts and drops the old region's.
- ///
- public struct RegionTransitRequest : IRpcCommand
- {
- /// Destination region id (see ).
- public byte TargetRegion;
- }
-}
diff --git a/Assets/_Project/Scripts/Simulation/World/RegionTransitRequest.cs.meta b/Assets/_Project/Scripts/Simulation/World/RegionTransitRequest.cs.meta
deleted file mode 100644
index 7f65c13de..000000000
--- a/Assets/_Project/Scripts/Simulation/World/RegionTransitRequest.cs.meta
+++ /dev/null
@@ -1,2 +0,0 @@
-fileFormatVersion: 2
-guid: 32c76b46284ed1845a412ca030de2499
\ No newline at end of file
diff --git a/Assets/_Project/Tests/EditMode/HealthApplyDamageSystemTests.cs b/Assets/_Project/Tests/EditMode/HealthApplyDamageSystemTests.cs
index 8bf426f5a..0b1399c50 100644
--- a/Assets/_Project/Tests/EditMode/HealthApplyDamageSystemTests.cs
+++ b/Assets/_Project/Tests/EditMode/HealthApplyDamageSystemTests.cs
@@ -14,7 +14,7 @@ namespace ProjectM.Tests
/// filter is ignored, so it still runs in this netcode-free world. The system plays its
/// EntityCommandBuffer back to state.EntityManager immediately (Temp allocator) per the build
/// contract, so no separate ECB system is required for destruction to take effect within a single
- /// group update. Mirrors PlayerMoveSystemTests and HeartbeatSystemTests.
+ /// group update. Uses the plain-Entities world+tick pattern shared across the suite.
///
public class HealthApplyDamageSystemTests
{
@@ -40,9 +40,9 @@ namespace ProjectM.Tests
using (world)
{
var em = world.EntityManager;
- // TrainingDummyTag included so this entity is a valid death candidate too, but with
+ // EnemyTag included so this entity is a valid death candidate too, but with
// 50 HP and 35 total damage it survives, so it must NOT be destroyed here.
- var entity = em.CreateEntity(typeof(Health), typeof(DamageEvent), typeof(TrainingDummyTag));
+ var entity = em.CreateEntity(typeof(Health), typeof(DamageEvent), typeof(EnemyTag));
em.SetComponentData(entity, new Health { Current = 50f, Max = 50f });
var dmg = em.GetBuffer(entity);
@@ -61,13 +61,13 @@ namespace ProjectM.Tests
}
[Test]
- public void Lethal_Damage_Clamps_Health_To_Zero_And_Destroys_TrainingDummy()
+ public void Lethal_Damage_Clamps_Health_To_Zero_And_Destroys_Enemy()
{
- var (world, group) = MakeWorld("HealthApplyDamageLethalDummyWorld");
+ var (world, group) = MakeWorld("HealthApplyDamageLethalEnemyWorld");
using (world)
{
var em = world.EntityManager;
- var entity = em.CreateEntity(typeof(Health), typeof(DamageEvent), typeof(TrainingDummyTag));
+ var entity = em.CreateEntity(typeof(Health), typeof(DamageEvent), typeof(EnemyTag));
em.SetComponentData(entity, new Health { Current = 50f, Max = 50f });
var dmg = em.GetBuffer(entity);
@@ -75,22 +75,22 @@ namespace ProjectM.Tests
group.Update();
- // The system clamps Current to a floor of 0 then destroys the dummy via an
+ // The system clamps Current to a floor of 0 then destroys the enemy via an
// immediately-played ECB, so the entity is gone within this single group update.
Assert.IsFalse(em.Exists(entity),
- "A lethally-hit TrainingDummyTag entity must be destroyed by the system's ECB.");
+ "A lethally-hit EnemyTag entity must be destroyed by the system's ECB.");
- using var remaining = em.CreateEntityQuery(typeof(TrainingDummyTag));
+ using var remaining = em.CreateEntityQuery(typeof(EnemyTag));
Assert.AreEqual(0, remaining.CalculateEntityCount(),
- "No TrainingDummyTag entities should remain after a lethal hit.");
+ "No EnemyTag entities should remain after a lethal hit.");
}
}
[Test]
- public void Lethal_Damage_On_NonDummy_Clamps_To_Zero_Without_Destroying()
+ public void Lethal_Damage_On_Untagged_Entity_Clamps_To_Zero_Without_Destroying()
{
- // Player death is deferred in M2; only TrainingDummyTag entities are destroyed.
- // A non-dummy (no TrainingDummyTag) at zero HP must be clamped to 0 and kept alive.
+ // Only death candidates (EnemyTag / Destructible) are destroyed. An untagged entity
+ // (e.g. a player, whose death is deferred) at zero HP must be clamped to 0 and kept alive.
var (world, group) = MakeWorld("HealthApplyDamageLethalPlayerWorld");
using (world)
{
@@ -104,7 +104,7 @@ namespace ProjectM.Tests
group.Update();
Assert.IsTrue(em.Exists(entity),
- "A non-dummy (player) entity must survive lethal damage in M2; death is deferred.");
+ "An untagged (player) entity must survive lethal damage; death is deferred.");
Assert.AreEqual(0f, em.GetComponentData(entity).Current, 1e-4f,
"Health.Current must be clamped to 0 (never negative).");
Assert.AreEqual(0, em.GetBuffer(entity).Length,
@@ -120,7 +120,7 @@ namespace ProjectM.Tests
using (world)
{
var em = world.EntityManager;
- var entity = em.CreateEntity(typeof(Health), typeof(DamageEvent), typeof(TrainingDummyTag));
+ var entity = em.CreateEntity(typeof(Health), typeof(DamageEvent), typeof(EnemyTag));
em.SetComponentData(entity, new Health { Current = 42f, Max = 60f });
group.Update();
@@ -193,6 +193,5 @@ namespace ProjectM.Tests
Assert.AreEqual(65f, em.GetComponentData(e).Current, 1e-4f, "No stats ceiling -> 100-35 = 65.");
}
}
-
}
}
diff --git a/Assets/_Project/Tests/EditMode/HeartbeatSystemTests.cs b/Assets/_Project/Tests/EditMode/HeartbeatSystemTests.cs
deleted file mode 100644
index e137c6dce..000000000
--- a/Assets/_Project/Tests/EditMode/HeartbeatSystemTests.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-using NUnit.Framework;
-using Unity.Entities;
-using ProjectM.Simulation;
-
-namespace ProjectM.Tests
-{
- ///
- /// Setup smoke test: proves the DOTS toolchain compiles, source-generates, and ticks.
- /// Boots a bare ECS world, registers in the
- /// SimulationSystemGroup, and asserts the component advances once per group update.
- /// (Netcode client/server world boot is covered separately by the §3 Play Mode check.)
- ///
- public class HeartbeatSystemTests
- {
- [Test]
- public void Heartbeat_Advances_Once_Per_SimulationGroup_Tick()
- {
- using var world = new World("HeartbeatTestWorld");
- var simulationGroup = world.GetOrCreateSystemManaged();
- var heartbeatSystem = world.GetOrCreateSystem();
- simulationGroup.AddSystemToUpdateList(heartbeatSystem);
- simulationGroup.SortSystems();
-
- var entityManager = world.EntityManager;
- var entity = entityManager.CreateEntity(typeof(Heartbeat));
-
- Assert.AreEqual(0, entityManager.GetComponentData(entity).Tick,
- "Heartbeat should start at 0.");
-
- const int ticks = 8;
- for (int i = 0; i < ticks; i++)
- {
- simulationGroup.Update();
- }
-
- Assert.AreEqual(ticks, entityManager.GetComponentData(entity).Tick,
- "Heartbeat.Tick should advance exactly once per SimulationSystemGroup update.");
- }
- }
-}
diff --git a/Assets/_Project/Tests/EditMode/HeartbeatSystemTests.cs.meta b/Assets/_Project/Tests/EditMode/HeartbeatSystemTests.cs.meta
deleted file mode 100644
index 65b0e599a..000000000
--- a/Assets/_Project/Tests/EditMode/HeartbeatSystemTests.cs.meta
+++ /dev/null
@@ -1,2 +0,0 @@
-fileFormatVersion: 2
-guid: 74e3326af426947cfaff903aa94ed9f0
\ No newline at end of file
diff --git a/Assets/_Project/Tests/EditMode/InventoryDepositSystemTests.cs b/Assets/_Project/Tests/EditMode/InventoryDepositSystemTests.cs
index 216b9465b..93ac4c15c 100644
--- a/Assets/_Project/Tests/EditMode/InventoryDepositSystemTests.cs
+++ b/Assets/_Project/Tests/EditMode/InventoryDepositSystemTests.cs
@@ -9,7 +9,7 @@ namespace ProjectM.Tests
{
///
/// Plain-Entities EditMode tests for the server-only — the RPC that
- /// moves a player's PERSONAL inventory into the shared ledger. Mirrors RegionTransitSystemTests' seeding:
+ /// moves a player's PERSONAL inventory into the shared ledger. Mirrors the RPC-receive tests' seeding:
/// a ResourceLedger singleton, a mock connection (NetworkId), a player (GhostOwner + InventorySlot +
/// PlayerTag), and an InventoryDepositRequest + ReceiveRpcCommandRequest. Pins: a specific-item deposit
/// moves the clamped amount; ItemId 0 deposits everything and empties the bag; an unresolvable connection
diff --git a/Assets/_Project/Tests/EditMode/RegionTransitSystemTests.cs b/Assets/_Project/Tests/EditMode/RegionTransitSystemTests.cs
deleted file mode 100644
index ba3f83754..000000000
--- a/Assets/_Project/Tests/EditMode/RegionTransitSystemTests.cs
+++ /dev/null
@@ -1,106 +0,0 @@
-using NUnit.Framework;
-using ProjectM.Server;
-using ProjectM.Simulation;
-using Unity.Core;
-using Unity.Entities;
-using Unity.Mathematics;
-using Unity.NetCode;
-using Unity.Transforms;
-
-namespace ProjectM.Tests
-{
- ///
- /// Plain-Entities EditMode tests for the server-only — the RPC region-transit
- /// handler. A bare world is seeded with a BaseAnchor, a mock connection entity (NetworkId), a player
- /// (GhostOwner + RegionTag + LocalTransform + PlayerTag) and a RegionTransitRequest + ReceiveRpcCommandRequest
- /// whose SourceConnection points at the connection. Pins: a request from a resolvable connection flips the
- /// player's region + teleports it to the region origin; an unresolvable connection transits nobody; the request
- /// is consumed either way.
- ///
- public class RegionTransitSystemTests
- {
- static (World world, SimulationSystemGroup group) MakeWorld(string name)
- {
- var world = new World(name);
- var group = world.GetOrCreateSystemManaged();
- group.AddSystemToUpdateList(world.GetOrCreateSystem());
- group.SortSystems();
- world.SetTime(new TimeData(elapsedTime: 0f, deltaTime: 1f / 60f));
- var em = world.EntityManager;
- var anchor = em.CreateEntity(typeof(BaseAnchor));
- em.SetComponentData(anchor, new BaseAnchor
- {
- AnchorPos = new float3(5, 0, 5),
- GridOrigin = new float3(0, 0, 0),
- CellSize = 2f,
- GridDims = new int2(5, 5),
- });
- return (world, group);
- }
-
- static Entity MakeConnection(EntityManager em, int networkId)
- {
- var e = em.CreateEntity();
- em.AddComponentData(e, new NetworkId { Value = networkId });
- return e;
- }
-
- static Entity MakePlayer(EntityManager em, int networkId, byte region, float3 pos)
- {
- var e = em.CreateEntity();
- em.AddComponentData(e, new GhostOwner { NetworkId = networkId });
- em.AddComponentData(e, new RegionTag { Region = region });
- em.AddComponentData(e, LocalTransform.FromPosition(pos));
- em.AddComponent(e);
- return e;
- }
-
- static void MakeTransitRequest(EntityManager em, byte targetRegion, Entity sourceConnection)
- {
- var e = em.CreateEntity();
- em.AddComponentData(e, new RegionTransitRequest { TargetRegion = targetRegion });
- em.AddComponentData(e, new ReceiveRpcCommandRequest { SourceConnection = sourceConnection });
- }
-
- [Test]
- public void Request_From_Known_Connection_Transits_Its_Player()
- {
- var (world, group) = MakeWorld("RegionTransitOk");
- using (world)
- {
- var em = world.EntityManager;
- var conn = MakeConnection(em, networkId: 1);
- var player = MakePlayer(em, networkId: 1, region: RegionId.Base, pos: new float3(5, 1, 5));
- MakeTransitRequest(em, RegionId.Expedition, conn);
-
- group.Update();
-
- Assert.AreEqual(RegionId.Expedition, em.GetComponentData(player).Region,
- "The sender's player flips to the requested region.");
- Assert.AreEqual(1005f, em.GetComponentData(player).Position.x, 1e-2f,
- "The player teleports to the expedition region origin (base center + 1000 on X).");
- using var reqQ = em.CreateEntityQuery(typeof(RegionTransitRequest));
- Assert.AreEqual(0, reqQ.CalculateEntityCount(), "The handled request is destroyed.");
- }
- }
-
- [Test]
- public void Request_From_Unresolvable_Connection_Transits_Nobody()
- {
- var (world, group) = MakeWorld("RegionTransitUnknown");
- using (world)
- {
- var em = world.EntityManager;
- var player = MakePlayer(em, networkId: 1, region: RegionId.Base, pos: new float3(5, 1, 5));
- MakeTransitRequest(em, RegionId.Expedition, Entity.Null); // no NetworkId on Entity.Null
-
- group.Update();
-
- Assert.AreEqual(RegionId.Base, em.GetComponentData(player).Region,
- "A request whose connection can't be resolved transits nobody.");
- using var reqQ = em.CreateEntityQuery(typeof(RegionTransitRequest));
- Assert.AreEqual(0, reqQ.CalculateEntityCount(), "The request is still consumed.");
- }
- }
- }
-}
diff --git a/Assets/_Project/Tests/EditMode/RegionTransitSystemTests.cs.meta b/Assets/_Project/Tests/EditMode/RegionTransitSystemTests.cs.meta
deleted file mode 100644
index 8294f1ad9..000000000
--- a/Assets/_Project/Tests/EditMode/RegionTransitSystemTests.cs.meta
+++ /dev/null
@@ -1,2 +0,0 @@
-fileFormatVersion: 2
-guid: 727cdc6da6f5b8842ba5b311702e5224
\ No newline at end of file
diff --git a/Assets/_Project/Tests/EditMode/UpgradePickupSystemTests.cs b/Assets/_Project/Tests/EditMode/UpgradePickupSystemTests.cs
deleted file mode 100644
index 47300a002..000000000
--- a/Assets/_Project/Tests/EditMode/UpgradePickupSystemTests.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-using NUnit.Framework;
-using ProjectM.Server;
-using ProjectM.Simulation;
-using Unity.Entities;
-using Unity.Mathematics;
-using Unity.Transforms;
-
-namespace ProjectM.Tests
-{
- ///
- /// Plain-Entities test for (server grant). A player overlapping a
- /// pickup gets the pickup's modifier appended to its StatModifier buffer and the pickup is destroyed;
- /// a player out of range leaves the buffer empty and the pickup alive. The system's ECB plays back
- /// immediately (server pattern), so no separate ECB system is needed.
- ///
- public class UpgradePickupSystemTests
- {
- static (World world, Entity player, Entity pickup) MakeWorld(float3 playerPos, float3 pickupPos, float radius)
- {
- var world = new World("UpgradePickupTestWorld");
- var group = world.GetOrCreateSystemManaged();
- group.AddSystemToUpdateList(world.GetOrCreateSystem());
- group.SortSystems();
-
- var em = world.EntityManager;
-
- var player = em.CreateEntity(typeof(PlayerTag), typeof(StatModifier), typeof(LocalTransform));
- em.SetComponentData(player, LocalTransform.FromPosition(playerPos));
-
- var pickup = em.CreateEntity(typeof(UpgradePickup), typeof(HitRadius), typeof(LocalTransform));
- em.SetComponentData(pickup, LocalTransform.FromPosition(pickupPos));
- em.SetComponentData(pickup, new HitRadius { Value = radius });
- em.SetComponentData(pickup, new UpgradePickup
- {
- Target = (byte)StatTarget.Damage, Op = (byte)ModOp.Flat, Value = 25f, SourceId = 7u
- });
-
- return (world, player, pickup);
- }
-
- [Test]
- public void Overlap_Grants_Modifier_And_Destroys_Pickup()
- {
- var (world, player, pickup) = MakeWorld(float3.zero, new float3(0.5f, 0f, 0f), 1f);
- try
- {
- world.GetExistingSystemManaged().Update();
- var buf = world.EntityManager.GetBuffer(player);
- Assert.AreEqual(1, buf.Length);
- Assert.AreEqual((byte)StatTarget.Damage, buf[0].Target);
- Assert.AreEqual((byte)ModOp.Flat, buf[0].Op);
- Assert.AreEqual(25f, buf[0].Value, 1e-4f);
- Assert.AreEqual(7u, buf[0].SourceId);
- Assert.IsFalse(world.EntityManager.Exists(pickup), "Pickup should be destroyed after grant.");
- }
- finally { world.Dispose(); }
- }
-
- [Test]
- public void Out_Of_Range_Leaves_Buffer_Empty_And_Pickup_Alive()
- {
- var (world, player, pickup) = MakeWorld(float3.zero, new float3(10f, 0f, 0f), 1f);
- try
- {
- world.GetExistingSystemManaged().Update();
- var buf = world.EntityManager.GetBuffer(player);
- Assert.AreEqual(0, buf.Length);
- Assert.IsTrue(world.EntityManager.Exists(pickup), "Out-of-range pickup should remain.");
- }
- finally { world.Dispose(); }
- }
- }
-}
diff --git a/Assets/_Project/Tests/EditMode/UpgradePickupSystemTests.cs.meta b/Assets/_Project/Tests/EditMode/UpgradePickupSystemTests.cs.meta
deleted file mode 100644
index 454ea9509..000000000
--- a/Assets/_Project/Tests/EditMode/UpgradePickupSystemTests.cs.meta
+++ /dev/null
@@ -1,2 +0,0 @@
-fileFormatVersion: 2
-guid: 34f9fd7580c614586b6a5c68a0e6393c
\ No newline at end of file
diff --git a/Assets/_Project/Tests/EditMode/WaveSystemTests.cs b/Assets/_Project/Tests/EditMode/WaveSystemTests.cs
index fde396581..53575ab2c 100644
--- a/Assets/_Project/Tests/EditMode/WaveSystemTests.cs
+++ b/Assets/_Project/Tests/EditMode/WaveSystemTests.cs
@@ -68,7 +68,7 @@ namespace ProjectM.Tests
[Test]
public void Due_Lull_Starts_Wave_With_Escalating_Count()
{
- var (world, group) = MakeWorld("WaveLullStart", serverTick: 100, cyclePhase: CyclePhase.Defend);
+ var (world, group) = MakeWorld("WaveLullStart", serverTick: 100, cyclePhase: CyclePhase.Siege);
using (world)
{
var em = world.EntityManager;
@@ -88,7 +88,7 @@ namespace ProjectM.Tests
[Test]
public void Spawning_Emits_One_Husk_And_Decrements_Remaining()
{
- var (world, group) = MakeWorld("WaveSpawnOne", serverTick: 100, cyclePhase: CyclePhase.Defend);
+ var (world, group) = MakeWorld("WaveSpawnOne", serverTick: 100, cyclePhase: CyclePhase.Siege);
using (world)
{
var em = world.EntityManager;
@@ -107,7 +107,7 @@ namespace ProjectM.Tests
[Test]
public void Director_Is_Gated_Off_Outside_Defend()
{
- var (world, group) = MakeWorld("WaveGated", serverTick: 100, cyclePhase: CyclePhase.Expedition);
+ var (world, group) = MakeWorld("WaveGated", serverTick: 100, cyclePhase: CyclePhase.Calm);
using (world)
{
var em = world.EntityManager;
@@ -125,7 +125,7 @@ namespace ProjectM.Tests
[Test]
public void Fully_Spawned_Cleared_Wave_Returns_To_Lull()
{
- var (world, group) = MakeWorld("WaveCleared", serverTick: 100, cyclePhase: CyclePhase.Defend);
+ var (world, group) = MakeWorld("WaveCleared", serverTick: 100, cyclePhase: CyclePhase.Siege);
using (world)
{
var em = world.EntityManager;