diff --git a/Assets/GameMain/Scripts/Simulation/SimulationWorld.EnemyJobs.cs b/Assets/GameMain/Scripts/Simulation/SimulationWorld.EnemyJobs.cs index 3711363..8fbfee7 100644 --- a/Assets/GameMain/Scripts/Simulation/SimulationWorld.EnemyJobs.cs +++ b/Assets/GameMain/Scripts/Simulation/SimulationWorld.EnemyJobs.cs @@ -226,9 +226,6 @@ namespace Simulation RecycleInactiveProjectiles(); } } - - MarkEnemyTargetSpatialIndexDirty(); - BuildEnemyTargetSpatialIndexIfNeeded(); } private JobHandle ExecuteEnemyMovementJob(in SimulationTickContext context) diff --git a/Assets/GameMain/Scripts/Simulation/SimulationWorld.JobDataChannel.cs b/Assets/GameMain/Scripts/Simulation/SimulationWorld.JobDataChannel.cs index a4b9d32..53f2207 100644 --- a/Assets/GameMain/Scripts/Simulation/SimulationWorld.JobDataChannel.cs +++ b/Assets/GameMain/Scripts/Simulation/SimulationWorld.JobDataChannel.cs @@ -619,9 +619,23 @@ namespace Simulation private void ApplyJobOutputToSimulation() { int enemyCount = Mathf.Min(_enemies.Count, _enemyJobOutputs.Length); + bool hasEnemyPositionChanged = false; for (int i = 0; i < enemyCount; i++) { - _enemies[i] = ConvertToEnemySimData(_enemyJobOutputs[i]); + EnemyJobOutputData output = _enemyJobOutputs[i]; + if (!hasEnemyPositionChanged) + { + Vector3 currentPosition = _enemies[i].Position; + hasEnemyPositionChanged = currentPosition.x != output.Position.x || + currentPosition.z != output.Position.z; + } + + _enemies[i] = ConvertToEnemySimData(output); + } + + if (hasEnemyPositionChanged) + { + MarkEnemyTargetSpatialIndexDirty(); } int projectileCount = Mathf.Min(_projectiles.Count, _projectileJobOutputs.Length); diff --git a/Assets/GameMain/Scripts/Simulation/SimulationWorld.ProjectileJobs.cs b/Assets/GameMain/Scripts/Simulation/SimulationWorld.ProjectileJobs.cs index 8ec1748..d70d85b 100644 --- a/Assets/GameMain/Scripts/Simulation/SimulationWorld.ProjectileJobs.cs +++ b/Assets/GameMain/Scripts/Simulation/SimulationWorld.ProjectileJobs.cs @@ -453,7 +453,7 @@ namespace Simulation return false; } - damage = CalculateProjectileDamage(sourceImpact.AttackBase, sourceImpact.AttackStat, + damage = AIUtility.CalcDamageHP(sourceImpact.AttackBase, sourceImpact.AttackStat, targetImpact.DefenseStat, targetImpact.DodgeStat); shouldDispatchPresentation = true; @@ -537,36 +537,6 @@ namespace Simulation return false; } - private static int CalculateProjectileDamage(int attack, StatProperty attackStat, StatProperty defenseStat, - StatProperty dodgeStat) - { - if (dodgeStat != null) - { - if (UnityEngine.Random.value < Mathf.Clamp(dodgeStat.Percent, 0f, 0.9f)) - { - return 0; - } - } - - float damage = attack; - if (attackStat != null) - { - damage = (attack + attackStat.Value) * attackStat.Percent; - } - - if (defenseStat != null) - { - damage = (damage - defenseStat.Value) / defenseStat.Percent; - } - - if (damage < 1f) - { - return 1; - } - - return Mathf.CeilToInt(damage); - } - private static bool TryGetTargetableEntity(int entityId, out TargetableObject target) { target = null; diff --git a/Assets/GameMain/Scripts/Simulation/SimulationWorld.TargetSelectionSpatialIndex.cs b/Assets/GameMain/Scripts/Simulation/SimulationWorld.TargetSelectionSpatialIndex.cs index 23c39dd..37bf518 100644 --- a/Assets/GameMain/Scripts/Simulation/SimulationWorld.TargetSelectionSpatialIndex.cs +++ b/Assets/GameMain/Scripts/Simulation/SimulationWorld.TargetSelectionSpatialIndex.cs @@ -8,7 +8,6 @@ namespace Simulation { private NativeParallelMultiHashMap _enemyTargetBuckets; private bool _enemyTargetBucketsDirty = true; - private int _enemyTargetBucketsFrame = -1; [SerializeField] private float _targetSelectionCellSize = 2f; @@ -85,7 +84,6 @@ namespace Simulation _enemyTargetBuckets = new NativeParallelMultiHashMap(256, Allocator.Persistent); _enemyTargetBucketsDirty = true; - _enemyTargetBucketsFrame = -1; } private void DisposeEnemyTargetSpatialIndex() @@ -97,7 +95,6 @@ namespace Simulation _enemyTargetBuckets = default; _enemyTargetBucketsDirty = true; - _enemyTargetBucketsFrame = -1; } private void ClearEnemyTargetSpatialIndex() @@ -108,20 +105,18 @@ namespace Simulation } _enemyTargetBucketsDirty = true; - _enemyTargetBucketsFrame = -1; } private void MarkEnemyTargetSpatialIndexDirty() { _enemyTargetBucketsDirty = true; - _enemyTargetBucketsFrame = -1; } private void BuildEnemyTargetSpatialIndexIfNeeded() { InitializeEnemyTargetSpatialIndex(); - if (!_enemyTargetBucketsDirty && _enemyTargetBucketsFrame == Time.frameCount) + if (!_enemyTargetBucketsDirty) { return; } @@ -148,7 +143,6 @@ namespace Simulation } _enemyTargetBucketsDirty = false; - _enemyTargetBucketsFrame = Time.frameCount; } private float GetTargetSelectionCellSize() diff --git a/openspec/config.yaml b/openspec/config.yaml deleted file mode 100644 index 392946c..0000000 --- a/openspec/config.yaml +++ /dev/null @@ -1,20 +0,0 @@ -schema: spec-driven - -# Project context (optional) -# This is shown to AI when creating artifacts. -# Add your tech stack, conventions, style guides, domain knowledge, etc. -# Example: -# context: | -# Tech stack: TypeScript, React, Node.js -# We use conventional commits -# Domain: e-commerce platform - -# Per-artifact rules (optional) -# Add custom rules for specific artifacts. -# Example: -# rules: -# proposal: -# - Keep proposals under 500 words -# - Always include a "Non-goals" section -# tasks: -# - Break tasks into chunks of max 2 hours