| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 |
- using UnityEngine;
- /// <summary>
- /// Integration manager that connects TravelEventSystem with CombatEventPopup
- /// Handles the choice between battle and escape when combat events occur
- /// </summary>
- public class CombatEventIntegration : MonoBehaviour
- {
- [Header("Combat Popup Integration")]
- [Tooltip("Use either the original CombatEventPopup or the new CombatEventPopupUXML")]
- public CombatEventPopup combatEventPopup; // Original popup (legacy)
- public CombatEventPopupUXML combatEventPopupUXML; // New UXML-based popup
- public GameObject combatPopupPrefab; // Optional: if popup component not already in scene
- // Component references
- private TravelEventSystem travelEventSystem;
- private TravelEventUI eventUI;
- private TeamTravelSystem teamTravelSystem;
- // Current combat state
- private bool isHandlingCombat = false;
- private CombatTravelEvent currentCombatEvent; // Store reference to the current combat event
- void Start()
- {
- // Find required components - try same GameObject first, then search scene
- travelEventSystem = GetComponent<TravelEventSystem>();
- if (travelEventSystem == null)
- travelEventSystem = FindFirstObjectByType<TravelEventSystem>();
- eventUI = FindFirstObjectByType<TravelEventUI>();
- teamTravelSystem = FindFirstObjectByType<TeamTravelSystem>();
- if (travelEventSystem == null)
- {
- Debug.LogError("❌ Combat Event Integration requires TravelEventSystem in the scene!");
- Debug.LogError(" Please ensure you have a GameObject with TravelEventSystem component.");
- enabled = false;
- return;
- }
- else if (GetComponent<TravelEventSystem>() == null)
- {
- Debug.LogWarning("⚠️ CombatEventIntegration is not on the same GameObject as TravelEventSystem.");
- Debug.LogWarning(" Consider moving it to the TravelEventSystem GameObject for better organization.");
- }
- // Try to find existing popup components first
- if (combatEventPopup == null)
- combatEventPopup = FindFirstObjectByType<CombatEventPopup>();
- if (combatEventPopupUXML == null)
- combatEventPopupUXML = FindFirstObjectByType<CombatEventPopupUXML>();
- // If no popup component found and we have a prefab, instantiate it
- if (combatEventPopup == null && combatEventPopupUXML == null && combatPopupPrefab != null)
- {
- GameObject popupInstance = Instantiate(combatPopupPrefab);
- combatEventPopup = popupInstance.GetComponent<CombatEventPopup>();
- combatEventPopupUXML = popupInstance.GetComponent<CombatEventPopupUXML>();
- if (combatEventPopup == null && combatEventPopupUXML == null)
- {
- Debug.LogError("❌ Combat popup prefab does not contain CombatEventPopup or CombatEventPopupUXML component!");
- enabled = false;
- return;
- }
- }
- if (combatEventPopup == null && combatEventPopupUXML == null)
- {
- Debug.LogError("❌ Combat Event Integration requires a CombatEventPopup or CombatEventPopupUXML component!");
- Debug.LogError(" Either add one of these components to a GameObject in the scene,");
- Debug.LogError(" or assign a prefab with one of these components to combatPopupPrefab field.");
- enabled = false;
- return;
- }
- // Setup combat popup callbacks
- if (combatEventPopup != null)
- combatEventPopup.OnCombatDecision += HandleCombatDecision;
- if (combatEventPopupUXML != null)
- combatEventPopupUXML.OnCombatDecision += HandleCombatDecision;
- }
- void OnDestroy()
- {
- if (combatEventPopup != null)
- combatEventPopup.OnCombatDecision -= HandleCombatDecision;
- if (combatEventPopupUXML != null)
- combatEventPopupUXML.OnCombatDecision -= HandleCombatDecision;
- }
- /// <summary>
- /// Call this method when a combat event occurs to show the popup
- /// This should be called from TravelEventTypes.cs in the ExecuteEvent method
- /// </summary>
- public void ShowCombatChoicePopup(BattleEventData battleData, TravelEventContext context, string eventDescription, CombatTravelEvent combatEvent = null)
- {
- if (isHandlingCombat || battleData == null)
- return;
- isHandlingCombat = true;
- currentCombatEvent = combatEvent; // Store reference to the original combat event
- // Store battle data for later use
- currentBattleData = battleData;
- currentContext = context;
- // Show combat popup - try UXML version first, then fallback to original
- if (combatEventPopupUXML != null)
- {
- combatEventPopupUXML.OnCombatDecision = HandleCombatDecision;
- combatEventPopupUXML.ShowCombatEncounter(battleData, context, eventDescription);
- }
- else if (combatEventPopup != null)
- {
- combatEventPopup.OnCombatDecision = HandleCombatDecision;
- combatEventPopup.ShowCombatEncounter(battleData, context, eventDescription);
- }
- else
- {
- Debug.LogError("No combat popup component assigned! Please assign either CombatEventPopup or CombatEventPopupUXML.");
- isHandlingCombat = false;
- }
- }
- // Store current battle data
- private BattleEventData currentBattleData;
- private TravelEventContext currentContext;
- /// <summary>
- /// Handle the player's combat decision from the popup
- /// </summary>
- private void HandleCombatDecision(bool chooseToAttack)
- {
- if (!isHandlingCombat || currentBattleData == null)
- return;
- isHandlingCombat = false;
- if (chooseToAttack)
- {
- HandleAttackChoice();
- }
- else
- {
- HandleRunAwayChoice();
- }
- // Clear stored data
- currentBattleData = null;
- currentContext = null;
- }
- /// <summary>
- /// Handle when player chooses to attack
- /// </summary>
- private void HandleAttackChoice()
- {
- // Create and return the battle result that will start the battle
- var battleResult = EventResult.SimpleBattle(
- $"Your party prepares for battle against {currentBattleData.enemyCount} {currentBattleData.enemyType}!",
- currentBattleData.enemyCount,
- currentBattleData.enemyType
- );
- // Copy over the enemy character data
- battleResult.battleData.enemyCharacterData = currentBattleData.enemyCharacterData;
- // Apply the battle result through the travel event system
- ApplyBattleResult(battleResult);
- }
- /// <summary>
- /// Handle when player chooses to run away
- /// </summary>
- private void HandleRunAwayChoice()
- {
- EventResult escapeResult = null;
- // Use the combat event's escape handling if available
- if (currentCombatEvent != null)
- {
- escapeResult = currentCombatEvent.HandleEscapeAttempt(currentContext);
- }
- else
- {
- Debug.LogWarning("⚠️ No combat event reference - using hardcoded fallback escape handling");
- // Hardcoded fallback values when no combat event is available
- const float fallbackSuccessChance = 0.75f;
- bool escapeSuccessful = Random.value <= fallbackSuccessChance;
- if (escapeSuccessful)
- {
- escapeResult = CreateFallbackSuccessfulEscape();
- }
- else
- {
- escapeResult = CreateFallbackFailedEscape();
- }
- }
- // Apply the escape result
- if (escapeResult != null)
- {
- ApplyBattleResult(escapeResult);
- }
- else
- {
- Debug.LogWarning("⚠️ Escape not allowed by combat event - forcing battle");
- HandleAttackChoice();
- }
- }
- /// <summary>
- /// Create fallback successful escape result when no combat event is available
- /// </summary>
- private EventResult CreateFallbackSuccessfulEscape()
- {
- string message = "Your party successfully escapes from the enemies!";
- return new EventResult(message)
- {
- shouldStopTravel = false,
- startBattle = false,
- eventOccurred = true,
- healthChange = 0
- };
- }
- /// <summary>
- /// Create fallback failed escape result when no combat event is available
- /// </summary>
- private EventResult CreateFallbackFailedEscape()
- {
- const int fallbackHealthPenalty = 5; // Hardcoded fallback value
- string message = $"The enemies catch up to your party! You take {fallbackHealthPenalty} damage while trying to escape.";
- return new EventResult(message)
- {
- shouldStopTravel = true,
- startBattle = false,
- eventOccurred = true,
- healthChange = -fallbackHealthPenalty
- };
- } /// <summary>
- /// Apply battle result through the travel event system
- /// </summary>
- private void ApplyBattleResult(EventResult result)
- {
- // Apply resource changes
- if (result.healthChange != 0)
- {
- Debug.Log($"❤️ Health changed by {result.healthChange}");
- // TODO: Actually apply health changes to party
- }
- if (result.goldChange != 0)
- {
- Debug.Log($"💰 Gold changed by {result.goldChange}");
- // TODO: Actually apply gold changes to party
- }
- // Handle travel stopping
- if (result.shouldStopTravel && teamTravelSystem != null)
- {
- teamTravelSystem.CancelJourney();
- }
- // Handle battle start
- if (result.startBattle)
- {
- // Use the new CombatSceneManager to handle battle transition
- MonoBehaviour combatSceneManager = FindCombatSceneManager();
- if (combatSceneManager != null)
- {
- // Use reflection to call StartCombatEncounter method
- var method = combatSceneManager.GetType().GetMethod("StartCombatEncounter");
- if (method != null)
- {
- method.Invoke(combatSceneManager, new object[] { result.battleData, currentContext });
- }
- }
- }
- }
- /// <summary>
- /// Check if the system is currently handling a combat choice
- /// </summary>
- public bool IsHandlingCombat => isHandlingCombat;
- /// <summary>
- /// Cancel current combat handling (for cleanup)
- /// </summary>
- public void CancelCombatHandling()
- {
- if (isHandlingCombat)
- {
- isHandlingCombat = false;
- currentBattleData = null;
- currentContext = null;
- if (combatEventPopup != null)
- combatEventPopup.ForceClose();
- }
- }
- /// <summary>
- /// Find CombatSceneManager using reflection to avoid compilation issues
- /// </summary>
- private MonoBehaviour FindCombatSceneManager()
- {
- // First try to find it by component type name
- var allComponents = FindObjectsByType<MonoBehaviour>(FindObjectsSortMode.None);
- var combatSceneManager = System.Array.Find(allComponents,
- comp => comp.GetType().Name == "CombatSceneManager");
- return combatSceneManager;
- }
- }
|