| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 |
- namespace MazeGen
- {
- /// <summary>
- /// Declares a fight with monsters in the current room if the threat level is acceptable.
- /// Uses a health-aware retreat threshold: lower health = more defensive.
- /// </summary>
- public class DeclareFightDecision : AgentDecision
- {
- private CombatDirector _director;
- private float _retreatThreshold;
- public override string DecisionName => "Declare Fight";
- public DeclareFightDecision(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;
- Room room = agent.CurrentRoom;
- if (room == null || room.Encounter == null || !room.Encounter.HasLivingMonsters)
- return false;
- // Already failed here before
- if (agent.HasFledFrom(room.Id))
- return false;
- // Would we accept this threat level?
- float threat = room.Encounter.GetPerceivedChallengeRating(agent.CharacterSheet);
- float effectiveThreshold = GetEffectiveReteatThreshold(agent);
- return threat <= effectiveThreshold;
- }
- public override bool Execute(MazeAgent agent)
- {
- Room room = agent.CurrentRoom;
- float threat = room.Encounter.GetPerceivedChallengeRating(agent.CharacterSheet);
- int hostiles = room.Encounter.AliveMonsterCount;
- _director.DeclareFight(room, agent, $"sized up {hostiles} hostile(s) at threat {threat:0.00} and attacked");
- return true;
- }
- public override void Think(MazeAgent agent)
- {
- Room room = agent.CurrentRoom;
- float threat = room.Encounter.GetPerceivedChallengeRating(agent.CharacterSheet);
- float effectiveThreshold = GetEffectiveReteatThreshold(agent);
- int hostiles = room.Encounter.AliveMonsterCount;
- agent.Thoughts.Add(ThoughtKind.Fight,
- $"Peeked: {hostiles} hostile(s), threat {threat:0.00} vs my limit {effectiveThreshold:0.00} - engaging. Fight starts in {_director.JoinWindowSeconds:0.0}s, hopefully someone joins.");
- }
- 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;
- }
- }
- }
|