using Unity.Mathematics; namespace DanieleMarotta.RiversongCodeShowcase { [GameSystemGroup(typeof(EarlyAgentsSystemGroup))] [UpdateAfter(typeof(AgentSpawnSystemsGroup))] public class HunterBehaviorSystem : GameSystem, IUpdatable { private const int HunterFireRange = 8; [InjectService] private IEntityCollection _entityCollection; [InjectService] private IEntityCache _entityCache; [InjectService] private ITileSpace _tileSpace; [InjectService] private IIntentLogicExecutor _intentLogicExecutor; [InjectService] private IProjectileManager _projectileManager; public HunterBehaviorSystem(IServiceLocator serviceLocator) : base(serviceLocator) { } public void Update() { foreach (var hunter in _entityCache.GetHunterAgents()) { if (hunter.LifecycleState != AgentLifecycleState.Live) continue; ref var jobState = ref hunter.GetJobStateRW(); if (jobState.StateMachineStep != AgentStateMachineStep.Hunter_SeekingPrey) continue; if (UpdateSeekingPrey(hunter)) jobState.StateMachineStep = AgentStateMachineStep.ReturningHome; } } private bool UpdateSeekingPrey(Agent hunter) { const float hunterRangeSq = HunterFireRange * HunterFireRange; if (!_entityCollection.TryGet(hunter.HomeId, out var hunterBuilding)) return false; var hunterTile = _tileSpace.WorldToTile(hunter.Position); var critterDefinitionId = hunterBuilding.Definition.TargetCritter.RuntimeId; foreach (var critter in _entityCache.GetCritterAgents()) { ref var critterState = ref critter.GetCritterStateRW(); if (critterState.CritterDefinitionId != critterDefinitionId || critter.LifecycleState != AgentLifecycleState.Live || critterState.LockId != Entity.InvalidId) continue; var critterTile = _tileSpace.WorldToTile(critter.Position); if (math.distancesq(hunterTile, critterTile) > hunterRangeSq) continue; critterState.LockId = hunter.Id; ref var hunterIntentQueue = ref _intentLogicExecutor.CancelRemainingIntents(hunter); var projectileTravelTime = _projectileManager.ComputeProjectileTravelTime(hunter, critter); IntentQueue.FireAtPreyAndReturnHome(ref hunterIntentQueue, hunterBuilding.Rect, hunterBuilding.Id, critterTile, critter.Id, projectileTravelTime); ref var critterIntentQueue = ref _intentLogicExecutor.CancelRemainingIntents(critter); critterIntentQueue.EnqueueIntent(AgentIntent.WaitForever()); return true; } return false; } } }