PlayerDecisionController .cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. using System.Collections.Generic;
  2. using Unity.VisualScripting;
  3. using UnityEngine;
  4. public class PlayerDecisionController : MonoBehaviour
  5. {
  6. [Header("References")]
  7. public LayerMask enemyLayerMask = 1 << 10; // Enemies are on layer 10
  8. public LayerMask playerLayerMask = 1 << 9; // Players are on layer 9
  9. [Header("Settings")]
  10. public float enemySnapDistance = 1f;
  11. private List<Character> playerCharacters = new List<Character>();
  12. private Character selectedCharacter;
  13. private TargetingLine targetingLine;
  14. private Camera mainCamera;
  15. private bool isDragging = false;
  16. private Vector3 dragStartPosition;
  17. private bool isEnabled = true;
  18. private List<TargetingLine> activeActionLines = new List<TargetingLine>();
  19. void Awake()
  20. {
  21. mainCamera = Camera.main;
  22. targetingLine = GetComponent<TargetingLine>();
  23. if (targetingLine == null)
  24. {
  25. targetingLine = gameObject.AddComponent<TargetingLine>();
  26. }
  27. }
  28. void Start()
  29. {
  30. InitializePlayerCharacters();
  31. }
  32. void Update()
  33. {
  34. HandleInput();
  35. }
  36. private void InitializePlayerCharacters()
  37. {
  38. // Get player characters from GameManager if available
  39. if (GameManager.Instance != null)
  40. {
  41. playerCharacters.Clear();
  42. foreach (GameObject playerGO in GameManager.Instance.playerCharacters)
  43. {
  44. Character character = playerGO.GetComponent<Character>();
  45. if (character != null)
  46. {
  47. playerCharacters.Add(character);
  48. }
  49. }
  50. }
  51. else
  52. {
  53. // Fallback: find all characters (for testing without GameManager)
  54. Character[] characters = FindObjectsByType<Character>(FindObjectsSortMode.None);
  55. playerCharacters.AddRange(characters);
  56. }
  57. foreach (Character character in playerCharacters)
  58. {
  59. character.actionData.Reset();
  60. character.SetVisualState(ActionDecisionState.NoAction);
  61. }
  62. }
  63. private void HandleInput()
  64. {
  65. if (!isEnabled) return;
  66. if (Input.GetMouseButtonDown(0)) // Left click
  67. {
  68. HandleLeftClickDown();
  69. }
  70. else if (Input.GetMouseButton(0) && isDragging) // Left drag
  71. {
  72. HandleLeftDrag();
  73. }
  74. else if (Input.GetMouseButtonUp(0)) // Left release
  75. {
  76. HandleLeftClickUp();
  77. }
  78. else if (Input.GetMouseButtonDown(1)) // Right click
  79. {
  80. HandleRightClick();
  81. }
  82. }
  83. private void HandleLeftClickDown()
  84. {
  85. Vector3 mouseWorldPosition = GetMouseWorldPosition();
  86. Character clickedCharacter = GetPlayerCharacterAtPosition(mouseWorldPosition);
  87. if (clickedCharacter != null)
  88. {
  89. selectedCharacter = clickedCharacter;
  90. isDragging = true;
  91. dragStartPosition = clickedCharacter.transform.position;
  92. // Clear any existing action lines before starting new targeting
  93. ClearActionLineForCharacter(clickedCharacter);
  94. targetingLine.StartTargeting(dragStartPosition);
  95. // CinemachineCameraController.Instance.FocusOnCharacter(clickedCharacter.transform);
  96. }
  97. }
  98. private void HandleLeftDrag()
  99. {
  100. if (selectedCharacter == null) return;
  101. Vector3 mouseWorldPos = GetMouseWorldPosition();
  102. GameObject enemyAtMouse = GetEnemyAtPosition(mouseWorldPos);
  103. if (enemyAtMouse != null)
  104. {
  105. // Snap to enemy
  106. Vector3 enemyPos = enemyAtMouse.transform.position;
  107. targetingLine.UpdateTargeting(dragStartPosition, enemyPos, true);
  108. }
  109. else
  110. {
  111. // Follow mouse
  112. targetingLine.UpdateTargeting(dragStartPosition, mouseWorldPos, false);
  113. }
  114. }
  115. private void HandleLeftClickUp()
  116. {
  117. if (!isDragging || selectedCharacter == null) return;
  118. Vector3 mouseWorldPos = GetMouseWorldPosition();
  119. GameObject enemyAtMouse = GetEnemyAtPosition(mouseWorldPos);
  120. if (enemyAtMouse != null)
  121. {
  122. // Set attack target
  123. selectedCharacter.actionData.SetAttackTarget(enemyAtMouse);
  124. }
  125. else
  126. {
  127. // Set move target
  128. selectedCharacter.actionData.SetMoveTarget(mouseWorldPos);
  129. }
  130. selectedCharacter.SetVisualState(selectedCharacter.actionData.state);
  131. // Cleanup
  132. targetingLine.StopTargeting();
  133. selectedCharacter = null;
  134. isDragging = false;
  135. }
  136. private void HandleRightClick()
  137. {
  138. if (isDragging && selectedCharacter != null)
  139. {
  140. // Cancel current action
  141. selectedCharacter.actionData.Reset();
  142. selectedCharacter.SetVisualState(ActionDecisionState.NoAction);
  143. targetingLine.StopTargeting();
  144. selectedCharacter = null;
  145. isDragging = false;
  146. }
  147. else
  148. {
  149. // Right click on character to reset their action
  150. Vector3 mouseWorldPos = GetMouseWorldPosition();
  151. Character clickedCharacter = GetPlayerCharacterAtPosition(mouseWorldPos);
  152. if (clickedCharacter != null)
  153. {
  154. clickedCharacter.actionData.Reset();
  155. clickedCharacter.SetVisualState(ActionDecisionState.NoAction);
  156. }
  157. }
  158. }
  159. private Vector3 GetMouseWorldPosition()
  160. {
  161. Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
  162. RaycastHit hit;
  163. // Raycast against a ground plane or existing colliders
  164. if (Physics.Raycast(ray, out hit, 200f))
  165. {
  166. return hit.point;
  167. }
  168. // Fallback: project onto a horizontal plane at y=0
  169. Plane groundPlane = new Plane(Vector3.up, Vector3.zero);
  170. if (groundPlane.Raycast(ray, out float distance))
  171. {
  172. return ray.GetPoint(distance);
  173. }
  174. return Vector3.zero;
  175. }
  176. private Character GetPlayerCharacterAtPosition(Vector3 worldPosition)
  177. {
  178. Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
  179. RaycastHit hit;
  180. if (Physics.Raycast(ray, out hit, 200f, playerLayerMask))
  181. {
  182. return hit.collider.GetComponent<Character>();
  183. }
  184. // Try raycast without layer mask to see what we're hitting
  185. if (Physics.Raycast(ray, out hit, 200f))
  186. {
  187. }
  188. else
  189. {
  190. }
  191. return null;
  192. }
  193. private GameObject GetEnemyAtPosition(Vector3 worldPosition)
  194. {
  195. Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
  196. RaycastHit hit;
  197. if (Physics.Raycast(ray, out hit, 200f, enemyLayerMask))
  198. {
  199. return hit.collider.gameObject;
  200. }
  201. return null;
  202. }
  203. public bool AllCharactersHaveActions()
  204. {
  205. foreach (var character in playerCharacters)
  206. {
  207. // Characters need actions if they have no action set
  208. if (character.actionData.state == ActionDecisionState.NoAction)
  209. return false;
  210. }
  211. return true;
  212. }
  213. public void ResetAllCharacterActions()
  214. {
  215. foreach (var character in playerCharacters)
  216. {
  217. character.actionData.Reset();
  218. character.SetVisualState(ActionDecisionState.NoAction);
  219. }
  220. }
  221. public void UpdateVisualStates()
  222. {
  223. foreach (var character in playerCharacters)
  224. {
  225. // Update visual states based on current action status
  226. if (character.actionData.state == ActionDecisionState.NoAction)
  227. {
  228. character.SetVisualState(ActionDecisionState.NoAction); // Pink
  229. }
  230. else if (character.HasActionSelected())
  231. {
  232. character.SetVisualState(ActionDecisionState.ActionSelected); // Green
  233. }
  234. }
  235. }
  236. public void RefreshPlayerCharacters()
  237. {
  238. InitializePlayerCharacters();
  239. }
  240. public void SetEnabled(bool enabled)
  241. {
  242. isEnabled = enabled;
  243. if (!enabled)
  244. {
  245. if (isDragging)
  246. {
  247. // Cancel any current dragging operation
  248. targetingLine.StopTargeting();
  249. selectedCharacter = null;
  250. isDragging = false;
  251. }
  252. // Don't automatically hide action lines when disabling - let caller decide
  253. }
  254. }
  255. public void ShowActiveActionLines()
  256. {
  257. HideActiveActionLines(); // Clear any existing lines first
  258. foreach (var character in playerCharacters)
  259. {
  260. if (character.HasActionSelected() && !character.IsActionComplete())
  261. {
  262. GameObject lineObject = new GameObject($"ActionLine_{character.name}");
  263. TargetingLine line = lineObject.AddComponent<TargetingLine>();
  264. activeActionLines.Add(line);
  265. Vector3 startPos = character.transform.position + Vector3.up * 0.5f;
  266. if (character.actionData.targetEnemy != null)
  267. {
  268. Vector3 endPos = character.actionData.targetEnemy.transform.position + Vector3.up * 0.5f;
  269. line.StartTargeting(startPos);
  270. line.UpdateTargeting(startPos, endPos, true); // true for enemy target (red line)
  271. }
  272. else if (character.actionData.targetPosition != Vector3.zero)
  273. {
  274. line.StartTargeting(startPos);
  275. line.UpdateTargeting(startPos, character.actionData.targetPosition, false); // false for movement (blue line)
  276. }
  277. }
  278. }
  279. }
  280. public void HideActiveActionLines()
  281. {
  282. foreach (var line in activeActionLines)
  283. {
  284. if (line != null)
  285. {
  286. line.StopTargeting();
  287. Destroy(line.gameObject);
  288. }
  289. }
  290. activeActionLines.Clear();
  291. }
  292. public void ClearActionLineForCharacter(Character character)
  293. {
  294. for (int i = activeActionLines.Count - 1; i >= 0; i--)
  295. {
  296. var line = activeActionLines[i];
  297. if (line != null && line.gameObject.name == $"ActionLine_{character.name}")
  298. {
  299. line.StopTargeting();
  300. Destroy(line.gameObject);
  301. activeActionLines.RemoveAt(i);
  302. break;
  303. }
  304. }
  305. }
  306. }