using System.Collections.Generic;
using UnityEngine;
namespace MazeGen
{
///
/// Skeleton for resolving combat between an agent and monsters in a room.
/// This is NOT a full implementation - you'll need to expand this with:
/// - Turn order calculation
/// - Action resolution (attack, defend, ability)
/// - Damage calculation
/// - Status effects
/// - Ability cooldowns
///
/// This provides just the structure and basic helper functions.
///
public class CombatResolver
{
public enum CombatOutcome
{
AgentVictory,
AgentDefeated,
Fleeing // Agent escaped before resolution
}
///
/// Simulate combat between an agent and the monsters in this room.
/// Returns the outcome. You'll need to expand this significantly for a real system.
///
public static CombatOutcome ResolveCombat(MazeAgent agent, MonsterEncounter encounter)
{
if (encounter == null || !encounter.HasLivingMonsters)
return CombatOutcome.AgentVictory; // No fight needed
// TODO: Implement full combat loop
// 1. Build turn order from Speed stats
var turnOrder = BuildTurnOrder(agent, encounter);
// 2. Simulate turns until victory/defeat
int maxRounds = 100; // Prevent infinite loops during development
int round = 0;
while (round < maxRounds && agent.CharacterSheet.Stats.IsAlive && encounter.HasLivingMonsters)
{
round++;
// Execute each turn in order
foreach (var turn in turnOrder)
{
if (turn.IsAgent)
{
ExecuteAgentTurn(agent, encounter);
}
else
{
ExecuteMonsterTurn(turn.MonsterIndex, agent, encounter);
}
// Check win conditions each turn
if (!agent.CharacterSheet.Stats.IsAlive)
return CombatOutcome.AgentDefeated;
if (!encounter.HasLivingMonsters)
return CombatOutcome.AgentVictory;
}
}
if (agent.CharacterSheet.Stats.IsAlive && !encounter.HasLivingMonsters)
return CombatOutcome.AgentVictory;
return CombatOutcome.AgentDefeated;
}
///
/// Determine turn order based on Speed stats.
/// Higher speed = earlier in turn order.
///
private static List<(bool IsAgent, int MonsterIndex)> BuildTurnOrder(MazeAgent agent, MonsterEncounter encounter)
{
var order = new List<(bool, int)>();
// Agent's speed
float agentInitiative = agent.CharacterSheet.GetEffectiveSpeed();
order.Add((true, -1)); // IsAgent=true, MonsterIndex unused
// Each monster's speed
for (int i = 0; i < encounter.Monsters.Count; i++)
{
if (!encounter.Monsters[i].IsDefeated)
{
float monsterInitiative = encounter.Monsters[i].CharacterSheet.GetEffectiveSpeed();
order.Add((false, i));
}
}
// Sort by initiative (higher = first)
// TODO: Implement proper sorting by speed
// order.Sort((a, b) => ...)
return order;
}
///
/// Execute the agent's turn. Pick a target and attack.
/// This is a stub - implement your action selection here.
///
private static void ExecuteAgentTurn(MazeAgent agent, MonsterEncounter encounter)
{
// TODO: Implement agent decision (which monster to target, what ability to use)
// For now, just attack the first alive monster
for (int i = 0; i < encounter.Monsters.Count; i++)
{
if (!encounter.Monsters[i].IsDefeated)
{
AttackMonster(agent, encounter, i);
break;
}
}
}
///
/// Execute one monster's turn. They attack the agent.
/// This is a stub - add AI/decision logic here.
///
private static void ExecuteMonsterTurn(int monsterIndex, MazeAgent agent, MonsterEncounter encounter)
{
if (monsterIndex < 0 || monsterIndex >= encounter.Monsters.Count)
return;
var monster = encounter.Monsters[monsterIndex];
if (monster.IsDefeated)
return;
// TODO: Implement monster AI (target selection, ability choice, etc.)
// For now, just attack the agent
AttackAgent(monster, agent);
}
///
/// Calculate and apply damage when agent attacks a monster.
/// Stub - expand with damage types, abilities, modifiers, etc.
///
private static void AttackMonster(MazeAgent agent, MonsterEncounter encounter, int targetIndex)
{
var target = encounter.Monsters[targetIndex];
// Simple attack: agent's attack vs target's defense
float baseDamage = agent.CharacterSheet.GetEffectiveAttack();
float damage = target.CharacterSheet.Stats.CalculateDamageReduction(baseDamage);
Debug.Log($"{agent.Name} attacks {target.Template.MonsterName} for {damage} damage");
target.CharacterSheet.Stats.TakeDamage(damage);
if (target.IsDefeated)
{
Debug.Log($"{target.Template.MonsterName} defeated!");
// TODO: Award loot to agent
}
}
///
/// Calculate and apply damage when monster attacks agent.
/// Stub - expand similarly to AttackMonster.
///
private static void AttackAgent(MonsterEncounter.MonsterInstance attacker, MazeAgent target)
{
float baseDamage = attacker.CharacterSheet.GetEffectiveAttack();
float damage = target.CharacterSheet.Stats.CalculateDamageReduction(baseDamage);
Debug.Log($"{attacker.Template.MonsterName} attacks {target.Name} for {damage} damage");
target.CharacterSheet.Stats.TakeDamage(damage);
if (!target.CharacterSheet.Stats.IsAlive)
{
Debug.Log($"{target.Name} defeated!");
target.Die();
}
}
///
/// Award loot from a defeated monster to the agent.
/// Stub - implement inventory/pickup logic.
///
private static void AwardLoot(MonsterEncounter.MonsterInstance monster, MazeAgent agent)
{
// TODO: Implement loot pickup
// var loot = monster.Template.GetRandomLoot();
// if (loot != null)
// agent.CharacterSheet.AddToInventory(loot);
}
}
}