using System; using Cysharp.Threading.Tasks; using Unity.Mathematics; using UnityEngine.Pool; using Random = UnityEngine.Random; namespace DanieleMarotta.RiversongCodeShowcase { public class WanderingExecutionLogic : IntentExecutionLogic { private ITileSpace _tileSpace; private World _world; public override UniTask InitializeAsync(IServiceLocator serviceLocator) { _tileSpace = serviceLocator.GetService(); _world = serviceLocator.GetService(); return UniTask.CompletedTask; } public override IntentExecutionResult Execute(Agent agent, in AgentIntent intent) { switch (intent.Type) { case AgentIntentType.Wander: return Wander(agent); case AgentIntentType.LoopWandering: LoopWandering(agent); return IntentExecutionResult.Success; } throw new InvalidOperationException(); } private IntentExecutionResult Wander(Agent agent) { using var candidatesScope = ListPool.Get(out var candidates); var tile = _tileSpace.WorldToTile(agent.Position); for (var i = 0; i < 8; i++) { var candidate = ((Directions)i).ToVector(); if (!_world.BlockMap.IsBlocked(tile + candidate, BlockReason.BlocksAgents)) candidates.Add(candidate); } if (candidates.Count <= 0) return IntentExecutionResult.Failure; var direction = candidates[Random.Range(0, candidates.Count)]; if (agent.Definition.WanderingRadius > 0) { var distance = TileMath.StepCount(agent.WanderingCenter, tile + direction); if (distance > agent.Definition.WanderingRadius) direction = math.sign(agent.WanderingCenter - tile); } ref var path = ref agent.GetPathRW(); path.Steps.Clear(); path.Steps.Add(tile); path.Steps.Add(tile + direction); return IntentExecutionResult.Success; } private void LoopWandering(Agent agent) { var idleTimeRange = agent.Definition.WanderingIdleTime; var idleTime = Random.Range(idleTimeRange.x, idleTimeRange.y); IntentQueue.LoopWandering(ref agent.GetIntentQueueRW(), idleTime); } } }