| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- namespace MazeGen
- {
- /// <summary>
- /// Handles arrival at a room where a fight is already forming.
- /// Agent can join (raising odds) or try to sneak past, with failed sneak forcing entry.
- /// </summary>
- public class HandleExistingFightDecision : AgentDecision
- {
- private CombatDirector _director;
- private float _retreatThreshold;
- public override string DecisionName => "Handle Existing Fight";
- public HandleExistingFightDecision(CombatDirector director, float retreatThreshold)
- {
- _director = director;
- _retreatThreshold = retreatThreshold;
- }
- public override bool CanExecute(MazeAgent agent)
- {
- if (agent == null || _director == null) return false;
- if (agent.IsEngaged) return false; // Already committed
- Room room = agent.CurrentRoom;
- if (room == null) return false;
- // Is there a fight already mustering here that we're not in?
- PendingFight mustering = _director.FindMusteringFight(room);
- return mustering != null && !mustering.Contains(agent);
- }
- public override bool Execute(MazeAgent agent)
- {
- Room room = agent.CurrentRoom;
- PendingFight fight = _director.FindMusteringFight(room);
- if (fight == null) return false;
- float threat = fight.Encounter.GetPerceivedChallengeRating(agent.CharacterSheet);
- float effectiveThreshold = GetEffectiveReteatThreshold(agent);
- float sharedThreat = threat / (fight.Agents.Count + 1);
- bool wantsToSneak = sharedThreat > effectiveThreshold || agent.HasFledFrom(fight.Room.Id);
- if (!wantsToSneak)
- {
- // Join the fight
- var result = _director.ResolveArrival(agent, false);
- return result == CombatDirector.ArrivalDecision.Joined;
- }
- else
- {
- // Try to sneak, which might fail and force a join
- var result = _director.ResolveArrival(agent, true);
- return result == CombatDirector.ArrivalDecision.Joined ||
- result == CombatDirector.ArrivalDecision.SneakFailedAndJoined;
- }
- }
- public override void Think(MazeAgent agent)
- {
- Room room = agent.CurrentRoom;
- PendingFight fight = _director.FindMusteringFight(room);
- if (fight == null) return;
- float threat = fight.Encounter.GetPerceivedChallengeRating(agent.CharacterSheet);
- float effectiveThreshold = GetEffectiveReteatThreshold(agent);
- float sharedThreat = threat / (fight.Agents.Count + 1);
- bool wantsToSneak = sharedThreat > effectiveThreshold || agent.HasFledFrom(fight.Room.Id);
- if (!wantsToSneak)
- agent.Thoughts.Add(ThoughtKind.Fight,
- $"Walked into fight #{fight.Id} - {fight.Agents.Count} ally(s) already in, shared threat {sharedThreat:0.00}. Joining.");
- else
- agent.Thoughts.Add(ThoughtKind.Sneak,
- $"Walked into fight #{fight.Id} - shared threat {sharedThreat:0.00} still over my limit. Trying to sneak past it.");
- }
- private float GetEffectiveReteatThreshold(MazeAgent agent)
- {
- CharacterSheet sheet = agent.CharacterSheet;
- float maxHealth = sheet.Stats.MaxHealth;
- if (maxHealth <= 0) return _retreatThreshold;
- float healthPercent = sheet.Stats.CurrentHealth / maxHealth;
- if (healthPercent < 0.3f)
- return _retreatThreshold * 0.5f;
- else if (healthPercent < 0.5f)
- {
- float t = (healthPercent - 0.3f) / 0.2f;
- return UnityEngine.Mathf.Lerp(_retreatThreshold * 0.5f, _retreatThreshold, t);
- }
- return _retreatThreshold;
- }
- }
- }
|