| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411 |
- using UnityEngine;
- /// <summary>
- /// Combat encounter events - ambushes, bandits, wild animals, etc.
- /// More likely in forests and mountains, less likely on roads
- /// </summary>
- [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);
- // Try to use combat event integration for popup choice
- Debug.Log("🔍 Looking for CombatEventIntegration component...");
- // First try to find it by component type
- var integrationComponents = FindObjectsByType<MonoBehaviour>(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)
- {
- Debug.Log($"✅ Found CombatEventIntegration: {combatIntegration.name}");
- // 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)
- {
- Debug.Log($"🎭 Calling ShowCombatChoicePopup with {enemyCount} {enemyType}(s) and combat event reference");
- 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;
- }
- /// <summary>
- /// Handle escape attempt for this specific combat event
- /// </summary>
- public EventResult HandleEscapeAttempt(TravelEventContext context)
- {
- if (!allowRunningAway)
- {
- Debug.LogWarning($"🚫 Running away is not allowed for this combat event: {eventName}");
- return null; // Force battle
- }
- Debug.Log($"🏃 Processing escape attempt for {eventName} (success chance: {runAwaySuccessChance:P})");
- // Roll for escape success
- bool escapeSuccessful = Random.value <= runAwaySuccessChance;
- if (escapeSuccessful)
- {
- return CreateSuccessfulEscapeResult();
- }
- else
- {
- return CreateFailedEscapeResult(context);
- }
- }
- /// <summary>
- /// Create result for successful escape
- /// </summary>
- private EventResult CreateSuccessfulEscapeResult()
- {
- string message = successfulRunAwayMessages[Random.Range(0, successfulRunAwayMessages.Length)];
- Debug.Log($"✅ Escape successful: {message}");
- return new EventResult(message)
- {
- shouldStopTravel = false, // Don't stop travel for successful escape
- startBattle = false,
- eventOccurred = true
- };
- }
- /// <summary>
- /// Create result for failed escape
- /// </summary>
- private EventResult CreateFailedEscapeResult(TravelEventContext context)
- {
- string message = failedRunAwayMessages[Random.Range(0, failedRunAwayMessages.Length)];
- message = message.Replace("{damage}", runAwayHealthPenalty.ToString());
- Debug.Log($"❌ Escape failed: {message}");
- 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;
- }
- }
- /// <summary>
- /// Trading encounter events - merchants, traders, caravans
- /// More likely on roads and near settlements
- /// </summary>
- [CreateAssetMenu(fileName = "New Trading Event", menuName = "RPG/Travel Events/Trading Event")]
- public class TradingTravelEvent : TravelEvent
- {
- [Header("Trading Event Settings")]
- public string[] merchantTypes = { "Traveling Merchant", "Caravan Trader", "Wandering Peddler" };
- public bool canHaveRareItems = true;
- [Range(0f, 1f)]
- public float rareItemChance = 0.3f;
- [Range(0.5f, 1.5f)]
- public float priceModifier = 1f;
- [Header("Trading Event Descriptions")]
- [TextArea(2, 4)]
- public string[] encounterDescriptions = {
- "You encounter a {merchantType} on the road.",
- "A {merchantType} approaches your party with goods to sell.",
- "You come across a {merchantType} resting by the roadside."
- };
- public override EventResult ExecuteEvent(TravelEventContext context)
- {
- string merchantType = merchantTypes[Random.Range(0, merchantTypes.Length)];
- string description = encounterDescriptions[Random.Range(0, encounterDescriptions.Length)];
- description = description.Replace("{merchantType}", merchantType);
- var result = EventResult.SimpleTrading(description, merchantType);
- result.tradingData.hasRareItems = canHaveRareItems && Random.value < rareItemChance;
- result.tradingData.priceModifier = priceModifier;
- return result;
- }
- void OnEnable()
- {
- // Set default values for trading events
- eventType = EventType.Trading;
- rarity = EventRarity.Common;
- // Trading events are more likely on roads and near settlements
- roadChance = 0.9f;
- townChance = 0.7f;
- villageChance = 0.8f;
- bridgeChance = 0.6f; // Common crossing points
- ferryChance = 0.5f;
- // Less likely in wilderness
- forestChance = 0.3f;
- mountainChance = 0.2f;
- plainsChance = 0.5f;
- }
- }
- /// <summary>
- /// Discovery events - finding treasures, resources, or hidden locations
- /// </summary>
- [CreateAssetMenu(fileName = "New Discovery Event", menuName = "RPG/Travel Events/Discovery Event")]
- public class DiscoveryTravelEvent : TravelEvent
- {
- [Header("Discovery Settings")]
- public int minGoldFound = 10;
- public int maxGoldFound = 100;
- public bool canFindItems = true;
- [Header("Discovery Descriptions")]
- [TextArea(2, 4)]
- public string[] discoveryDescriptions = {
- "Your party discovers a hidden cache containing {amount} gold!",
- "While exploring, you find an abandoned stash with {amount} gold pieces.",
- "A keen-eyed party member spots something valuable - {amount} gold!"
- };
- public override EventResult ExecuteEvent(TravelEventContext context)
- {
- int goldFound = Random.Range(minGoldFound, maxGoldFound + 1);
- string description = discoveryDescriptions[Random.Range(0, discoveryDescriptions.Length)];
- description = description.Replace("{amount}", goldFound.ToString());
- return new EventResult(description)
- {
- goldChange = goldFound
- };
- }
- void OnEnable()
- {
- eventType = EventType.Discovery;
- rarity = EventRarity.Uncommon;
- // More likely in remote areas
- forestChance = 0.7f;
- mountainChance = 0.8f;
- plainsChance = 0.4f;
- roadChance = 0.3f;
- townChance = 0.1f;
- }
- }
- /// <summary>
- /// Rest events - safe camping spots, inns, healing springs
- /// </summary>
- [CreateAssetMenu(fileName = "New Rest Event", menuName = "RPG/Travel Events/Rest Event")]
- public class RestTravelEvent : TravelEvent
- {
- [Header("Rest Settings")]
- public int healthRestored = 25;
- public bool restoresAllHealth = false;
- [Header("Rest Descriptions")]
- [TextArea(2, 4)]
- public string[] restDescriptions = {
- "Your party finds a peaceful grove perfect for resting and recovers {health} health.",
- "A natural spring provides refreshing water, restoring {health} health to your party.",
- "Your party discovers a safe camping spot and takes time to tend wounds, recovering {health} health."
- };
- public override EventResult ExecuteEvent(TravelEventContext context)
- {
- int actualHealing = restoresAllHealth ? 100 : healthRestored;
- string description = restDescriptions[Random.Range(0, restDescriptions.Length)];
- description = description.Replace("{health}", actualHealing.ToString());
- return new EventResult(description)
- {
- healthChange = actualHealing
- };
- }
- void OnEnable()
- {
- eventType = EventType.Rest;
- rarity = EventRarity.Common;
- // More likely in natural areas
- forestChance = 0.8f;
- riverChance = 0.9f;
- lakeChance = 0.9f;
- plainsChance = 0.6f;
- mountainChance = 0.5f;
- roadChance = 0.4f;
- townChance = 0.2f;
- }
- }
- /// <summary>
- /// Hazard events - natural dangers, traps, environmental challenges
- /// </summary>
- [CreateAssetMenu(fileName = "New Hazard Event", menuName = "RPG/Travel Events/Hazard Event")]
- public class HazardTravelEvent : TravelEvent
- {
- [Header("Hazard Settings")]
- public int minHealthLoss = 5;
- public int maxHealthLoss = 20;
- public int goldCost = 0; // Cost to avoid the hazard
- [Header("Hazard Descriptions")]
- [TextArea(2, 4)]
- public string[] hazardDescriptions = {
- "Your party gets caught in a sudden rockslide, losing {damage} health.",
- "Treacherous terrain causes injuries to your party members, resulting in {damage} health loss.",
- "A hidden pit trap catches one of your party members, causing {damage} damage."
- };
- public override EventResult ExecuteEvent(TravelEventContext context)
- {
- int damage = Random.Range(minHealthLoss, maxHealthLoss + 1);
- string description = hazardDescriptions[Random.Range(0, hazardDescriptions.Length)];
- description = description.Replace("{damage}", damage.ToString());
- return new EventResult(description)
- {
- healthChange = -damage,
- goldChange = -goldCost
- };
- }
- void OnEnable()
- {
- eventType = EventType.Hazard;
- rarity = EventRarity.Common;
- // More likely in dangerous terrain
- mountainChance = 0.9f;
- forestChance = 0.6f;
- riverChance = 0.7f;
- oceanChance = 0.8f;
- // Less likely in safe areas
- roadChance = 0.2f;
- townChance = 0.1f;
- villageChance = 0.2f;
- plainsChance = 0.4f;
- }
- }
|