MainTeamSelectScript.cs 69 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040
  1. using UnityEngine;
  2. using UnityEngine.UIElements; // Make sure you have this using directive
  3. using UnityEngine.SceneManagement; // Added for scene management
  4. using System.Collections.Generic; // Needed for List<>
  5. using System.Linq; // Needed for LINQ operations
  6. using System.Collections; // Needed for coroutines
  7. public class MainTeamSelectScript : MonoBehaviour
  8. {
  9. private UIDocument uiDocument;
  10. private TeamCharacter currentCharacter;
  11. private List<Button> characterSlotButtons = new List<Button>();
  12. private List<Button> createNewCharacterButtons = new List<Button>();
  13. // Character slot management
  14. private TeamCharacter[] characterSlots = new TeamCharacter[4]; // 4 character slots
  15. private int currentSlotIndex = -1; // -1 means no slot selected
  16. // UI elements
  17. private TextField characterNameField;
  18. private Button randomizeNameButton;
  19. private DropdownField genderDropdown;
  20. private IntegerField strengthField, dexterityField, constitutionField, wisdomField;
  21. private IntegerField initField, damageField, spellCastingField, movementSpeedField, hpField, acField;
  22. // Attribute management UI
  23. private Button randomizeAttributesButton;
  24. private Button resetToPointBuyButton;
  25. private Label availablePointsLabel;
  26. private Label creationModeLabel;
  27. // Inventory/Shop UI elements
  28. private Button addWeaponButton;
  29. private Button addArmorButton;
  30. private Button addMiscButton;
  31. private IntegerField goldField;
  32. private IntegerField silverField;
  33. private IntegerField copperField;
  34. private VisualElement weaponsList;
  35. private VisualElement armorList;
  36. private VisualElement miscList;
  37. // Shop reference
  38. private SimpleShopManager shopManager;
  39. // Navigation buttons
  40. private Button backToTitleButton;
  41. private Button proceedToBattleButton;
  42. void Awake()
  43. {
  44. uiDocument = GetComponent<UIDocument>();
  45. if (uiDocument == null)
  46. {
  47. Debug.LogError("UIDocument component not found on this GameObject.", this);
  48. return; // Exit if no UIDocument is found
  49. }
  50. // Initialize character slots array
  51. characterSlots = new TeamCharacter[4];
  52. // Clear all existing character equipment to ensure shop-only acquisition
  53. ClearAllCharacterEquipment();
  54. // Start with no character selected (empty character sheet)
  55. currentCharacter = null;
  56. currentSlotIndex = -1;
  57. // Check if team has been finalized (proceeded to map)
  58. bool teamFinalized = IsTeamFinalized();
  59. // Load saved team if available
  60. LoadSavedTeamData();
  61. // Get UI element references
  62. GetUIElementReferences();
  63. // Set up event listeners
  64. SetupEventListeners();
  65. // Try to find missing UI elements one more time after everything is set up
  66. ValidateUIElements();
  67. // If team is finalized, disable editing and show message
  68. if (teamFinalized)
  69. {
  70. SetTeamFinalizedMode();
  71. }
  72. // Initialize UI with character data
  73. UpdateCharacterUI();
  74. UpdateSlotVisualStates();
  75. UpdateNavigationButtons();
  76. }
  77. private void ValidateUIElements()
  78. {
  79. // Final attempt to find critical UI elements that might have been missed
  80. if (proceedToBattleButton == null && uiDocument != null)
  81. {
  82. var root = uiDocument.rootVisualElement;
  83. Debug.LogWarning("Final attempt to find proceedToBattleButton...");
  84. // Try searching with different approaches
  85. proceedToBattleButton = root.Q<Button>("ProceedToBattleButton") ??
  86. root.Q<Button>("ProceedButton") ??
  87. root.Q<Button>("StartButton") ??
  88. root.Q<Button>(className: "proceed-button");
  89. // If still not found, search through all buttons for text matches
  90. if (proceedToBattleButton == null)
  91. {
  92. var allButtons = root.Query<Button>().ToList();
  93. foreach (var button in allButtons)
  94. {
  95. if (button.text.ToLower().Contains("proceed") ||
  96. button.text.ToLower().Contains("start") ||
  97. button.text.ToLower().Contains("battle"))
  98. {
  99. proceedToBattleButton = button;
  100. break;
  101. }
  102. }
  103. }
  104. if (proceedToBattleButton != null)
  105. {
  106. // Set up the event listener since we found it late
  107. proceedToBattleButton.clicked += OnProceedToBattleClicked;
  108. }
  109. else
  110. {
  111. Debug.LogError("CRITICAL: Could not find proceed button in UI! Please check the UI Document.");
  112. }
  113. }
  114. }
  115. private void GetUIElementReferences()
  116. {
  117. var root = uiDocument.rootVisualElement;
  118. // Character info fields
  119. characterNameField = root.Q<TextField>("CharacterNameField");
  120. randomizeNameButton = root.Q<Button>("RandomizeNameButton");
  121. genderDropdown = root.Q<DropdownField>("GenderDropdown");
  122. // Stat fields
  123. strengthField = root.Q<IntegerField>("StrengthValue");
  124. dexterityField = root.Q<IntegerField>("DexterityValue");
  125. constitutionField = root.Q<IntegerField>("ConstitutionValue");
  126. wisdomField = root.Q<IntegerField>("WisdomValue");
  127. // Derived stat fields
  128. initField = root.Q<IntegerField>("InitValue");
  129. damageField = root.Q<IntegerField>("DamageValue");
  130. spellCastingField = root.Q<IntegerField>("SpellCastingValue");
  131. movementSpeedField = root.Q<IntegerField>("MovementSpeedValue");
  132. hpField = root.Q<IntegerField>("HPValue");
  133. acField = root.Q<IntegerField>("ACValue");
  134. // Attribute management UI
  135. randomizeAttributesButton = root.Q<Button>("RandomizeAttributesButton");
  136. resetToPointBuyButton = root.Q<Button>("ResetToPointBuyButton");
  137. availablePointsLabel = root.Q<Label>("AvailablePointsLabel");
  138. creationModeLabel = root.Q<Label>("CreationModeLabel");
  139. // Find all buttons with the name "CreateNewCharacterButton"
  140. createNewCharacterButtons = uiDocument.rootVisualElement.Query<Button>("CreateNewCharacterButton").ToList();
  141. // Find all ViewCharacterButton buttons
  142. characterSlotButtons = uiDocument.rootVisualElement.Query<Button>("ViewCharacterButton").ToList();
  143. // Inventory/Shop UI elements
  144. addWeaponButton = root.Q<Button>("AddWeaponButton");
  145. addArmorButton = root.Q<Button>("AddArmourButton");
  146. addMiscButton = root.Q<Button>("AddMiscButton");
  147. goldField = root.Q<IntegerField>("GoldValue");
  148. silverField = root.Q<IntegerField>("SilverValue");
  149. copperField = root.Q<IntegerField>("CopperValue");
  150. weaponsList = root.Q<VisualElement>("WeaponsList");
  151. armorList = root.Q<VisualElement>("ArmourList");
  152. miscList = root.Q<VisualElement>("MiscList");
  153. // Navigation buttons
  154. backToTitleButton = root.Q<Button>("BackToTitleButton");
  155. proceedToBattleButton = root.Q<Button>("ProceedToBattleButton");
  156. // Debug and fallback for Back to Title button
  157. if (backToTitleButton == null)
  158. {
  159. Debug.LogWarning("BackToTitleButton not found! Creating fallback button...");
  160. // Create a simple fallback button
  161. backToTitleButton = new Button();
  162. backToTitleButton.text = "Back to Title";
  163. backToTitleButton.name = "BackToTitleButton_Fallback";
  164. backToTitleButton.style.position = Position.Absolute;
  165. backToTitleButton.style.top = 10;
  166. backToTitleButton.style.left = 10;
  167. backToTitleButton.style.width = 120;
  168. backToTitleButton.style.height = 30;
  169. root.Add(backToTitleButton);
  170. }
  171. // Find shop manager in scene
  172. shopManager = FindFirstObjectByType<SimpleShopManager>();
  173. if (shopManager == null)
  174. {
  175. Debug.LogWarning("No SimpleShopManager found in scene. Shop functionality will be limited.");
  176. Debug.LogWarning("Trying to refresh shop manager reference...");
  177. // Try again after a short delay to allow for potential late initialization
  178. StartCoroutine(RefreshShopManagerReference());
  179. }
  180. else
  181. {
  182. SetupShopManagerCallbacks();
  183. }
  184. // Check if any buttons were found
  185. if (createNewCharacterButtons.Count == 0)
  186. {
  187. Debug.LogWarning("No buttons with the name 'CreateNewCharacterButton' found in the UI Document.");
  188. }
  189. else
  190. {
  191. // Add a click listener to each button found
  192. foreach (Button button in createNewCharacterButtons)
  193. {
  194. // Example of passing data (requires adjusting the handler method):
  195. int characterIndex = createNewCharacterButtons.IndexOf(button); // Example data
  196. button.clicked += () => OnCreateNewCharacterButtonClicked(characterIndex);
  197. }
  198. }
  199. // Add click listeners to ViewCharacterButton buttons
  200. for (int i = 0; i < characterSlotButtons.Count; i++)
  201. {
  202. int index = i; // Capture the index for the closure
  203. characterSlotButtons[i].clicked += () => OnViewCharacterButtonClicked(index);
  204. }
  205. }
  206. private void SetupEventListeners()
  207. {
  208. // Name randomization
  209. if (randomizeNameButton != null)
  210. {
  211. randomizeNameButton.clicked += OnRandomizeNameClicked;
  212. }
  213. // Character name change
  214. if (characterNameField != null)
  215. {
  216. characterNameField.RegisterValueChangedCallback(OnCharacterNameChanged);
  217. }
  218. // Gender change
  219. if (genderDropdown != null)
  220. {
  221. genderDropdown.RegisterValueChangedCallback(OnGenderChanged);
  222. }
  223. // Stat changes
  224. if (strengthField != null)
  225. strengthField.RegisterValueChangedCallback(evt => OnStatChanged());
  226. if (dexterityField != null)
  227. dexterityField.RegisterValueChangedCallback(evt => OnStatChanged());
  228. if (constitutionField != null)
  229. constitutionField.RegisterValueChangedCallback(evt => OnStatChanged());
  230. if (wisdomField != null)
  231. wisdomField.RegisterValueChangedCallback(evt => OnStatChanged());
  232. // Attribute management
  233. if (randomizeAttributesButton != null)
  234. randomizeAttributesButton.clicked += OnRandomizeAttributesClicked;
  235. if (resetToPointBuyButton != null)
  236. resetToPointBuyButton.clicked += OnResetToPointBuyClicked;
  237. // Inventory/Shop management
  238. if (addWeaponButton != null)
  239. addWeaponButton.clicked += OnAddWeaponClicked;
  240. if (addArmorButton != null)
  241. addArmorButton.clicked += OnAddArmorClicked;
  242. if (addMiscButton != null)
  243. addMiscButton.clicked += OnAddMiscClicked;
  244. // Bank field changes
  245. if (goldField != null)
  246. goldField.RegisterValueChangedCallback(evt => OnBankChanged());
  247. if (silverField != null)
  248. silverField.RegisterValueChangedCallback(evt => OnBankChanged());
  249. if (copperField != null)
  250. copperField.RegisterValueChangedCallback(evt => OnBankChanged());
  251. // Navigation buttons
  252. if (backToTitleButton != null)
  253. backToTitleButton.clicked += OnBackToTitleClicked;
  254. if (proceedToBattleButton != null)
  255. proceedToBattleButton.clicked += OnProceedToBattleClicked;
  256. else
  257. Debug.LogWarning("proceedToBattleButton is null during SetupEventListeners - will try to set up event listener later");
  258. }
  259. private void OnRandomizeNameClicked()
  260. {
  261. if (currentCharacter == null) return;
  262. currentCharacter.GenerateRandomName();
  263. characterNameField.value = currentCharacter.name;
  264. // Update the slot button and save to slot
  265. UpdateCurrentSlotButton();
  266. SaveCurrentCharacterToSlot();
  267. }
  268. private void OnCharacterNameChanged(ChangeEvent<string> evt)
  269. {
  270. if (currentCharacter == null) return;
  271. currentCharacter.name = evt.newValue;
  272. // Update the slot button and save to slot
  273. UpdateCurrentSlotButton();
  274. SaveCurrentCharacterToSlot();
  275. // Update the character card if we have a current slot
  276. if (currentSlotIndex >= 0)
  277. {
  278. UpdateCharacterCard(currentSlotIndex, currentCharacter);
  279. }
  280. }
  281. private void OnGenderChanged(ChangeEvent<string> evt)
  282. {
  283. if (currentCharacter == null) return;
  284. currentCharacter.SetGender(evt.newValue == "Male");
  285. // Optionally regenerate name when gender changes
  286. // You can remove this if you don't want automatic name regeneration
  287. currentCharacter.GenerateRandomName();
  288. characterNameField.value = currentCharacter.name;
  289. // Update the slot button and save to slot
  290. UpdateCurrentSlotButton();
  291. SaveCurrentCharacterToSlot();
  292. // Update the character card if we have a current slot
  293. if (currentSlotIndex >= 0)
  294. {
  295. UpdateCharacterCard(currentSlotIndex, currentCharacter);
  296. }
  297. }
  298. private void OnStatChanged()
  299. {
  300. if (currentCharacter == null) return;
  301. // Validate point-buy constraints
  302. int newStr = strengthField?.value ?? currentCharacter.strength;
  303. int newDex = dexterityField?.value ?? currentCharacter.dexterity;
  304. int newCon = constitutionField?.value ?? currentCharacter.constitution;
  305. int newWis = wisdomField?.value ?? currentCharacter.wisdom;
  306. // Clamp values to valid range (4-18)
  307. newStr = Mathf.Clamp(newStr, 4, 18);
  308. newDex = Mathf.Clamp(newDex, 4, 18);
  309. newCon = Mathf.Clamp(newCon, 4, 18);
  310. newWis = Mathf.Clamp(newWis, 4, 18);
  311. // Check if the new combination is affordable
  312. int totalCost = TeamCharacter.GetStatCost(newStr) + TeamCharacter.GetStatCost(newDex) +
  313. TeamCharacter.GetStatCost(newCon) + TeamCharacter.GetStatCost(newWis);
  314. if (totalCost <= 18) // Changed from 27 to 18 for 4-stat system
  315. {
  316. // Update character stats from UI
  317. currentCharacter.strength = newStr;
  318. currentCharacter.dexterity = newDex;
  319. currentCharacter.constitution = newCon;
  320. currentCharacter.wisdom = newWis;
  321. currentCharacter.UpdateAvailablePoints();
  322. }
  323. else
  324. {
  325. // Reset to previous valid values
  326. if (strengthField != null) strengthField.value = currentCharacter.strength;
  327. if (dexterityField != null) dexterityField.value = currentCharacter.dexterity;
  328. if (constitutionField != null) constitutionField.value = currentCharacter.constitution;
  329. if (wisdomField != null) wisdomField.value = currentCharacter.wisdom;
  330. }
  331. // Update derived stats and point display
  332. UpdateDerivedStats();
  333. UpdateAttributeUI();
  334. SaveCurrentCharacterToSlot();
  335. UpdateNavigationButtons();
  336. // Update the character card if we have a current slot
  337. if (currentSlotIndex >= 0)
  338. {
  339. UpdateCharacterCard(currentSlotIndex, currentCharacter);
  340. }
  341. }
  342. private void OnRandomizeAttributesClicked()
  343. {
  344. if (currentCharacter == null) return;
  345. currentCharacter.RandomizeAttributes();
  346. UpdateCharacterUI();
  347. UpdateAttributeUI();
  348. SaveCurrentCharacterToSlot();
  349. UpdateNavigationButtons();
  350. // Update the character card if we have a current slot
  351. if (currentSlotIndex >= 0)
  352. {
  353. UpdateCharacterCard(currentSlotIndex, currentCharacter);
  354. }
  355. }
  356. private void OnResetToPointBuyClicked()
  357. {
  358. if (currentCharacter == null) return;
  359. currentCharacter.ResetToPointBuy();
  360. UpdateCharacterUI();
  361. UpdateAttributeUI();
  362. SaveCurrentCharacterToSlot();
  363. UpdateNavigationButtons();
  364. // Update the character card if we have a current slot
  365. if (currentSlotIndex >= 0)
  366. {
  367. UpdateCharacterCard(currentSlotIndex, currentCharacter);
  368. }
  369. }
  370. private void OnAddWeaponClicked()
  371. {
  372. if (currentCharacter == null)
  373. {
  374. Debug.LogWarning("OnAddWeaponClicked: No current character selected");
  375. return;
  376. }
  377. // Open weapon shop for this character
  378. OpenWeaponShop();
  379. }
  380. private void OpenWeaponShop()
  381. {
  382. if (shopManager != null)
  383. {
  384. shopManager.OpenShop(currentCharacter);
  385. }
  386. else
  387. {
  388. Debug.LogWarning("No shop manager found - cannot open shop");
  389. }
  390. }
  391. private void AddWeaponToCharacter(string weaponType)
  392. {
  393. // Add weapon to character's inventory (would integrate with real shop/inventory system)
  394. if (currentCharacter.weapons == null)
  395. {
  396. currentCharacter.weapons = new System.Collections.Generic.List<string>();
  397. }
  398. currentCharacter.weapons.Add(weaponType);
  399. SaveCurrentCharacterToSlot();
  400. }
  401. private void OnAddArmorClicked()
  402. {
  403. if (currentCharacter == null) return;
  404. if (shopManager != null)
  405. {
  406. shopManager.OpenShop(currentCharacter);
  407. }
  408. else
  409. {
  410. Debug.LogWarning("No shop manager found - cannot open shop");
  411. }
  412. }
  413. private void OnAddMiscClicked()
  414. {
  415. if (currentCharacter == null) return;
  416. if (shopManager != null)
  417. {
  418. shopManager.OpenShop(currentCharacter);
  419. }
  420. else
  421. {
  422. Debug.LogWarning("No shop manager found - cannot open shop");
  423. }
  424. }
  425. private void AddArmorToCharacter(string armorType)
  426. {
  427. if (currentCharacter.armor == null)
  428. {
  429. currentCharacter.armor = new System.Collections.Generic.List<string>();
  430. }
  431. currentCharacter.armor.Add(armorType);
  432. SaveCurrentCharacterToSlot();
  433. UpdateInventoryUI();
  434. }
  435. private void AddMiscItemToCharacter(string itemType)
  436. {
  437. if (currentCharacter.miscItems == null)
  438. {
  439. currentCharacter.miscItems = new System.Collections.Generic.List<string>();
  440. }
  441. currentCharacter.miscItems.Add(itemType);
  442. SaveCurrentCharacterToSlot();
  443. UpdateInventoryUI();
  444. }
  445. private void OnBankChanged()
  446. {
  447. if (currentCharacter == null) return;
  448. currentCharacter.gold = goldField?.value ?? currentCharacter.gold;
  449. currentCharacter.silver = silverField?.value ?? currentCharacter.silver;
  450. currentCharacter.copper = copperField?.value ?? currentCharacter.copper;
  451. SaveCurrentCharacterToSlot();
  452. }
  453. private void UpdateInventoryUI()
  454. {
  455. if (currentCharacter == null) return;
  456. // Update bank fields
  457. if (goldField != null) goldField.value = currentCharacter.gold;
  458. if (silverField != null) silverField.value = currentCharacter.silver;
  459. if (copperField != null) copperField.value = currentCharacter.copper;
  460. // Update weapon list
  461. UpdateItemList(weaponsList, currentCharacter.weapons, "WeaponItemRow", OnRemoveWeapon);
  462. // Update armor list
  463. UpdateItemList(armorList, currentCharacter.armor, "ArmorItemRow", OnRemoveArmor);
  464. // Update misc list
  465. UpdateItemList(miscList, currentCharacter.miscItems, "MiscItemRow", OnRemoveMisc);
  466. }
  467. private void UpdateItemList(VisualElement container, System.Collections.Generic.List<string> items, string rowClassName, System.Action<string> removeAction)
  468. {
  469. if (container == null || items == null) return;
  470. // Clear existing items (except example rows)
  471. var itemsToRemove = container.Query<VisualElement>(className: "inventory-item-row").ToList()
  472. .Where(item => !item.name.Contains("Example")).ToList();
  473. foreach (var item in itemsToRemove)
  474. {
  475. container.Remove(item);
  476. }
  477. // Add current items
  478. foreach (var itemName in items)
  479. {
  480. var itemRow = new VisualElement();
  481. itemRow.AddToClassList("inventory-item-row");
  482. itemRow.AddToClassList(rowClassName);
  483. var nameLabel = new Label(itemName);
  484. nameLabel.AddToClassList("item-name-label");
  485. itemRow.Add(nameLabel);
  486. var removeButton = new Button(() => removeAction(itemName));
  487. removeButton.text = "Remove (Refund)";
  488. removeButton.AddToClassList("remove-item-button");
  489. // Add tooltip or title to show refund information
  490. string itemType = GetItemTypeFromClassName(rowClassName);
  491. string refundInfo = GetRefundInfo(itemName, itemType);
  492. if (!string.IsNullOrEmpty(refundInfo))
  493. {
  494. removeButton.tooltip = $"Remove and refund: {refundInfo}";
  495. }
  496. itemRow.Add(removeButton);
  497. container.Add(itemRow);
  498. }
  499. }
  500. private string GetItemTypeFromClassName(string className)
  501. {
  502. if (className.Contains("Weapon")) return "weapon";
  503. if (className.Contains("Armor")) return "armor";
  504. if (className.Contains("Misc")) return "misc";
  505. return "";
  506. }
  507. private string GetRefundInfo(string itemName, string itemType)
  508. {
  509. if (shopManager == null) return "";
  510. System.Collections.Generic.List<SimpleShopItem> itemList = null;
  511. switch (itemType.ToLower())
  512. {
  513. case "weapon":
  514. itemList = shopManager.weapons;
  515. break;
  516. case "armor":
  517. itemList = shopManager.armor;
  518. break;
  519. case "misc":
  520. itemList = shopManager.miscItems;
  521. break;
  522. }
  523. if (itemList != null)
  524. {
  525. var shopItem = itemList.Find(item => item.name == itemName);
  526. if (shopItem != null)
  527. {
  528. return shopItem.GetCostString();
  529. }
  530. }
  531. return "";
  532. }
  533. private void RefundItemPrice(string itemName, string itemType)
  534. {
  535. if (shopManager == null || currentCharacter == null)
  536. {
  537. Debug.LogWarning($"Cannot refund {itemName}: shop manager or current character is null");
  538. return;
  539. }
  540. // Find the item price from the shop manager
  541. int goldRefund = 0;
  542. int silverRefund = 0;
  543. int copperRefund = 0;
  544. // Check the appropriate list based on item type
  545. System.Collections.Generic.List<SimpleShopItem> itemList = null;
  546. switch (itemType.ToLower())
  547. {
  548. case "weapon":
  549. itemList = shopManager.weapons;
  550. break;
  551. case "armor":
  552. itemList = shopManager.armor;
  553. break;
  554. case "misc":
  555. itemList = shopManager.miscItems;
  556. break;
  557. }
  558. if (itemList != null)
  559. {
  560. // Find the item in the shop list
  561. var shopItem = itemList.Find(item => item.name == itemName);
  562. if (shopItem != null)
  563. {
  564. goldRefund = shopItem.goldCost;
  565. silverRefund = shopItem.silverCost;
  566. copperRefund = shopItem.copperCost;
  567. // Add the refund to the character's money
  568. currentCharacter.gold += goldRefund;
  569. currentCharacter.silver += silverRefund;
  570. currentCharacter.copper += copperRefund;
  571. }
  572. else
  573. {
  574. Debug.LogWarning($"Could not find {itemName} in shop {itemType} list for refund");
  575. }
  576. }
  577. else
  578. {
  579. Debug.LogWarning($"Could not access shop {itemType} list for refund");
  580. }
  581. }
  582. private void OnRemoveWeapon(string weaponName)
  583. {
  584. if (currentCharacter?.weapons != null)
  585. {
  586. currentCharacter.weapons.Remove(weaponName);
  587. // Refund the weapon price
  588. RefundItemPrice(weaponName, "weapon");
  589. SaveCurrentCharacterToSlot();
  590. UpdateInventoryUI();
  591. }
  592. }
  593. private void OnRemoveArmor(string armorName)
  594. {
  595. if (currentCharacter?.armor != null)
  596. {
  597. currentCharacter.armor.Remove(armorName);
  598. // Refund the armor price
  599. RefundItemPrice(armorName, "armor");
  600. SaveCurrentCharacterToSlot();
  601. UpdateInventoryUI();
  602. }
  603. }
  604. private void OnRemoveMisc(string itemName)
  605. {
  606. if (currentCharacter?.miscItems != null)
  607. {
  608. currentCharacter.miscItems.Remove(itemName);
  609. // Refund the misc item price
  610. RefundItemPrice(itemName, "misc");
  611. SaveCurrentCharacterToSlot();
  612. UpdateInventoryUI();
  613. }
  614. }
  615. private void UpdateCharacterUI()
  616. {
  617. if (currentCharacter == null)
  618. {
  619. // Clear the UI when no character is selected
  620. if (characterNameField != null) characterNameField.value = "";
  621. if (genderDropdown != null) genderDropdown.value = "Male";
  622. if (strengthField != null) strengthField.value = 10;
  623. if (dexterityField != null) dexterityField.value = 10;
  624. if (constitutionField != null) constitutionField.value = 10;
  625. if (wisdomField != null) wisdomField.value = 10;
  626. // Clear derived stats
  627. if (initField != null) initField.value = 0;
  628. if (damageField != null) damageField.value = 0;
  629. if (spellCastingField != null) spellCastingField.value = 0;
  630. if (movementSpeedField != null) movementSpeedField.value = 30;
  631. if (hpField != null) hpField.value = 10;
  632. if (acField != null) acField.value = 0;
  633. // Clear attribute UI
  634. if (creationModeLabel != null) creationModeLabel.text = "Mode: None";
  635. if (availablePointsLabel != null) availablePointsLabel.text = "Available Points: 0";
  636. return;
  637. }
  638. // Update UI with current character data
  639. if (characterNameField != null)
  640. characterNameField.value = currentCharacter.name;
  641. if (genderDropdown != null)
  642. genderDropdown.value = currentCharacter.isMale ? "Male" : "Female";
  643. if (strengthField != null) strengthField.value = currentCharacter.strength;
  644. if (dexterityField != null) dexterityField.value = currentCharacter.dexterity;
  645. if (constitutionField != null) constitutionField.value = currentCharacter.constitution;
  646. if (wisdomField != null) wisdomField.value = currentCharacter.wisdom;
  647. // Recalculate equipment bonuses from inventory
  648. currentCharacter.RecalculateEquipmentBonuses();
  649. UpdateDerivedStats();
  650. UpdateAttributeUI();
  651. UpdateInventoryUI();
  652. }
  653. private void UpdateAttributeUI()
  654. {
  655. if (currentCharacter == null) return;
  656. // Update creation mode display
  657. if (creationModeLabel != null)
  658. {
  659. creationModeLabel.text = "Mode: Point Buy";
  660. }
  661. // Update available points display
  662. if (availablePointsLabel != null)
  663. {
  664. availablePointsLabel.text = $"Available Points: {currentCharacter.availablePoints}";
  665. }
  666. // All stat fields are always editable in the new system
  667. if (strengthField != null) strengthField.SetEnabled(true);
  668. if (dexterityField != null) dexterityField.SetEnabled(true);
  669. if (constitutionField != null) constitutionField.SetEnabled(true);
  670. if (wisdomField != null) wisdomField.SetEnabled(true);
  671. }
  672. private void UpdateDerivedStats()
  673. {
  674. if (currentCharacter == null) return;
  675. // Update the read-only derived stats (uses final stats including equipment modifiers)
  676. if (initField != null) initField.value = currentCharacter.Initiative;
  677. if (damageField != null) damageField.value = currentCharacter.DamageBonus;
  678. if (spellCastingField != null) spellCastingField.value = currentCharacter.SpellAC;
  679. if (movementSpeedField != null) movementSpeedField.value = currentCharacter.MovementSpeed;
  680. if (hpField != null) hpField.value = currentCharacter.HitPoints;
  681. if (acField != null) acField.value = currentCharacter.ArmorClass;
  682. }
  683. private void UpdateCurrentSlotButton()
  684. {
  685. // Update the character card information if we have a current slot selected
  686. if (currentSlotIndex >= 0 && currentSlotIndex < characterSlotButtons.Count && currentCharacter != null)
  687. {
  688. UpdateCharacterCard(currentSlotIndex, currentCharacter);
  689. }
  690. }
  691. private void UpdateCharacterCard(int slotIndex, TeamCharacter character)
  692. {
  693. if (slotIndex < 0 || slotIndex >= 4 || character == null) return;
  694. var root = uiDocument.rootVisualElement;
  695. // Find the character slot instance based on index
  696. string[] slotNames = { "Character1", "Character2", "Character3", "Character4" };
  697. var characterSlot = root.Q<VisualElement>(slotNames[slotIndex]);
  698. if (characterSlot == null) return;
  699. // Find the character card button within this slot
  700. var characterCard = characterSlot.Q<Button>("ViewCharacterButton");
  701. if (characterCard == null) return;
  702. // Update character name
  703. var nameLabel = characterCard.Q<Label>("CharacterNameLabel");
  704. if (nameLabel != null)
  705. {
  706. nameLabel.text = character.name;
  707. }
  708. // Update stats
  709. var strengthLabel = characterCard.Q<Label>("StrengthLabel");
  710. if (strengthLabel != null) strengthLabel.text = character.strength.ToString();
  711. var dexterityLabel = characterCard.Q<Label>("DexterityLabel");
  712. if (dexterityLabel != null) dexterityLabel.text = character.dexterity.ToString();
  713. var constitutionLabel = characterCard.Q<Label>("ConstitutionLabel");
  714. if (constitutionLabel != null) constitutionLabel.text = character.constitution.ToString();
  715. var wisdomLabel = characterCard.Q<Label>("WisdomLabel");
  716. if (wisdomLabel != null) wisdomLabel.text = character.wisdom.ToString();
  717. // Update HP and AC
  718. var hpLabel = characterCard.Q<Label>("HPLabel");
  719. if (hpLabel != null) hpLabel.text = $"HP: {character.HitPoints}";
  720. var acLabel = characterCard.Q<Label>("ACLabel");
  721. if (acLabel != null) acLabel.text = $"AC: {character.ArmorClass}";
  722. // Show the character card and hide the create button
  723. var createButton = characterSlot.Q<Button>("CreateNewCharacterButton");
  724. if (createButton != null)
  725. {
  726. createButton.style.display = DisplayStyle.None;
  727. }
  728. characterCard.RemoveFromClassList("disabled-card");
  729. characterCard.style.display = DisplayStyle.Flex;
  730. characterCard.SetEnabled(true);
  731. }
  732. private void SaveCurrentCharacterToSlot()
  733. {
  734. // Save the current character data back to its slot
  735. if (currentSlotIndex >= 0 && currentSlotIndex < characterSlots.Length && currentCharacter != null)
  736. {
  737. characterSlots[currentSlotIndex] = currentCharacter.CreateCopy();
  738. }
  739. }
  740. private void UpdateSlotVisualStates()
  741. {
  742. var root = uiDocument.rootVisualElement;
  743. string[] slotNames = { "Character1", "Character2", "Character3", "Character4" };
  744. // Update visual states of all character slots
  745. for (int i = 0; i < slotNames.Length; i++)
  746. {
  747. var characterSlot = root.Q<VisualElement>(slotNames[i]);
  748. if (characterSlot == null) continue;
  749. // Remove all visual state classes first
  750. characterSlot.RemoveFromClassList("selected-slot");
  751. // Add selected state if this is the current slot
  752. if (i == currentSlotIndex)
  753. {
  754. characterSlot.AddToClassList("selected-slot");
  755. }
  756. // Update character card visibility and data
  757. if (characterSlots[i] != null)
  758. {
  759. // Character exists in this slot
  760. UpdateCharacterCard(i, characterSlots[i]);
  761. }
  762. else
  763. {
  764. // No character in this slot - show create button
  765. var createButton = characterSlot.Q<Button>("CreateNewCharacterButton");
  766. var characterCard = characterSlot.Q<Button>("ViewCharacterButton");
  767. if (createButton != null)
  768. {
  769. createButton.style.display = DisplayStyle.Flex;
  770. }
  771. if (characterCard != null)
  772. {
  773. characterCard.style.display = DisplayStyle.None;
  774. characterCard.AddToClassList("disabled-card");
  775. characterCard.SetEnabled(false);
  776. }
  777. }
  778. }
  779. }
  780. // Example handler if you need to pass data (like an index)
  781. private void OnCreateNewCharacterButtonClicked(int index)
  782. {
  783. // Create a new character with random name
  784. currentCharacter = new TeamCharacter();
  785. // Generate name after construction to avoid serialization issues
  786. currentCharacter.GenerateRandomName();
  787. // Save character to the slot (create a proper copy)
  788. characterSlots[index] = currentCharacter.CreateCopy();
  789. currentSlotIndex = index;
  790. UpdateCharacterUI();
  791. UpdateSlotVisualStates();
  792. // Update navigation buttons immediately after character creation
  793. UpdateNavigationButtons();
  794. // Update the character card for this slot
  795. UpdateCharacterCard(index, currentCharacter);
  796. // Call UpdateNavigationButtons again after UI updates
  797. UpdateNavigationButtons();
  798. }
  799. private void OnViewCharacterButtonClicked(int index)
  800. {
  801. // Check if there's a character in this slot
  802. if (characterSlots[index] != null)
  803. {
  804. // Create a working copy of the character from the slot
  805. currentCharacter = characterSlots[index].CreateCopy();
  806. currentSlotIndex = index;
  807. UpdateCharacterUI();
  808. UpdateSlotVisualStates();
  809. UpdateNavigationButtons();
  810. }
  811. else
  812. {
  813. // Slot is empty, save current character to this slot if we have one
  814. if (currentCharacter != null)
  815. {
  816. // Create a proper copy of the current character data
  817. characterSlots[index] = currentCharacter.CreateCopy();
  818. currentSlotIndex = index;
  819. // Update the character card for this slot
  820. UpdateCharacterCard(index, currentCharacter);
  821. UpdateSlotVisualStates();
  822. UpdateNavigationButtons();
  823. }
  824. }
  825. }
  826. // Start is called once before the first execution of Update after the MonoBehaviour is created
  827. void Start()
  828. {
  829. // You can keep Start if needed for other initialization
  830. }
  831. // Update is called once per frame
  832. void Update()
  833. {
  834. // Debug keys for testing
  835. if (Input.GetKeyDown(KeyCode.F5))
  836. {
  837. DebugCurrentCharacterSlots();
  838. }
  839. if (Input.GetKeyDown(KeyCode.F6))
  840. {
  841. SaveTeamToGameState();
  842. }
  843. if (Input.GetKeyDown(KeyCode.F7))
  844. {
  845. TestPlayerPrefsData();
  846. }
  847. }
  848. private void DebugCurrentCharacterSlots()
  849. {
  850. for (int i = 0; i < characterSlots.Length; i++)
  851. {
  852. if (characterSlots[i] != null)
  853. {
  854. var character = characterSlots[i];
  855. }
  856. else
  857. {
  858. }
  859. }
  860. }
  861. private void TestPlayerPrefsData()
  862. {
  863. for (int i = 0; i < 4; i++)
  864. {
  865. string existsKey = $"Character{i}_Exists";
  866. if (PlayerPrefs.HasKey(existsKey))
  867. {
  868. int exists = PlayerPrefs.GetInt(existsKey);
  869. if (exists == 1)
  870. {
  871. string prefix = $"Character{i}_";
  872. string name = PlayerPrefs.GetString(prefix + "Name", "UNKNOWN");
  873. int str = PlayerPrefs.GetInt(prefix + "Strength", 0);
  874. int dex = PlayerPrefs.GetInt(prefix + "Dexterity", 0);
  875. int con = PlayerPrefs.GetInt(prefix + "Constitution", 0);
  876. int wis = PlayerPrefs.GetInt(prefix + "Wisdom", 0);
  877. }
  878. }
  879. else
  880. {
  881. }
  882. }
  883. }
  884. void OnDestroy()
  885. {
  886. // Clean up shop manager callbacks to prevent memory leaks
  887. if (shopManager != null)
  888. {
  889. shopManager.OnCharacterDataChanged -= OnShopCharacterDataChanged;
  890. }
  891. }
  892. #region Navigation Methods
  893. private void OnBackToTitleClicked()
  894. {
  895. // Check if team is finalized and this is acting as "New Game" button
  896. if (IsTeamFinalized())
  897. {
  898. // Show confirmation dialog for starting new game
  899. #if UNITY_EDITOR
  900. bool confirmed = UnityEditor.EditorUtility.DisplayDialog(
  901. "Start New Game",
  902. "This will start a completely new game and overwrite your current progress.\n\nAre you sure you want to continue?",
  903. "Start New Game",
  904. "Cancel"
  905. );
  906. if (confirmed)
  907. {
  908. StartNewGame();
  909. }
  910. #else
  911. // In builds, we'll assume user confirms for now
  912. // In a real game, implement a proper UI dialog system
  913. Debug.LogWarning("Starting new game - implement proper dialog for builds");
  914. StartNewGame();
  915. #endif
  916. }
  917. else
  918. {
  919. // Normal back to title behavior
  920. SceneManager.LoadScene("TitleScreenScene");
  921. }
  922. }
  923. private void StartNewGame()
  924. {
  925. // Initialize GameStateManager for new game
  926. if (GameStateManager.Instance != null)
  927. {
  928. GameStateManager.Instance.StartNewGame();
  929. }
  930. // Clear all save data
  931. ClearAllSaveData();
  932. // Reload the scene to start fresh
  933. SceneManager.LoadScene("MainTeamSelectScene");
  934. }
  935. private void ClearAllSaveData()
  936. {
  937. // Clear GameStateManager data
  938. if (GameStateManager.Instance != null)
  939. {
  940. GameStateManager.Instance.teamSetupComplete = false;
  941. GameStateManager.Instance.hasGeneratedMap = false;
  942. }
  943. // Clear PlayerPrefs data
  944. for (int i = 0; i < 4; i++)
  945. {
  946. string prefix = $"Character{i}_";
  947. PlayerPrefs.DeleteKey($"Character{i}_Exists");
  948. PlayerPrefs.DeleteKey(prefix + "Name");
  949. PlayerPrefs.DeleteKey(prefix + "IsMale");
  950. PlayerPrefs.DeleteKey(prefix + "Strength");
  951. PlayerPrefs.DeleteKey(prefix + "Dexterity");
  952. PlayerPrefs.DeleteKey(prefix + "Constitution");
  953. PlayerPrefs.DeleteKey(prefix + "Wisdom");
  954. PlayerPrefs.DeleteKey(prefix + "Gold");
  955. PlayerPrefs.DeleteKey(prefix + "Silver");
  956. PlayerPrefs.DeleteKey(prefix + "Copper");
  957. }
  958. // Clear map data
  959. PlayerPrefs.DeleteKey("HasGeneratedMap");
  960. PlayerPrefs.DeleteKey("MapSeed");
  961. PlayerPrefs.DeleteKey("TeamSize");
  962. PlayerPrefs.DeleteKey("TeamSetupComplete");
  963. PlayerPrefs.DeleteKey("GameSaved");
  964. PlayerPrefs.Save();
  965. }
  966. private void OnProceedToBattleClicked()
  967. {
  968. // Check if team is already finalized
  969. if (IsTeamFinalized())
  970. {
  971. // Team is finalized, return to MapScene2
  972. SceneManager.LoadScene("MapScene2");
  973. return;
  974. }
  975. // Check if we have at least one character
  976. if (!HasAtLeastOneCharacter())
  977. {
  978. Debug.LogWarning("Need at least one character to proceed to battle!");
  979. // TODO: Show message to user
  980. return;
  981. }
  982. // Save all configured characters before proceeding
  983. SaveTeamToGameState();
  984. // Mark that the team has proceeded to the map (finalized)
  985. // Save to both GameStateManager and PlayerPrefs for redundancy
  986. if (GameStateManager.Instance != null)
  987. {
  988. GameStateManager.Instance.teamSetupComplete = true;
  989. GameStateManager.Instance.SaveGame();
  990. }
  991. // Also save to PlayerPrefs as backup
  992. PlayerPrefs.SetInt("TeamSetupComplete", 1);
  993. PlayerPrefs.Save();
  994. SceneManager.LoadScene("MapScene2");
  995. }
  996. private void SaveTeamToGameState()
  997. {
  998. // Save team data to GameStateManager for persistence
  999. List<TeamCharacter> configuredCharacters = new List<TeamCharacter>();
  1000. for (int i = 0; i < characterSlots.Length; i++)
  1001. {
  1002. if (characterSlots[i] != null)
  1003. {
  1004. configuredCharacters.Add(characterSlots[i]);
  1005. // Save individual character data
  1006. SaveCharacterToPlayerPrefs(characterSlots[i], i);
  1007. // Verify the save immediately
  1008. PlayerPrefs.SetInt($"Character{i}_Exists", 1);
  1009. string testName = PlayerPrefs.GetString($"Character{i}_Name", "NOT_FOUND");
  1010. }
  1011. else
  1012. {
  1013. // Clear any existing character data for empty slots
  1014. PlayerPrefs.DeleteKey($"Character{i}_Exists");
  1015. }
  1016. }
  1017. // Save team composition info
  1018. PlayerPrefs.SetInt("TeamSize", configuredCharacters.Count);
  1019. // Update GameStateManager if available
  1020. if (GameStateManager.Instance != null)
  1021. {
  1022. // Copy our team to the GameStateManager
  1023. for (int i = 0; i < characterSlots.Length; i++)
  1024. {
  1025. if (characterSlots[i] != null)
  1026. {
  1027. GameStateManager.Instance.savedTeam[i] = characterSlots[i].CreateCopy();
  1028. }
  1029. else
  1030. {
  1031. GameStateManager.Instance.savedTeam[i] = null;
  1032. }
  1033. }
  1034. GameStateManager.Instance.teamSetupComplete = true;
  1035. GameStateManager.Instance.SaveGame();
  1036. }
  1037. else
  1038. {
  1039. Debug.LogWarning("GameStateManager.Instance is null!");
  1040. }
  1041. // Log configured team for MapScene
  1042. foreach (var character in configuredCharacters)
  1043. {
  1044. }
  1045. PlayerPrefs.Save(); // Ensure data is written to disk
  1046. }
  1047. public List<TeamCharacter> GetConfiguredCharacters()
  1048. {
  1049. // Public method to get all configured characters (useful for other scripts)
  1050. List<TeamCharacter> configuredCharacters = new List<TeamCharacter>();
  1051. for (int i = 0; i < characterSlots.Length; i++)
  1052. {
  1053. if (characterSlots[i] != null)
  1054. {
  1055. configuredCharacters.Add(characterSlots[i]);
  1056. }
  1057. }
  1058. return configuredCharacters;
  1059. }
  1060. private void UpdateNavigationButtons()
  1061. {
  1062. // Enable/disable proceed button based on team status
  1063. if (proceedToBattleButton != null)
  1064. {
  1065. bool canProceed = HasAtLeastOneCharacter();
  1066. proceedToBattleButton.SetEnabled(canProceed);
  1067. // Also remove/add visual disabled state
  1068. if (!canProceed)
  1069. {
  1070. proceedToBattleButton.AddToClassList("disabled-button");
  1071. proceedToBattleButton.tooltip = "Create at least one character to proceed";
  1072. }
  1073. else
  1074. {
  1075. proceedToBattleButton.RemoveFromClassList("disabled-button");
  1076. proceedToBattleButton.tooltip = "Start adventure with your team";
  1077. // Force remove any disabled classes that might be interfering
  1078. proceedToBattleButton.RemoveFromClassList("unity-disabled");
  1079. }
  1080. }
  1081. else
  1082. {
  1083. Debug.LogWarning("UpdateNavigationButtons: proceedToBattleButton is null! The button name in the UI might be different than expected.");
  1084. Debug.LogWarning("Please check that a button with name 'ProceedToBattleButton' exists in your UI Document.");
  1085. // Try to find the button again with common alternative names
  1086. var root = uiDocument?.rootVisualElement;
  1087. if (root != null)
  1088. {
  1089. proceedToBattleButton = root.Q<Button>("ProceedButton") ??
  1090. root.Q<Button>("StartButton") ??
  1091. root.Q<Button>("BattleButton") ??
  1092. root.Q<Button>("ProceedToBattleButton");
  1093. if (proceedToBattleButton != null)
  1094. {
  1095. // Recursively call this method now that we found the button
  1096. UpdateNavigationButtons();
  1097. }
  1098. }
  1099. }
  1100. }
  1101. private bool HasAtLeastOneCharacter()
  1102. {
  1103. int characterCount = 0;
  1104. for (int i = 0; i < characterSlots.Length; i++)
  1105. {
  1106. if (characterSlots[i] != null)
  1107. {
  1108. characterCount++;
  1109. }
  1110. else
  1111. {
  1112. }
  1113. }
  1114. bool hasCharacters = characterCount > 0;
  1115. return hasCharacters;
  1116. }
  1117. #endregion
  1118. #region Save/Load Team Data
  1119. private void LoadSavedTeamData()
  1120. {
  1121. // Try to load from GameStateManager first (if available and has data)
  1122. if (GameStateManager.Instance != null && GameStateManager.Instance.savedTeam != null)
  1123. {
  1124. for (int i = 0; i < characterSlots.Length && i < GameStateManager.Instance.savedTeam.Length; i++)
  1125. {
  1126. if (GameStateManager.Instance.savedTeam[i] != null)
  1127. {
  1128. characterSlots[i] = GameStateManager.Instance.savedTeam[i].CreateCopy();
  1129. // Update the slot button
  1130. if (i < characterSlotButtons.Count)
  1131. {
  1132. characterSlotButtons[i].text = characterSlots[i].name;
  1133. characterSlotButtons[i].SetEnabled(true);
  1134. characterSlotButtons[i].RemoveFromClassList("unity-disabled");
  1135. characterSlotButtons[i].RemoveFromClassList("DisabledCharacterCard");
  1136. // Hide the create button
  1137. if (i < createNewCharacterButtons.Count)
  1138. {
  1139. createNewCharacterButtons[i].style.display = DisplayStyle.None;
  1140. }
  1141. }
  1142. }
  1143. }
  1144. }
  1145. // Always also try to load from PlayerPrefs (either as backup or primary)
  1146. for (int i = 0; i < characterSlots.Length; i++)
  1147. {
  1148. // If we haven't loaded this slot from GameStateManager, try PlayerPrefs
  1149. if (characterSlots[i] == null && PlayerPrefs.HasKey($"Character{i}_Exists") && PlayerPrefs.GetInt($"Character{i}_Exists") == 1)
  1150. {
  1151. // Load character data from PlayerPrefs
  1152. characterSlots[i] = LoadCharacterFromPlayerPrefs(i);
  1153. // Update the slot button
  1154. if (i < characterSlotButtons.Count)
  1155. {
  1156. characterSlotButtons[i].text = characterSlots[i].name;
  1157. characterSlotButtons[i].SetEnabled(true);
  1158. characterSlotButtons[i].RemoveFromClassList("unity-disabled");
  1159. characterSlotButtons[i].RemoveFromClassList("DisabledCharacterCard");
  1160. // Hide the create button
  1161. if (i < createNewCharacterButtons.Count)
  1162. {
  1163. createNewCharacterButtons[i].style.display = DisplayStyle.None;
  1164. }
  1165. }
  1166. }
  1167. }
  1168. // Count loaded characters
  1169. int loadedCount = 0;
  1170. for (int i = 0; i < characterSlots.Length; i++)
  1171. {
  1172. if (characterSlots[i] != null) loadedCount++;
  1173. }
  1174. }
  1175. private void SaveCurrentTeamToGameState()
  1176. {
  1177. // Save the current team using PlayerPrefs for now
  1178. for (int i = 0; i < characterSlots.Length; i++)
  1179. {
  1180. if (characterSlots[i] != null)
  1181. {
  1182. SaveCharacterToPlayerPrefs(characterSlots[i], i);
  1183. PlayerPrefs.SetInt($"Character{i}_Exists", 1);
  1184. }
  1185. else
  1186. {
  1187. PlayerPrefs.SetInt($"Character{i}_Exists", 0);
  1188. }
  1189. }
  1190. PlayerPrefs.Save();
  1191. }
  1192. private TeamCharacter LoadCharacterFromPlayerPrefs(int index)
  1193. {
  1194. string prefix = $"Character{index}_";
  1195. var character = new TeamCharacter();
  1196. character.name = PlayerPrefs.GetString(prefix + "Name", "");
  1197. character.isMale = PlayerPrefs.GetInt(prefix + "IsMale", 1) == 1;
  1198. character.strength = PlayerPrefs.GetInt(prefix + "Strength", 10);
  1199. character.dexterity = PlayerPrefs.GetInt(prefix + "Dexterity", 10);
  1200. character.constitution = PlayerPrefs.GetInt(prefix + "Constitution", 10);
  1201. character.wisdom = PlayerPrefs.GetInt(prefix + "Wisdom", 10);
  1202. character.gold = PlayerPrefs.GetInt(prefix + "Gold", 25);
  1203. character.silver = PlayerPrefs.GetInt(prefix + "Silver", 0);
  1204. character.copper = PlayerPrefs.GetInt(prefix + "Copper", 0);
  1205. // Recalculate equipment bonuses from inventory after loading
  1206. character.RecalculateEquipmentBonuses();
  1207. return character;
  1208. }
  1209. private void SaveCharacterToPlayerPrefs(TeamCharacter character, int index)
  1210. {
  1211. string prefix = $"Character{index}_";
  1212. PlayerPrefs.SetString(prefix + "Name", character.name);
  1213. PlayerPrefs.SetInt(prefix + "IsMale", character.isMale ? 1 : 0);
  1214. PlayerPrefs.SetInt(prefix + "Strength", character.strength);
  1215. PlayerPrefs.SetInt(prefix + "Dexterity", character.dexterity);
  1216. PlayerPrefs.SetInt(prefix + "Constitution", character.constitution);
  1217. PlayerPrefs.SetInt(prefix + "Wisdom", character.wisdom);
  1218. PlayerPrefs.SetInt(prefix + "Gold", character.gold);
  1219. PlayerPrefs.SetInt(prefix + "Silver", character.silver);
  1220. PlayerPrefs.SetInt(prefix + "Copper", character.copper);
  1221. // Immediately verify what was saved
  1222. string savedName = PlayerPrefs.GetString(prefix + "Name", "FAILED_TO_SAVE");
  1223. int savedStr = PlayerPrefs.GetInt(prefix + "Strength", -1);
  1224. if (savedName != character.name)
  1225. {
  1226. Debug.LogError($" ERROR: Name save failed! Expected '{character.name}', got '{savedName}'");
  1227. }
  1228. }
  1229. #endregion
  1230. #region Team Finalization
  1231. private bool IsTeamFinalized()
  1232. {
  1233. // Check if the team has been finalized (player clicked "Proceed to Battle" and went to MapScene)
  1234. // This is indicated by TeamSetupComplete being true or HasGeneratedMap being true
  1235. bool hasGeneratedMap = PlayerPrefs.HasKey("HasGeneratedMap") && PlayerPrefs.GetInt("HasGeneratedMap") == 1;
  1236. bool teamSetupCompletePrefs = PlayerPrefs.HasKey("TeamSetupComplete") && PlayerPrefs.GetInt("TeamSetupComplete") == 1;
  1237. bool teamSetupCompleteGameState = false;
  1238. if (GameStateManager.Instance != null)
  1239. {
  1240. teamSetupCompleteGameState = GameStateManager.Instance.teamSetupComplete;
  1241. }
  1242. bool finalized = hasGeneratedMap || teamSetupCompletePrefs || teamSetupCompleteGameState;
  1243. return finalized;
  1244. }
  1245. private void SetTeamFinalizedMode()
  1246. {
  1247. // Disable all character creation and editing
  1248. foreach (var button in createNewCharacterButtons)
  1249. {
  1250. button.SetEnabled(false);
  1251. button.style.opacity = 0.5f;
  1252. button.tooltip = "Team has been finalized - cannot create new characters";
  1253. }
  1254. // Disable character editing fields
  1255. DisableCharacterEditingFields();
  1256. // Change the proceed button to "Return to Adventure"
  1257. if (proceedToBattleButton != null)
  1258. {
  1259. proceedToBattleButton.text = "Return to Adventure";
  1260. proceedToBattleButton.tooltip = "Return to your ongoing adventure";
  1261. }
  1262. // Change the back button to offer new game option
  1263. if (backToTitleButton != null)
  1264. {
  1265. backToTitleButton.text = "New Game";
  1266. backToTitleButton.tooltip = "Start a completely new game (will overwrite current save)";
  1267. }
  1268. // Show a message that team is finalized
  1269. }
  1270. private void DisableCharacterEditingFields()
  1271. {
  1272. // Disable name editing
  1273. if (characterNameField != null)
  1274. {
  1275. characterNameField.SetEnabled(false);
  1276. characterNameField.style.opacity = 0.7f;
  1277. }
  1278. if (randomizeNameButton != null)
  1279. {
  1280. randomizeNameButton.SetEnabled(false);
  1281. randomizeNameButton.style.opacity = 0.5f;
  1282. }
  1283. if (genderDropdown != null)
  1284. {
  1285. genderDropdown.SetEnabled(false);
  1286. genderDropdown.style.opacity = 0.7f;
  1287. }
  1288. // Disable stat editing
  1289. if (strengthField != null) strengthField.SetEnabled(false);
  1290. if (dexterityField != null) dexterityField.SetEnabled(false);
  1291. if (constitutionField != null) constitutionField.SetEnabled(false);
  1292. if (wisdomField != null) wisdomField.SetEnabled(false);
  1293. // Disable attribute buttons
  1294. if (randomizeAttributesButton != null)
  1295. {
  1296. randomizeAttributesButton.SetEnabled(false);
  1297. randomizeAttributesButton.style.opacity = 0.5f;
  1298. }
  1299. if (resetToPointBuyButton != null)
  1300. {
  1301. resetToPointBuyButton.SetEnabled(false);
  1302. resetToPointBuyButton.style.opacity = 0.5f;
  1303. }
  1304. // Disable inventory management
  1305. if (addWeaponButton != null)
  1306. {
  1307. addWeaponButton.SetEnabled(false);
  1308. addWeaponButton.style.opacity = 0.5f;
  1309. }
  1310. if (addArmorButton != null)
  1311. {
  1312. addArmorButton.SetEnabled(false);
  1313. addArmorButton.style.opacity = 0.5f;
  1314. }
  1315. if (addMiscButton != null)
  1316. {
  1317. addMiscButton.SetEnabled(false);
  1318. addMiscButton.style.opacity = 0.5f;
  1319. }
  1320. // Disable bank editing
  1321. if (goldField != null) goldField.SetEnabled(false);
  1322. if (silverField != null) silverField.SetEnabled(false);
  1323. if (copperField != null) copperField.SetEnabled(false);
  1324. }
  1325. #endregion
  1326. private System.Collections.IEnumerator RefreshShopManagerReference()
  1327. {
  1328. // Wait for a short delay to allow for potential late initialization
  1329. yield return new WaitForSeconds(0.1f);
  1330. // Try to find the shop manager again
  1331. var newShopManager = FindFirstObjectByType<SimpleShopManager>();
  1332. if (newShopManager != null)
  1333. {
  1334. shopManager = newShopManager;
  1335. SetupShopManagerCallbacks();
  1336. }
  1337. else
  1338. {
  1339. Debug.LogWarning("Still no SimpleShopManager found after delay. You may need to create one manually using the ShopSystemSetup component.");
  1340. }
  1341. }
  1342. private void SetupShopManagerCallbacks()
  1343. {
  1344. if (shopManager != null)
  1345. {
  1346. // Subscribe to character data changes from the shop
  1347. shopManager.OnCharacterDataChanged += OnShopCharacterDataChanged;
  1348. }
  1349. }
  1350. private void OnShopCharacterDataChanged(TeamCharacter updatedCharacter)
  1351. {
  1352. if (updatedCharacter == null || currentCharacter == null)
  1353. {
  1354. Debug.LogWarning("OnShopCharacterDataChanged: updatedCharacter or currentCharacter is null");
  1355. return;
  1356. }
  1357. // Copy the updated data back to the current character
  1358. // This ensures the character object reference remains the same but data is updated
  1359. currentCharacter.gold = updatedCharacter.gold;
  1360. currentCharacter.silver = updatedCharacter.silver;
  1361. currentCharacter.copper = updatedCharacter.copper;
  1362. // Update inventory lists (create new lists to avoid reference issues)
  1363. currentCharacter.weapons = new System.Collections.Generic.List<string>(updatedCharacter.weapons);
  1364. currentCharacter.armor = new System.Collections.Generic.List<string>(updatedCharacter.armor);
  1365. currentCharacter.miscItems = new System.Collections.Generic.List<string>(updatedCharacter.miscItems);
  1366. // Update the UI to reflect the changes
  1367. UpdateInventoryUI();
  1368. // Save the updated character to the slot
  1369. SaveCurrentCharacterToSlot();
  1370. }
  1371. // Clear all equipment from existing characters to ensure shop-only acquisition
  1372. private void ClearAllCharacterEquipment()
  1373. {
  1374. // Clear equipment from any existing characters in slots
  1375. for (int i = 0; i < characterSlots.Length; i++)
  1376. {
  1377. if (characterSlots[i] != null)
  1378. {
  1379. characterSlots[i].weapons.Clear();
  1380. characterSlots[i].armor.Clear();
  1381. characterSlots[i].miscItems.Clear();
  1382. characterSlots[i].equippedWeapon = "";
  1383. characterSlots[i].equippedArmor = "";
  1384. }
  1385. }
  1386. // Also clear equipment from current character if it exists
  1387. if (currentCharacter != null)
  1388. {
  1389. currentCharacter.weapons.Clear();
  1390. currentCharacter.armor.Clear();
  1391. currentCharacter.miscItems.Clear();
  1392. currentCharacter.equippedWeapon = "";
  1393. currentCharacter.equippedArmor = "";
  1394. }
  1395. }
  1396. }
  1397. [System.Serializable]
  1398. public class TeamCharacter
  1399. {
  1400. public string name = "";
  1401. public bool isMale = true;
  1402. // Base attributes (can be modified by equipment in the future)
  1403. public int strength = 10;
  1404. public int dexterity = 10;
  1405. public int constitution = 10;
  1406. public int wisdom = 10;
  1407. // Character creation mode
  1408. public bool isRandomized = false; // Track if stats were randomized
  1409. public int availablePoints = 18; // Point-buy system (adjusted for 4 stats instead of 6)
  1410. // Equipment modifiers (for future use)
  1411. public int strengthModifier = 0;
  1412. public int dexterityModifier = 0;
  1413. public int constitutionModifier = 0;
  1414. public int wisdomModifier = 0;
  1415. public int acModifier = 0; // Direct AC bonuses from equipment
  1416. // Currency
  1417. public int gold = 25; // Reduced starting money to make shop purchases more strategic
  1418. public int silver = 0;
  1419. public int copper = 0;
  1420. // Equipment/Inventory (simple string-based for now)
  1421. public System.Collections.Generic.List<string> weapons = new System.Collections.Generic.List<string>();
  1422. public System.Collections.Generic.List<string> armor = new System.Collections.Generic.List<string>();
  1423. public System.Collections.Generic.List<string> miscItems = new System.Collections.Generic.List<string>();
  1424. public string equippedWeapon = "";
  1425. public string equippedArmor = "";
  1426. // Final attributes (base + equipment modifiers)
  1427. public int FinalStrength => strength + strengthModifier;
  1428. public int FinalDexterity => dexterity + dexterityModifier;
  1429. public int FinalConstitution => constitution + constitutionModifier;
  1430. public int FinalWisdom => wisdom + wisdomModifier;
  1431. // Derived stats (calculated from final stats)
  1432. public int Initiative => FinalDexterity - 10;
  1433. public int DamageBonus => (FinalStrength - 10) / 2;
  1434. public int SpellAC => FinalWisdom - 10; // Renamed from SpellCastingBonus
  1435. public int MovementSpeed => 30 + (int)(Mathf.Ceil((FinalDexterity - 10) / 5.0f) * 5); // Rounded to closest 5 above
  1436. public int HitPoints => Mathf.Max(10, 10 + (FinalConstitution - 10) * 2 + (FinalStrength - 10) + (FinalDexterity - 10) / 2);
  1437. public int ArmorClass => 10 + (FinalDexterity - 10) / 2 + (FinalConstitution - 10) / 3 + acModifier; // Base 10 + DEX bonus + small CON bonus + equipment AC
  1438. public TeamCharacter()
  1439. {
  1440. // Don't generate random name in constructor to avoid serialization issues
  1441. // Name will be generated explicitly when needed
  1442. }
  1443. public TeamCharacter(string characterName, bool male = true)
  1444. {
  1445. name = characterName;
  1446. isMale = male;
  1447. }
  1448. public void GenerateRandomName()
  1449. {
  1450. // Only generate names when the application is playing to avoid serialization issues
  1451. if (Application.isPlaying)
  1452. {
  1453. name = FantasyNameGenerator.GenerateCharacterName(isMale);
  1454. }
  1455. else
  1456. {
  1457. // Fallback name for serialization/design time
  1458. name = isMale ? "New Male Character" : "New Female Character";
  1459. }
  1460. }
  1461. public void SetGender(bool male)
  1462. {
  1463. isMale = male;
  1464. }
  1465. // Randomize all attributes using point-buy system (18 points)
  1466. public void RandomizeAttributes()
  1467. {
  1468. if (Application.isPlaying)
  1469. {
  1470. // Start with random base values (4-12 range for variety)
  1471. int[] stats = new int[4];
  1472. for (int i = 0; i < 4; i++)
  1473. {
  1474. stats[i] = UnityEngine.Random.Range(4, 13); // Random start between 4-12
  1475. }
  1476. // Calculate how many points we've spent so far
  1477. int pointsSpent = 0;
  1478. for (int i = 0; i < 4; i++)
  1479. {
  1480. pointsSpent += GetStatCost(stats[i]);
  1481. }
  1482. int pointsRemaining = 18 - pointsSpent; // Changed from 27 to 18
  1483. // If we're over budget, reduce some stats
  1484. while (pointsRemaining < 0)
  1485. {
  1486. int randomStat = UnityEngine.Random.Range(0, 4);
  1487. if (stats[randomStat] > 4) // Don't go below 4
  1488. {
  1489. int oldCost = GetStatCost(stats[randomStat]);
  1490. stats[randomStat]--;
  1491. int newCost = GetStatCost(stats[randomStat]);
  1492. pointsRemaining += (oldCost - newCost);
  1493. }
  1494. }
  1495. // Now spend remaining points randomly
  1496. while (pointsRemaining > 0)
  1497. {
  1498. // Pick a random stat to increase
  1499. int randomStat = UnityEngine.Random.Range(0, 4);
  1500. // Check if we can afford to increase this stat
  1501. int currentValue = stats[randomStat];
  1502. if (currentValue >= 18) continue; // Can't go higher than 18
  1503. int currentCost = GetStatCost(currentValue);
  1504. int newCost = GetStatCost(currentValue + 1);
  1505. int costDifference = newCost - currentCost;
  1506. if (pointsRemaining >= costDifference)
  1507. {
  1508. stats[randomStat]++;
  1509. pointsRemaining -= costDifference;
  1510. }
  1511. else
  1512. {
  1513. // If we can't afford any increases, try to find a stat we can afford
  1514. bool foundAffordable = false;
  1515. for (int i = 0; i < 4; i++)
  1516. {
  1517. if (stats[i] < 18)
  1518. {
  1519. int testCurrentCost = GetStatCost(stats[i]);
  1520. int testNewCost = GetStatCost(stats[i] + 1);
  1521. int testCostDiff = testNewCost - testCurrentCost;
  1522. if (pointsRemaining >= testCostDiff)
  1523. {
  1524. foundAffordable = true;
  1525. break;
  1526. }
  1527. }
  1528. }
  1529. // If no affordable increases, break out
  1530. if (!foundAffordable) break;
  1531. }
  1532. }
  1533. // Assign back to properties
  1534. strength = stats[0];
  1535. dexterity = stats[1];
  1536. constitution = stats[2];
  1537. wisdom = stats[3];
  1538. // Set as point-buy mode (not locked like true random)
  1539. isRandomized = false;
  1540. UpdateAvailablePoints();
  1541. }
  1542. } // Alternative: Truly random stats (2-18, locked from editing)
  1543. public void RandomizeAttributesWild()
  1544. {
  1545. if (Application.isPlaying)
  1546. {
  1547. strength = UnityEngine.Random.Range(2, 19); // 2-18 inclusive
  1548. dexterity = UnityEngine.Random.Range(2, 19);
  1549. constitution = UnityEngine.Random.Range(2, 19);
  1550. wisdom = UnityEngine.Random.Range(2, 19);
  1551. isRandomized = true;
  1552. availablePoints = 0; // No points available when randomized
  1553. }
  1554. }
  1555. // Reset attributes to default for point-buy
  1556. public void ResetToPointBuy()
  1557. {
  1558. strength = 10;
  1559. dexterity = 10;
  1560. constitution = 10;
  1561. wisdom = 10;
  1562. isRandomized = false;
  1563. availablePoints = 18; // Reset to full point pool (adjusted for 4 stats)
  1564. }
  1565. // Calculate point cost for a stat value (point-buy system)
  1566. public static int GetStatCost(int statValue)
  1567. {
  1568. // Point-buy costs: 4=-4pts, 5=-2pts, 6=-1pts, 7=-1pts, 8=0pts, 9=1pt, 10=2pts, 11=3pts, 12=4pts, 13=5pts, 14=7pts, 15=9pts, 16=12pts, 17=16pts, 18=21pts
  1569. switch (statValue)
  1570. {
  1571. case 4: return -4;
  1572. case 5: return -2;
  1573. case 6: return -1;
  1574. case 7: return -1;
  1575. case 8: return 0;
  1576. case 9: return 1;
  1577. case 10: return 2;
  1578. case 11: return 3;
  1579. case 12: return 4;
  1580. case 13: return 5;
  1581. case 14: return 7;
  1582. case 15: return 9;
  1583. case 16: return 12;
  1584. case 17: return 16;
  1585. case 18: return 21;
  1586. default: return statValue < 4 ? -4 : 25; // Invalid values
  1587. }
  1588. }
  1589. // Calculate total points spent
  1590. public int GetTotalPointsSpent()
  1591. {
  1592. return GetStatCost(strength) + GetStatCost(dexterity) + GetStatCost(constitution) + GetStatCost(wisdom);
  1593. }
  1594. // Update available points based on current stats
  1595. public void UpdateAvailablePoints()
  1596. {
  1597. if (!isRandomized)
  1598. {
  1599. availablePoints = 18 - GetTotalPointsSpent(); // Changed from 27 to 18
  1600. }
  1601. }
  1602. // Check if we can afford to increase a stat
  1603. public bool CanIncreaseStat(int currentValue)
  1604. {
  1605. if (isRandomized) return false; // Can't change randomized stats
  1606. if (currentValue >= 18) return false; // Max value
  1607. int currentCost = GetStatCost(currentValue);
  1608. int newCost = GetStatCost(currentValue + 1);
  1609. int costDifference = newCost - currentCost;
  1610. return availablePoints >= costDifference;
  1611. }
  1612. // Create a deep copy of this character
  1613. public TeamCharacter CreateCopy()
  1614. {
  1615. var copy = new TeamCharacter(name, isMale)
  1616. {
  1617. strength = this.strength,
  1618. dexterity = this.dexterity,
  1619. constitution = this.constitution,
  1620. wisdom = this.wisdom,
  1621. isRandomized = this.isRandomized,
  1622. availablePoints = this.availablePoints,
  1623. gold = this.gold,
  1624. silver = this.silver,
  1625. copper = this.copper,
  1626. equippedWeapon = this.equippedWeapon,
  1627. equippedArmor = this.equippedArmor
  1628. };
  1629. // Deep copy the lists
  1630. copy.weapons = new System.Collections.Generic.List<string>(this.weapons);
  1631. copy.armor = new System.Collections.Generic.List<string>(this.armor);
  1632. copy.miscItems = new System.Collections.Generic.List<string>(this.miscItems);
  1633. return copy;
  1634. }
  1635. // Recalculate all equipment modifiers from items in inventory (temporary solution)
  1636. public void RecalculateEquipmentBonuses()
  1637. {
  1638. // Reset all modifiers to zero
  1639. strengthModifier = 0;
  1640. dexterityModifier = 0;
  1641. constitutionModifier = 0;
  1642. wisdomModifier = 0;
  1643. acModifier = 0;
  1644. // Get reference to the shop manager to access item definitions
  1645. var shopManager = UnityEngine.Object.FindFirstObjectByType<SimpleShopManager>();
  1646. if (shopManager == null) return;
  1647. // Apply bonuses from all items in inventory
  1648. ApplyBonusesFromItemList(shopManager.weapons, weapons);
  1649. ApplyBonusesFromItemList(shopManager.armor, armor);
  1650. ApplyBonusesFromItemList(shopManager.miscItems, miscItems);
  1651. }
  1652. private void ApplyBonusesFromItemList(System.Collections.Generic.List<SimpleShopItem> shopItems, System.Collections.Generic.List<string> ownedItems)
  1653. {
  1654. foreach (string itemName in ownedItems)
  1655. {
  1656. var shopItem = shopItems.Find(item => item.name == itemName);
  1657. if (shopItem != null && shopItem.stats != null)
  1658. {
  1659. strengthModifier += shopItem.stats.strengthBonus;
  1660. dexterityModifier += shopItem.stats.dexterityBonus;
  1661. constitutionModifier += shopItem.stats.constitutionBonus;
  1662. wisdomModifier += shopItem.stats.wisdomBonus;
  1663. acModifier += shopItem.stats.acBonus;
  1664. }
  1665. }
  1666. }
  1667. // Copy data from another character into this one
  1668. public void CopyFrom(TeamCharacter other)
  1669. {
  1670. if (other == null) return;
  1671. name = other.name;
  1672. isMale = other.isMale;
  1673. strength = other.strength;
  1674. dexterity = other.dexterity;
  1675. constitution = other.constitution;
  1676. wisdom = other.wisdom;
  1677. }
  1678. }