BattleActionIntegration.cs 21 KB

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