BattleActionIntegration.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. using UnityEngine;
  2. using UnityEngine.UIElements;
  3. /// <summary>
  4. /// Integration script that connects the new battle action system with existing character selection
  5. /// This allows switching between the old click-drag system and the new action wheel system
  6. /// </summary>
  7. public class BattleActionIntegration : MonoBehaviour
  8. {
  9. [Header("System References")]
  10. public PlayerDecisionController playerDecisionController;
  11. public BattleActionSystem battleActionSystem;
  12. public BattleActionWheel actionWheel; // Legacy Canvas-based wheel
  13. public EnemySelectionUI enemySelectionUI; // TODO: Add after compilation
  14. public BattleItemSelector itemSelectionUI;
  15. [Header("Settings")]
  16. [Tooltip("Enable new action wheel system (false = use old click-drag system)")]
  17. public bool useNewActionSystem = false; // Changed to false by default for simpler testing
  18. public KeyCode actionWheelKey = KeyCode.Q; // Use Q consistently
  19. [Space]
  20. [Tooltip("Press this key to toggle between action systems")]
  21. public KeyCode toggleSystemKey = KeyCode.T;
  22. private Character lastSelectedCharacter;
  23. private MonoBehaviour simpleWheelComponent;
  24. private string currentInstruction = "";
  25. private float instructionTimer = 0f;
  26. private float instructionDuration = 5f;
  27. void Start()
  28. {
  29. Debug.Log("🚀 BattleActionIntegration starting...");
  30. // Find components if not assigned
  31. if (playerDecisionController == null)
  32. playerDecisionController = FindFirstObjectByType<PlayerDecisionController>();
  33. if (battleActionSystem == null)
  34. battleActionSystem = FindFirstObjectByType<BattleActionSystem>();
  35. if (actionWheel == null)
  36. actionWheel = FindFirstObjectByType<BattleActionWheel>();
  37. if (enemySelectionUI == null)
  38. enemySelectionUI = FindFirstObjectByType<EnemySelectionUI>();
  39. if (itemSelectionUI == null)
  40. itemSelectionUI = FindFirstObjectByType<BattleItemSelector>();
  41. // Disable old drag system if using new action system (but allow re-enabling for targeting)
  42. if (useNewActionSystem && playerDecisionController != null)
  43. {
  44. // Don't completely disable - we'll use it for targeting after action selection
  45. Debug.Log("🎮 PlayerDecisionController will be used for targeting after action selection");
  46. }
  47. // Try to find or create a simple wheel component
  48. var existingWheels = FindObjectsByType<MonoBehaviour>(FindObjectsSortMode.None);
  49. foreach (var comp in existingWheels)
  50. {
  51. if (comp.GetType().Name == "SimpleActionWheel")
  52. {
  53. simpleWheelComponent = comp;
  54. Debug.Log("🎮 Found existing SimpleActionWheel");
  55. break;
  56. }
  57. }
  58. if (simpleWheelComponent == null)
  59. {
  60. // Create simple wheel if it doesn't exist
  61. GameObject wheelObj = new GameObject("SimpleActionWheel");
  62. // Use reflection to add the component
  63. var componentType = System.Type.GetType("SimpleActionWheel");
  64. if (componentType != null)
  65. {
  66. simpleWheelComponent = wheelObj.AddComponent(componentType) as MonoBehaviour;
  67. Debug.Log("🎮 Created SimpleActionWheel automatically");
  68. }
  69. else
  70. {
  71. Debug.LogError("❌ Could not find SimpleActionWheel type");
  72. }
  73. }
  74. // Subscribe to events
  75. if (battleActionSystem != null)
  76. {
  77. battleActionSystem.OnActionCompleted += OnCharacterActionCompleted;
  78. }
  79. // Connect SimpleActionWheel events using reflection
  80. if (simpleWheelComponent != null)
  81. {
  82. ConnectSimpleWheelEvents();
  83. }
  84. Debug.Log($"✅ BattleActionIntegration initialized - useNewActionSystem: {useNewActionSystem}, actionWheelKey: {actionWheelKey}");
  85. }
  86. void Update()
  87. {
  88. // Allow toggling between systems
  89. if (Input.GetKeyDown(toggleSystemKey))
  90. {
  91. ToggleActionSystem();
  92. }
  93. if (useNewActionSystem)
  94. {
  95. HandleNewActionSystemInput();
  96. }
  97. // Note: When useNewActionSystem is false, the old PlayerDecisionController.Update()
  98. // will handle input automatically - no need to interfere
  99. // Update instruction timer
  100. if (instructionTimer > 0f)
  101. {
  102. instructionTimer -= Time.deltaTime;
  103. if (instructionTimer <= 0f)
  104. {
  105. currentInstruction = "";
  106. }
  107. }
  108. }
  109. void OnGUI()
  110. {
  111. // Show instruction message if active
  112. if (!string.IsNullOrEmpty(currentInstruction))
  113. {
  114. GUIStyle instructionStyle = new GUIStyle(GUI.skin.label);
  115. instructionStyle.fontSize = 18;
  116. instructionStyle.fontStyle = FontStyle.Bold;
  117. instructionStyle.alignment = TextAnchor.MiddleCenter;
  118. instructionStyle.normal.textColor = Color.yellow;
  119. Rect instructionRect = new Rect(0, 50, Screen.width, 30);
  120. // Background
  121. GUI.color = new Color(0, 0, 0, 0.7f);
  122. GUI.Box(instructionRect, "");
  123. // Text
  124. GUI.color = Color.white;
  125. GUI.Label(instructionRect, currentInstruction, instructionStyle);
  126. }
  127. if (!useNewActionSystem) return;
  128. // Simple UI for testing
  129. GUILayout.BeginArea(new Rect(10, 10, 300, 250));
  130. GUILayout.Label("Battle Action System");
  131. GUILayout.Label($"Action Key: {actionWheelKey}");
  132. GUILayout.Label($"Simple Wheel: {(simpleWheelComponent != null ? "✅" : "❌")}");
  133. if (lastSelectedCharacter != null)
  134. {
  135. GUILayout.Label($"Selected: {lastSelectedCharacter.CharacterName}");
  136. var actionData = lastSelectedCharacter.GetEnhancedActionData<EnhancedCharacterActionData>();
  137. if (actionData != null && actionData.hasValidAction)
  138. {
  139. GUILayout.Label($"Action: {actionData.GetActionDescription()}");
  140. }
  141. }
  142. else
  143. {
  144. GUILayout.Label("No character selected");
  145. GUILayout.Label("Click a player character to select");
  146. }
  147. GUILayout.Label($"Press {actionWheelKey} to show action wheel");
  148. if (GUILayout.Button("Test Action Wheel"))
  149. {
  150. var testCharacter = FindFirstObjectByType<Character>();
  151. if (testCharacter != null)
  152. {
  153. ShowActionWheelForCharacter(testCharacter);
  154. }
  155. }
  156. GUILayout.EndArea();
  157. }
  158. private void HandleNewActionSystemInput()
  159. {
  160. // Check for character selection
  161. if (Input.GetMouseButtonDown(0))
  162. {
  163. Character selectedCharacter = GetCharacterAtMousePosition();
  164. if (selectedCharacter != null)
  165. {
  166. Debug.Log($"🖱️ Clicked on character: {selectedCharacter.CharacterName} - Tag: {selectedCharacter.tag}");
  167. if (selectedCharacter.CompareTag("Player"))
  168. {
  169. Debug.Log($"✅ Confirmed player character: {selectedCharacter.CharacterName}");
  170. SelectCharacterForAction(selectedCharacter);
  171. }
  172. else
  173. {
  174. Debug.Log($"❌ Not a player character: {selectedCharacter.CharacterName} (Tag: {selectedCharacter.tag})");
  175. // Try to force selection anyway for testing
  176. Debug.Log($"🧪 Trying to select anyway for testing...");
  177. SelectCharacterForAction(selectedCharacter);
  178. }
  179. }
  180. else
  181. {
  182. Debug.Log("🖱️ Clicked but no character found");
  183. }
  184. }
  185. // Show action wheel with Q key
  186. if (Input.GetKeyDown(actionWheelKey))
  187. {
  188. if (lastSelectedCharacter != null)
  189. {
  190. Debug.Log($"⌨️ {actionWheelKey} pressed, showing wheel for {lastSelectedCharacter.CharacterName}");
  191. ShowActionWheelForCharacter(lastSelectedCharacter);
  192. }
  193. else
  194. {
  195. Debug.Log($"⌨️ {actionWheelKey} pressed but no character selected");
  196. }
  197. }
  198. }
  199. private Character GetCharacterAtMousePosition()
  200. {
  201. Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
  202. RaycastHit hit;
  203. if (Physics.Raycast(ray, out hit))
  204. {
  205. return hit.collider.GetComponent<Character>();
  206. }
  207. return null;
  208. }
  209. private void SelectCharacterForAction(Character character)
  210. {
  211. // Clear previous selection
  212. if (lastSelectedCharacter != null)
  213. {
  214. lastSelectedCharacter.SetVisualState(ActionDecisionState.NoAction);
  215. }
  216. lastSelectedCharacter = character;
  217. // Initialize enhanced action data if needed
  218. var actionData = character.GetEnhancedActionData<EnhancedCharacterActionData>();
  219. if (actionData == null)
  220. {
  221. // Create instance at runtime to avoid compilation issues
  222. actionData = new EnhancedCharacterActionData();
  223. character.SetEnhancedActionData(actionData);
  224. }
  225. // Highlight selected character
  226. character.SetVisualState(ActionDecisionState.NoAction);
  227. Debug.Log($"🎯 Selected character for action: {character.CharacterName}");
  228. // Don't auto-show wheel - let user press Q manually
  229. // if (useNewActionSystem)
  230. // {
  231. // ShowActionWheelForCharacter(character);
  232. // }
  233. }
  234. private void ShowActionWheelForCharacter(Character character)
  235. {
  236. Debug.Log($"🎯 ShowActionWheelForCharacter called for: {character.CharacterName}");
  237. // Try simple wheel first
  238. if (simpleWheelComponent != null)
  239. {
  240. Debug.Log($"🎮 Found SimpleActionWheel component: {simpleWheelComponent.GetType().Name}");
  241. // Use reflection to call ShowWheelForCharacter
  242. var method = simpleWheelComponent.GetType().GetMethod("ShowWheelForCharacter");
  243. if (method != null)
  244. {
  245. Debug.Log("🔧 Calling ShowWheelForCharacter via reflection...");
  246. method.Invoke(simpleWheelComponent, new object[] { character });
  247. return;
  248. }
  249. else
  250. {
  251. Debug.LogError("❌ ShowWheelForCharacter method not found on SimpleActionWheel!");
  252. }
  253. }
  254. else
  255. {
  256. Debug.LogError("❌ simpleWheelComponent is null!");
  257. }
  258. // Fallback to battle action system
  259. if (battleActionSystem != null)
  260. {
  261. Debug.Log("🔄 Falling back to BattleActionSystem...");
  262. battleActionSystem.ShowActionWheel(character);
  263. }
  264. else
  265. {
  266. Debug.LogError("BattleActionIntegration: No action wheel system found!");
  267. }
  268. }
  269. private void ConnectSimpleWheelEvents()
  270. {
  271. if (simpleWheelComponent == null)
  272. {
  273. Debug.LogError("❌ simpleWheelComponent is null in ConnectSimpleWheelEvents");
  274. return;
  275. }
  276. Debug.Log($"🔧 Connecting events for SimpleActionWheel component: {simpleWheelComponent.GetType().Name}");
  277. // Use reflection to connect to OnActionSelected event
  278. var eventInfo = simpleWheelComponent.GetType().GetEvent("OnActionSelected");
  279. if (eventInfo != null)
  280. {
  281. Debug.Log($"✅ Found OnActionSelected event: {eventInfo.EventHandlerType}");
  282. // Create delegate that matches the event signature: Action<BattleActionType>
  283. var delegateType = eventInfo.EventHandlerType;
  284. var methodInfo = this.GetType().GetMethod("OnActionSelected", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
  285. if (methodInfo != null)
  286. {
  287. Debug.Log($"✅ Found OnActionSelected method: {methodInfo.Name}");
  288. var handler = System.Delegate.CreateDelegate(delegateType, this, methodInfo);
  289. eventInfo.AddEventHandler(simpleWheelComponent, handler);
  290. Debug.Log("✅ Successfully connected SimpleActionWheel.OnActionSelected event");
  291. }
  292. else
  293. {
  294. Debug.LogError("❌ Could not find OnActionSelected method in BattleActionIntegration");
  295. }
  296. }
  297. else
  298. {
  299. Debug.LogError("❌ Could not find OnActionSelected event in SimpleActionWheel");
  300. }
  301. }
  302. private void OnActionSelected(BattleActionType actionType)
  303. {
  304. Debug.Log($"🔥 OnActionSelected called with: {actionType}");
  305. if (lastSelectedCharacter == null)
  306. {
  307. Debug.LogWarning("❌ Action selected but no character selected!");
  308. return;
  309. }
  310. Debug.Log($"🎯 {lastSelectedCharacter.CharacterName} selected action: {actionType}");
  311. // Set action data for the character
  312. var actionData = lastSelectedCharacter.GetEnhancedActionData<EnhancedCharacterActionData>();
  313. if (actionData == null)
  314. {
  315. actionData = new EnhancedCharacterActionData();
  316. lastSelectedCharacter.SetEnhancedActionData(actionData);
  317. Debug.Log($"📝 Created new EnhancedCharacterActionData for {lastSelectedCharacter.CharacterName}");
  318. }
  319. // Configure action based on type and enable targeting mode
  320. switch (actionType)
  321. {
  322. case BattleActionType.Attack:
  323. actionData.actionType = actionType;
  324. Debug.Log("🗡️ Attack selected - Now drag from character to target enemy!");
  325. ShowInstructionMessage("ATTACK: Drag from character to enemy");
  326. StartTargetingMode(lastSelectedCharacter, actionType);
  327. break;
  328. case BattleActionType.Move:
  329. actionData.actionType = actionType;
  330. Debug.Log("👟 Move selected - Now drag from character to target position!");
  331. ShowInstructionMessage("MOVE: Drag from character to target position");
  332. StartTargetingMode(lastSelectedCharacter, actionType);
  333. break;
  334. case BattleActionType.UseItem:
  335. actionData.actionType = actionType;
  336. Debug.Log("🧪 Use Item selected - showing item selection UI");
  337. ShowInstructionMessage("USE ITEM: Select item from list");
  338. ShowItemSelection(lastSelectedCharacter);
  339. break;
  340. case BattleActionType.CastSpell:
  341. actionData.actionType = actionType;
  342. actionData.state = ActionDecisionState.ActionSelected;
  343. lastSelectedCharacter.SetVisualState(ActionDecisionState.ActionSelected);
  344. Debug.Log("✨ Cast Spell selected - implement spell selection UI");
  345. break;
  346. case BattleActionType.Defend:
  347. actionData.actionType = actionType;
  348. actionData.state = ActionDecisionState.ActionSelected;
  349. lastSelectedCharacter.SetVisualState(ActionDecisionState.ActionSelected);
  350. Debug.Log("🛡️ Defend action set - character will defend this turn");
  351. break;
  352. case BattleActionType.RunAway:
  353. actionData.actionType = actionType;
  354. actionData.state = ActionDecisionState.ActionSelected;
  355. lastSelectedCharacter.SetVisualState(ActionDecisionState.ActionSelected);
  356. Debug.Log("💨 Run Away action set - character will attempt to flee");
  357. break;
  358. }
  359. Debug.Log($"✅ Action {actionType} configured for {lastSelectedCharacter.CharacterName}");
  360. }
  361. private void StartTargetingMode(Character character, BattleActionType actionType)
  362. {
  363. Debug.Log($"🎯 Starting targeting mode for {character.CharacterName} with action {actionType}");
  364. // Enable the PlayerDecisionController to handle targeting
  365. if (playerDecisionController != null)
  366. {
  367. // Use the new public method to start targeting
  368. playerDecisionController.StartTargetingForCharacter(character, actionType);
  369. Debug.Log($"✅ PlayerDecisionController targeting started for {actionType}");
  370. }
  371. else
  372. {
  373. Debug.LogError("❌ PlayerDecisionController not found - cannot start targeting mode");
  374. }
  375. }
  376. private void ShowItemSelection(Character character)
  377. {
  378. Debug.Log($"🧪 Showing item selection for {character.CharacterName}");
  379. if (itemSelectionUI != null)
  380. {
  381. // Subscribe to item selection events
  382. itemSelectionUI.OnItemSelected -= OnItemSelected;
  383. itemSelectionUI.OnSelectionCancelled -= OnItemSelectionCancelled;
  384. itemSelectionUI.OnItemSelected += OnItemSelected;
  385. itemSelectionUI.OnSelectionCancelled += OnItemSelectionCancelled;
  386. itemSelectionUI.ShowItemSelection(character);
  387. }
  388. else
  389. {
  390. Debug.LogError("❌ BattleItemSelector not found!");
  391. // Fallback: Complete action immediately
  392. var actionData = character.GetEnhancedActionData<EnhancedCharacterActionData>();
  393. if (actionData != null)
  394. {
  395. actionData.state = ActionDecisionState.ActionSelected;
  396. character.SetVisualState(ActionDecisionState.ActionSelected);
  397. }
  398. }
  399. }
  400. private void OnItemSelected(string itemName, int itemIndex)
  401. {
  402. Debug.Log($"📦 Item selected: {itemName} (index: {itemIndex})");
  403. if (lastSelectedCharacter != null)
  404. {
  405. var actionData = lastSelectedCharacter.GetEnhancedActionData<EnhancedCharacterActionData>();
  406. if (actionData != null)
  407. {
  408. actionData.selectedItemName = itemName;
  409. actionData.selectedItemIndex = itemIndex;
  410. actionData.state = ActionDecisionState.ActionSelected;
  411. lastSelectedCharacter.SetVisualState(ActionDecisionState.ActionSelected);
  412. Debug.Log($"✅ {lastSelectedCharacter.CharacterName} will use {itemName}");
  413. }
  414. }
  415. }
  416. private void OnItemSelectionCancelled()
  417. {
  418. Debug.Log("❌ Item selection cancelled");
  419. if (lastSelectedCharacter != null)
  420. {
  421. var actionData = lastSelectedCharacter.GetEnhancedActionData<EnhancedCharacterActionData>();
  422. if (actionData != null)
  423. {
  424. actionData.Reset();
  425. lastSelectedCharacter.SetVisualState(ActionDecisionState.NoAction);
  426. }
  427. }
  428. }
  429. private void OnCharacterActionCompleted(Character character)
  430. {
  431. Debug.Log($"✅ Action completed for {character.CharacterName}");
  432. // Clear selection after action is complete
  433. if (character == lastSelectedCharacter)
  434. {
  435. lastSelectedCharacter = null;
  436. }
  437. }
  438. /// <summary>
  439. /// Manually trigger action selection for a character (for use by other systems)
  440. /// </summary>
  441. public void SelectCharacter(Character character)
  442. {
  443. SelectCharacterForAction(character);
  444. }
  445. /// <summary>
  446. /// Execute all selected actions (for turn-based systems)
  447. /// </summary>
  448. public void ExecuteAllPlayerActions()
  449. {
  450. Character[] playerCharacters = FindObjectsByType<Character>(FindObjectsSortMode.None);
  451. foreach (Character character in playerCharacters)
  452. {
  453. var actionData = character.GetEnhancedActionData<EnhancedCharacterActionData>();
  454. if (character.CompareTag("Player") && actionData != null && actionData.hasValidAction)
  455. {
  456. if (battleActionSystem != null)
  457. {
  458. battleActionSystem.ExecuteCharacterAction(character);
  459. }
  460. }
  461. }
  462. }
  463. /// <summary>
  464. /// Switch between old and new action systems
  465. /// </summary>
  466. public void ToggleActionSystem()
  467. {
  468. useNewActionSystem = !useNewActionSystem;
  469. // Enable/disable appropriate systems
  470. if (playerDecisionController != null)
  471. {
  472. playerDecisionController.enabled = !useNewActionSystem;
  473. // If switching to old system, make sure it's properly enabled
  474. if (!useNewActionSystem)
  475. {
  476. playerDecisionController.SetEnabled(true);
  477. }
  478. }
  479. // Clear any instruction messages when switching
  480. currentInstruction = "";
  481. instructionTimer = 0f;
  482. Debug.Log($"🎯 Action system switched to: {(useNewActionSystem ? "New Action Wheel (Q to open wheel)" : "Old Click-Drag (direct drag to move/attack)")}");
  483. }
  484. /// <summary>
  485. /// Check if all players have selected actions
  486. /// </summary>
  487. public bool AllPlayersHaveActions()
  488. {
  489. Character[] playerCharacters = FindObjectsByType<Character>(FindObjectsSortMode.None);
  490. foreach (Character character in playerCharacters)
  491. {
  492. if (character.CompareTag("Player"))
  493. {
  494. var actionData = character.GetEnhancedActionData<EnhancedCharacterActionData>();
  495. if (actionData == null || !actionData.hasValidAction)
  496. {
  497. return false;
  498. }
  499. }
  500. }
  501. return true;
  502. }
  503. /// <summary>
  504. /// Reset all player actions (useful for new turns)
  505. /// </summary>
  506. public void ResetAllPlayerActions()
  507. {
  508. Character[] playerCharacters = FindObjectsByType<Character>(FindObjectsSortMode.None);
  509. foreach (Character character in playerCharacters)
  510. {
  511. if (character.CompareTag("Player"))
  512. {
  513. var actionData = character.GetEnhancedActionData<EnhancedCharacterActionData>();
  514. if (actionData != null)
  515. actionData.Reset();
  516. character.SetVisualState(ActionDecisionState.NoAction);
  517. }
  518. }
  519. lastSelectedCharacter = null;
  520. Debug.Log("🔄 All player actions reset");
  521. }
  522. private void ShowInstructionMessage(string message)
  523. {
  524. currentInstruction = message;
  525. instructionTimer = instructionDuration;
  526. Debug.Log($"📢 Instruction: {message}");
  527. }
  528. }