using UnityEngine;
///
/// Combat encounter events - ambushes, bandits, wild animals, etc.
/// More likely in forests and mountains, less likely on roads
///
[CreateAssetMenu(fileName = "New Combat Event", menuName = "RPG/Travel Events/Combat Event")]
public class CombatTravelEvent : TravelEvent
{
[Header("Combat Event Settings")]
public int minEnemies = 1;
public int maxEnemies = 3;
[Tooltip("Drag EnemyCharacterData assets here")]
public EnemyCharacterData[] possibleEnemies = new EnemyCharacterData[0];
[Header("Escape Configuration")]
public bool allowRunningAway = true;
[Range(0f, 1f)]
public float runAwaySuccessChance = 0.75f;
public int runAwayHealthPenalty = 5;
[Header("Run Away Messages")]
[TextArea(2, 4)]
public string[] successfulRunAwayMessages = {
"Your party successfully escapes from the enemies!",
"Quick thinking allows your party to avoid the confrontation!",
"Your party slips away unnoticed by the enemies."
};
[TextArea(2, 4)]
public string[] failedRunAwayMessages = {
"The enemies catch up to your party! You take {damage} damage while trying to escape.",
"Your escape attempt fails! The enemies pursue and wound your party for {damage} damage.",
"The enemies block your escape route! Your party suffers {damage} damage in the failed attempt."
};
[Header("Combat Event Descriptions")]
[TextArea(2, 4)]
public string[] encounterDescriptions = {
"Your party is ambushed by {enemyType}s!",
"A group of {enemyType}s blocks your path!",
"You stumble upon a {enemyType} camp!"
};
public override EventResult ExecuteEvent(TravelEventContext context)
{
int enemyCount = Random.Range(minEnemies, maxEnemies + 1);
// Ensure we have valid enemies configured
if (possibleEnemies == null || possibleEnemies.Length == 0)
{
Debug.LogError($"No enemies configured for combat event: {eventName}");
return EventResult.NoEvent();
}
// Filter out null entries
var validEnemies = System.Array.FindAll(possibleEnemies, e => e != null);
if (validEnemies.Length == 0)
{
Debug.LogError($"All enemy references are null for combat event: {eventName}");
return EventResult.NoEvent();
}
// Select random enemy
EnemyCharacterData selectedEnemy = validEnemies[Random.Range(0, validEnemies.Length)];
string enemyType = selectedEnemy.enemyName;
// Generate description
string description = encounterDescriptions[Random.Range(0, encounterDescriptions.Length)];
description = description.Replace("{enemyType}", enemyType);
// First try to find it by component type
var integrationComponents = FindObjectsByType(FindObjectsSortMode.None);
var combatIntegration = System.Array.Find(integrationComponents,
comp => comp.GetType().Name == "CombatEventIntegration");
if (combatIntegration == null)
{
// Try the reflection approach as fallback
var type = System.Type.GetType("CombatEventIntegration");
if (type != null)
{
combatIntegration = FindFirstObjectByType(type) as MonoBehaviour;
}
}
if (combatIntegration != null)
{
// Create battle data for the popup
var battleData = new BattleEventData
{
enemyCount = enemyCount,
enemyType = enemyType,
enemyCharacterData = selectedEnemy
};
// Use reflection to call ShowCombatChoicePopup with the new signature
var method = combatIntegration.GetType().GetMethod("ShowCombatChoicePopup");
if (method != null)
{
method.Invoke(combatIntegration, new object[] { battleData, context, description, this });
// Return a special result that indicates popup is handling the choice
return new EventResult("Combat encounter detected...")
{
shouldStopTravel = true, // Stop travel while popup is showing
startBattle = false, // Don't start battle yet - popup will handle it
suppressMessage = true, // Don't show default message - popup handles display
eventOccurred = true
};
}
else
{
Debug.LogError("❌ ShowCombatChoicePopup method not found on CombatEventIntegration");
}
}
else
{
Debug.LogWarning("⚠️ No CombatEventIntegration component found in scene");
}
// Fallback to immediate battle if no integration found
Debug.LogWarning("⚠️ No CombatEventIntegration found, proceeding with immediate battle");
var result = EventResult.SimpleBattle(description, enemyCount, enemyType);
result.battleData.enemyCharacterData = selectedEnemy;
return result;
}
///
/// Handle escape attempt for this specific combat event
///
public EventResult HandleEscapeAttempt(TravelEventContext context)
{
if (!allowRunningAway)
{
Debug.LogWarning($"🚫 Running away is not allowed for this combat event: {eventName}");
return null; // Force battle
}
// Roll for escape success
bool escapeSuccessful = Random.value <= runAwaySuccessChance;
if (escapeSuccessful)
{
return CreateSuccessfulEscapeResult();
}
else
{
return CreateFailedEscapeResult(context);
}
}
///
/// Create result for successful escape
///
private EventResult CreateSuccessfulEscapeResult()
{
string message = successfulRunAwayMessages[Random.Range(0, successfulRunAwayMessages.Length)];
return new EventResult(message)
{
shouldStopTravel = false, // Don't stop travel for successful escape
startBattle = false,
eventOccurred = true
};
}
///
/// Create result for failed escape
///
private EventResult CreateFailedEscapeResult(TravelEventContext context)
{
string message = failedRunAwayMessages[Random.Range(0, failedRunAwayMessages.Length)];
message = message.Replace("{damage}", runAwayHealthPenalty.ToString());
var result = new EventResult(message)
{
shouldStopTravel = true, // Stop travel for failed escape
startBattle = false, // Don't start battle, just apply penalty
eventOccurred = true,
healthChange = -runAwayHealthPenalty // Apply health penalty through EventResult system
};
return result;
}
void OnEnable()
{
// Set default values for combat events
eventType = EventType.Combat;
rarity = EventRarity.Common;
// Combat events are more likely in dangerous terrain
forestChance = 0.8f;
mountainChance = 0.9f;
plainsChance = 0.4f;
roadChance = 0.2f; // Much less likely on roads
townChance = 0.1f; // Very unlikely in towns
villageChance = 0.3f;
}
}