| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040 |
- using UnityEngine;
- using UnityEngine.UIElements; // Make sure you have this using directive
- using UnityEngine.SceneManagement; // Added for scene management
- using System.Collections.Generic; // Needed for List<>
- using System.Linq; // Needed for LINQ operations
- using System.Collections; // Needed for coroutines
- public class MainTeamSelectScript : MonoBehaviour
- {
- private UIDocument uiDocument;
- private TeamCharacter currentCharacter;
- private List<Button> characterSlotButtons = new List<Button>();
- private List<Button> createNewCharacterButtons = new List<Button>();
- // Character slot management
- private TeamCharacter[] characterSlots = new TeamCharacter[4]; // 4 character slots
- private int currentSlotIndex = -1; // -1 means no slot selected
- // UI elements
- private TextField characterNameField;
- private Button randomizeNameButton;
- private DropdownField genderDropdown;
- private IntegerField strengthField, dexterityField, constitutionField, wisdomField;
- private IntegerField initField, damageField, spellCastingField, movementSpeedField, hpField, acField;
- // Attribute management UI
- private Button randomizeAttributesButton;
- private Button resetToPointBuyButton;
- private Label availablePointsLabel;
- private Label creationModeLabel;
- // Inventory/Shop UI elements
- private Button addWeaponButton;
- private Button addArmorButton;
- private Button addMiscButton;
- private IntegerField goldField;
- private IntegerField silverField;
- private IntegerField copperField;
- private VisualElement weaponsList;
- private VisualElement armorList;
- private VisualElement miscList;
- // Shop reference
- private SimpleShopManager shopManager;
- // Navigation buttons
- private Button backToTitleButton;
- private Button proceedToBattleButton;
- void Awake()
- {
- uiDocument = GetComponent<UIDocument>();
- if (uiDocument == null)
- {
- Debug.LogError("UIDocument component not found on this GameObject.", this);
- return; // Exit if no UIDocument is found
- }
- // Initialize character slots array
- characterSlots = new TeamCharacter[4];
- // Clear all existing character equipment to ensure shop-only acquisition
- ClearAllCharacterEquipment();
- // Start with no character selected (empty character sheet)
- currentCharacter = null;
- currentSlotIndex = -1;
- // Check if team has been finalized (proceeded to map)
- bool teamFinalized = IsTeamFinalized();
- // Load saved team if available
- LoadSavedTeamData();
- // Get UI element references
- GetUIElementReferences();
- // Set up event listeners
- SetupEventListeners();
- // Try to find missing UI elements one more time after everything is set up
- ValidateUIElements();
- // If team is finalized, disable editing and show message
- if (teamFinalized)
- {
- SetTeamFinalizedMode();
- }
- // Initialize UI with character data
- UpdateCharacterUI();
- UpdateSlotVisualStates();
- UpdateNavigationButtons();
- }
- private void ValidateUIElements()
- {
- // Final attempt to find critical UI elements that might have been missed
- if (proceedToBattleButton == null && uiDocument != null)
- {
- var root = uiDocument.rootVisualElement;
- Debug.LogWarning("Final attempt to find proceedToBattleButton...");
- // Try searching with different approaches
- proceedToBattleButton = root.Q<Button>("ProceedToBattleButton") ??
- root.Q<Button>("ProceedButton") ??
- root.Q<Button>("StartButton") ??
- root.Q<Button>(className: "proceed-button");
- // If still not found, search through all buttons for text matches
- if (proceedToBattleButton == null)
- {
- var allButtons = root.Query<Button>().ToList();
- foreach (var button in allButtons)
- {
- if (button.text.ToLower().Contains("proceed") ||
- button.text.ToLower().Contains("start") ||
- button.text.ToLower().Contains("battle"))
- {
- proceedToBattleButton = button;
- break;
- }
- }
- }
- if (proceedToBattleButton != null)
- {
- // Set up the event listener since we found it late
- proceedToBattleButton.clicked += OnProceedToBattleClicked;
- }
- else
- {
- Debug.LogError("CRITICAL: Could not find proceed button in UI! Please check the UI Document.");
- }
- }
- }
- private void GetUIElementReferences()
- {
- var root = uiDocument.rootVisualElement;
- // Character info fields
- characterNameField = root.Q<TextField>("CharacterNameField");
- randomizeNameButton = root.Q<Button>("RandomizeNameButton");
- genderDropdown = root.Q<DropdownField>("GenderDropdown");
- // Stat fields
- strengthField = root.Q<IntegerField>("StrengthValue");
- dexterityField = root.Q<IntegerField>("DexterityValue");
- constitutionField = root.Q<IntegerField>("ConstitutionValue");
- wisdomField = root.Q<IntegerField>("WisdomValue");
- // Derived stat fields
- initField = root.Q<IntegerField>("InitValue");
- damageField = root.Q<IntegerField>("DamageValue");
- spellCastingField = root.Q<IntegerField>("SpellCastingValue");
- movementSpeedField = root.Q<IntegerField>("MovementSpeedValue");
- hpField = root.Q<IntegerField>("HPValue");
- acField = root.Q<IntegerField>("ACValue");
- // Attribute management UI
- randomizeAttributesButton = root.Q<Button>("RandomizeAttributesButton");
- resetToPointBuyButton = root.Q<Button>("ResetToPointBuyButton");
- availablePointsLabel = root.Q<Label>("AvailablePointsLabel");
- creationModeLabel = root.Q<Label>("CreationModeLabel");
- // Find all buttons with the name "CreateNewCharacterButton"
- createNewCharacterButtons = uiDocument.rootVisualElement.Query<Button>("CreateNewCharacterButton").ToList();
- // Find all ViewCharacterButton buttons
- characterSlotButtons = uiDocument.rootVisualElement.Query<Button>("ViewCharacterButton").ToList();
- // Inventory/Shop UI elements
- addWeaponButton = root.Q<Button>("AddWeaponButton");
- addArmorButton = root.Q<Button>("AddArmourButton");
- addMiscButton = root.Q<Button>("AddMiscButton");
- goldField = root.Q<IntegerField>("GoldValue");
- silverField = root.Q<IntegerField>("SilverValue");
- copperField = root.Q<IntegerField>("CopperValue");
- weaponsList = root.Q<VisualElement>("WeaponsList");
- armorList = root.Q<VisualElement>("ArmourList");
- miscList = root.Q<VisualElement>("MiscList");
- // Navigation buttons
- backToTitleButton = root.Q<Button>("BackToTitleButton");
- proceedToBattleButton = root.Q<Button>("ProceedToBattleButton");
- // Debug and fallback for Back to Title button
- if (backToTitleButton == null)
- {
- Debug.LogWarning("BackToTitleButton not found! Creating fallback button...");
- // Create a simple fallback button
- backToTitleButton = new Button();
- backToTitleButton.text = "Back to Title";
- backToTitleButton.name = "BackToTitleButton_Fallback";
- backToTitleButton.style.position = Position.Absolute;
- backToTitleButton.style.top = 10;
- backToTitleButton.style.left = 10;
- backToTitleButton.style.width = 120;
- backToTitleButton.style.height = 30;
- root.Add(backToTitleButton);
- }
- // Find shop manager in scene
- shopManager = FindFirstObjectByType<SimpleShopManager>();
- if (shopManager == null)
- {
- Debug.LogWarning("No SimpleShopManager found in scene. Shop functionality will be limited.");
- Debug.LogWarning("Trying to refresh shop manager reference...");
- // Try again after a short delay to allow for potential late initialization
- StartCoroutine(RefreshShopManagerReference());
- }
- else
- {
- SetupShopManagerCallbacks();
- }
- // Check if any buttons were found
- if (createNewCharacterButtons.Count == 0)
- {
- Debug.LogWarning("No buttons with the name 'CreateNewCharacterButton' found in the UI Document.");
- }
- else
- {
- // Add a click listener to each button found
- foreach (Button button in createNewCharacterButtons)
- {
- // Example of passing data (requires adjusting the handler method):
- int characterIndex = createNewCharacterButtons.IndexOf(button); // Example data
- button.clicked += () => OnCreateNewCharacterButtonClicked(characterIndex);
- }
- }
- // Add click listeners to ViewCharacterButton buttons
- for (int i = 0; i < characterSlotButtons.Count; i++)
- {
- int index = i; // Capture the index for the closure
- characterSlotButtons[i].clicked += () => OnViewCharacterButtonClicked(index);
- }
- }
- private void SetupEventListeners()
- {
- // Name randomization
- if (randomizeNameButton != null)
- {
- randomizeNameButton.clicked += OnRandomizeNameClicked;
- }
- // Character name change
- if (characterNameField != null)
- {
- characterNameField.RegisterValueChangedCallback(OnCharacterNameChanged);
- }
- // Gender change
- if (genderDropdown != null)
- {
- genderDropdown.RegisterValueChangedCallback(OnGenderChanged);
- }
- // Stat changes
- if (strengthField != null)
- strengthField.RegisterValueChangedCallback(evt => OnStatChanged());
- if (dexterityField != null)
- dexterityField.RegisterValueChangedCallback(evt => OnStatChanged());
- if (constitutionField != null)
- constitutionField.RegisterValueChangedCallback(evt => OnStatChanged());
- if (wisdomField != null)
- wisdomField.RegisterValueChangedCallback(evt => OnStatChanged());
- // Attribute management
- if (randomizeAttributesButton != null)
- randomizeAttributesButton.clicked += OnRandomizeAttributesClicked;
- if (resetToPointBuyButton != null)
- resetToPointBuyButton.clicked += OnResetToPointBuyClicked;
- // Inventory/Shop management
- if (addWeaponButton != null)
- addWeaponButton.clicked += OnAddWeaponClicked;
- if (addArmorButton != null)
- addArmorButton.clicked += OnAddArmorClicked;
- if (addMiscButton != null)
- addMiscButton.clicked += OnAddMiscClicked;
- // Bank field changes
- if (goldField != null)
- goldField.RegisterValueChangedCallback(evt => OnBankChanged());
- if (silverField != null)
- silverField.RegisterValueChangedCallback(evt => OnBankChanged());
- if (copperField != null)
- copperField.RegisterValueChangedCallback(evt => OnBankChanged());
- // Navigation buttons
- if (backToTitleButton != null)
- backToTitleButton.clicked += OnBackToTitleClicked;
- if (proceedToBattleButton != null)
- proceedToBattleButton.clicked += OnProceedToBattleClicked;
- else
- Debug.LogWarning("proceedToBattleButton is null during SetupEventListeners - will try to set up event listener later");
- }
- private void OnRandomizeNameClicked()
- {
- if (currentCharacter == null) return;
- currentCharacter.GenerateRandomName();
- characterNameField.value = currentCharacter.name;
- // Update the slot button and save to slot
- UpdateCurrentSlotButton();
- SaveCurrentCharacterToSlot();
- }
- private void OnCharacterNameChanged(ChangeEvent<string> evt)
- {
- if (currentCharacter == null) return;
- currentCharacter.name = evt.newValue;
- // Update the slot button and save to slot
- UpdateCurrentSlotButton();
- SaveCurrentCharacterToSlot();
- // Update the character card if we have a current slot
- if (currentSlotIndex >= 0)
- {
- UpdateCharacterCard(currentSlotIndex, currentCharacter);
- }
- }
- private void OnGenderChanged(ChangeEvent<string> evt)
- {
- if (currentCharacter == null) return;
- currentCharacter.SetGender(evt.newValue == "Male");
- // Optionally regenerate name when gender changes
- // You can remove this if you don't want automatic name regeneration
- currentCharacter.GenerateRandomName();
- characterNameField.value = currentCharacter.name;
- // Update the slot button and save to slot
- UpdateCurrentSlotButton();
- SaveCurrentCharacterToSlot();
- // Update the character card if we have a current slot
- if (currentSlotIndex >= 0)
- {
- UpdateCharacterCard(currentSlotIndex, currentCharacter);
- }
- }
- private void OnStatChanged()
- {
- if (currentCharacter == null) return;
- // Validate point-buy constraints
- int newStr = strengthField?.value ?? currentCharacter.strength;
- int newDex = dexterityField?.value ?? currentCharacter.dexterity;
- int newCon = constitutionField?.value ?? currentCharacter.constitution;
- int newWis = wisdomField?.value ?? currentCharacter.wisdom;
- // Clamp values to valid range (4-18)
- newStr = Mathf.Clamp(newStr, 4, 18);
- newDex = Mathf.Clamp(newDex, 4, 18);
- newCon = Mathf.Clamp(newCon, 4, 18);
- newWis = Mathf.Clamp(newWis, 4, 18);
- // Check if the new combination is affordable
- int totalCost = TeamCharacter.GetStatCost(newStr) + TeamCharacter.GetStatCost(newDex) +
- TeamCharacter.GetStatCost(newCon) + TeamCharacter.GetStatCost(newWis);
- if (totalCost <= 18) // Changed from 27 to 18 for 4-stat system
- {
- // Update character stats from UI
- currentCharacter.strength = newStr;
- currentCharacter.dexterity = newDex;
- currentCharacter.constitution = newCon;
- currentCharacter.wisdom = newWis;
- currentCharacter.UpdateAvailablePoints();
- }
- else
- {
- // Reset to previous valid values
- if (strengthField != null) strengthField.value = currentCharacter.strength;
- if (dexterityField != null) dexterityField.value = currentCharacter.dexterity;
- if (constitutionField != null) constitutionField.value = currentCharacter.constitution;
- if (wisdomField != null) wisdomField.value = currentCharacter.wisdom;
- }
- // Update derived stats and point display
- UpdateDerivedStats();
- UpdateAttributeUI();
- SaveCurrentCharacterToSlot();
- UpdateNavigationButtons();
- // Update the character card if we have a current slot
- if (currentSlotIndex >= 0)
- {
- UpdateCharacterCard(currentSlotIndex, currentCharacter);
- }
- }
- private void OnRandomizeAttributesClicked()
- {
- if (currentCharacter == null) return;
- currentCharacter.RandomizeAttributes();
- UpdateCharacterUI();
- UpdateAttributeUI();
- SaveCurrentCharacterToSlot();
- UpdateNavigationButtons();
- // Update the character card if we have a current slot
- if (currentSlotIndex >= 0)
- {
- UpdateCharacterCard(currentSlotIndex, currentCharacter);
- }
- }
- private void OnResetToPointBuyClicked()
- {
- if (currentCharacter == null) return;
- currentCharacter.ResetToPointBuy();
- UpdateCharacterUI();
- UpdateAttributeUI();
- SaveCurrentCharacterToSlot();
- UpdateNavigationButtons();
- // Update the character card if we have a current slot
- if (currentSlotIndex >= 0)
- {
- UpdateCharacterCard(currentSlotIndex, currentCharacter);
- }
- }
- private void OnAddWeaponClicked()
- {
- if (currentCharacter == null)
- {
- Debug.LogWarning("OnAddWeaponClicked: No current character selected");
- return;
- }
- // Open weapon shop for this character
- OpenWeaponShop();
- }
- private void OpenWeaponShop()
- {
- if (shopManager != null)
- {
- shopManager.OpenShop(currentCharacter);
- }
- else
- {
- Debug.LogWarning("No shop manager found - cannot open shop");
- }
- }
- private void AddWeaponToCharacter(string weaponType)
- {
- // Add weapon to character's inventory (would integrate with real shop/inventory system)
- if (currentCharacter.weapons == null)
- {
- currentCharacter.weapons = new System.Collections.Generic.List<string>();
- }
- currentCharacter.weapons.Add(weaponType);
- SaveCurrentCharacterToSlot();
- }
- private void OnAddArmorClicked()
- {
- if (currentCharacter == null) return;
- if (shopManager != null)
- {
- shopManager.OpenShop(currentCharacter);
- }
- else
- {
- Debug.LogWarning("No shop manager found - cannot open shop");
- }
- }
- private void OnAddMiscClicked()
- {
- if (currentCharacter == null) return;
- if (shopManager != null)
- {
- shopManager.OpenShop(currentCharacter);
- }
- else
- {
- Debug.LogWarning("No shop manager found - cannot open shop");
- }
- }
- private void AddArmorToCharacter(string armorType)
- {
- if (currentCharacter.armor == null)
- {
- currentCharacter.armor = new System.Collections.Generic.List<string>();
- }
- currentCharacter.armor.Add(armorType);
- SaveCurrentCharacterToSlot();
- UpdateInventoryUI();
- }
- private void AddMiscItemToCharacter(string itemType)
- {
- if (currentCharacter.miscItems == null)
- {
- currentCharacter.miscItems = new System.Collections.Generic.List<string>();
- }
- currentCharacter.miscItems.Add(itemType);
- SaveCurrentCharacterToSlot();
- UpdateInventoryUI();
- }
- private void OnBankChanged()
- {
- if (currentCharacter == null) return;
- currentCharacter.gold = goldField?.value ?? currentCharacter.gold;
- currentCharacter.silver = silverField?.value ?? currentCharacter.silver;
- currentCharacter.copper = copperField?.value ?? currentCharacter.copper;
- SaveCurrentCharacterToSlot();
- }
- private void UpdateInventoryUI()
- {
- if (currentCharacter == null) return;
- // Update bank fields
- if (goldField != null) goldField.value = currentCharacter.gold;
- if (silverField != null) silverField.value = currentCharacter.silver;
- if (copperField != null) copperField.value = currentCharacter.copper;
- // Update weapon list
- UpdateItemList(weaponsList, currentCharacter.weapons, "WeaponItemRow", OnRemoveWeapon);
- // Update armor list
- UpdateItemList(armorList, currentCharacter.armor, "ArmorItemRow", OnRemoveArmor);
- // Update misc list
- UpdateItemList(miscList, currentCharacter.miscItems, "MiscItemRow", OnRemoveMisc);
- }
- private void UpdateItemList(VisualElement container, System.Collections.Generic.List<string> items, string rowClassName, System.Action<string> removeAction)
- {
- if (container == null || items == null) return;
- // Clear existing items (except example rows)
- var itemsToRemove = container.Query<VisualElement>(className: "inventory-item-row").ToList()
- .Where(item => !item.name.Contains("Example")).ToList();
- foreach (var item in itemsToRemove)
- {
- container.Remove(item);
- }
- // Add current items
- foreach (var itemName in items)
- {
- var itemRow = new VisualElement();
- itemRow.AddToClassList("inventory-item-row");
- itemRow.AddToClassList(rowClassName);
- var nameLabel = new Label(itemName);
- nameLabel.AddToClassList("item-name-label");
- itemRow.Add(nameLabel);
- var removeButton = new Button(() => removeAction(itemName));
- removeButton.text = "Remove (Refund)";
- removeButton.AddToClassList("remove-item-button");
- // Add tooltip or title to show refund information
- string itemType = GetItemTypeFromClassName(rowClassName);
- string refundInfo = GetRefundInfo(itemName, itemType);
- if (!string.IsNullOrEmpty(refundInfo))
- {
- removeButton.tooltip = $"Remove and refund: {refundInfo}";
- }
- itemRow.Add(removeButton);
- container.Add(itemRow);
- }
- }
- private string GetItemTypeFromClassName(string className)
- {
- if (className.Contains("Weapon")) return "weapon";
- if (className.Contains("Armor")) return "armor";
- if (className.Contains("Misc")) return "misc";
- return "";
- }
- private string GetRefundInfo(string itemName, string itemType)
- {
- if (shopManager == null) return "";
- System.Collections.Generic.List<SimpleShopItem> itemList = null;
- switch (itemType.ToLower())
- {
- case "weapon":
- itemList = shopManager.weapons;
- break;
- case "armor":
- itemList = shopManager.armor;
- break;
- case "misc":
- itemList = shopManager.miscItems;
- break;
- }
- if (itemList != null)
- {
- var shopItem = itemList.Find(item => item.name == itemName);
- if (shopItem != null)
- {
- return shopItem.GetCostString();
- }
- }
- return "";
- }
- private void RefundItemPrice(string itemName, string itemType)
- {
- if (shopManager == null || currentCharacter == null)
- {
- Debug.LogWarning($"Cannot refund {itemName}: shop manager or current character is null");
- return;
- }
- // Find the item price from the shop manager
- int goldRefund = 0;
- int silverRefund = 0;
- int copperRefund = 0;
- // Check the appropriate list based on item type
- System.Collections.Generic.List<SimpleShopItem> itemList = null;
- switch (itemType.ToLower())
- {
- case "weapon":
- itemList = shopManager.weapons;
- break;
- case "armor":
- itemList = shopManager.armor;
- break;
- case "misc":
- itemList = shopManager.miscItems;
- break;
- }
- if (itemList != null)
- {
- // Find the item in the shop list
- var shopItem = itemList.Find(item => item.name == itemName);
- if (shopItem != null)
- {
- goldRefund = shopItem.goldCost;
- silverRefund = shopItem.silverCost;
- copperRefund = shopItem.copperCost;
- // Add the refund to the character's money
- currentCharacter.gold += goldRefund;
- currentCharacter.silver += silverRefund;
- currentCharacter.copper += copperRefund;
- }
- else
- {
- Debug.LogWarning($"Could not find {itemName} in shop {itemType} list for refund");
- }
- }
- else
- {
- Debug.LogWarning($"Could not access shop {itemType} list for refund");
- }
- }
- private void OnRemoveWeapon(string weaponName)
- {
- if (currentCharacter?.weapons != null)
- {
- currentCharacter.weapons.Remove(weaponName);
- // Refund the weapon price
- RefundItemPrice(weaponName, "weapon");
- SaveCurrentCharacterToSlot();
- UpdateInventoryUI();
- }
- }
- private void OnRemoveArmor(string armorName)
- {
- if (currentCharacter?.armor != null)
- {
- currentCharacter.armor.Remove(armorName);
- // Refund the armor price
- RefundItemPrice(armorName, "armor");
- SaveCurrentCharacterToSlot();
- UpdateInventoryUI();
- }
- }
- private void OnRemoveMisc(string itemName)
- {
- if (currentCharacter?.miscItems != null)
- {
- currentCharacter.miscItems.Remove(itemName);
- // Refund the misc item price
- RefundItemPrice(itemName, "misc");
- SaveCurrentCharacterToSlot();
- UpdateInventoryUI();
- }
- }
- private void UpdateCharacterUI()
- {
- if (currentCharacter == null)
- {
- // Clear the UI when no character is selected
- if (characterNameField != null) characterNameField.value = "";
- if (genderDropdown != null) genderDropdown.value = "Male";
- if (strengthField != null) strengthField.value = 10;
- if (dexterityField != null) dexterityField.value = 10;
- if (constitutionField != null) constitutionField.value = 10;
- if (wisdomField != null) wisdomField.value = 10;
- // Clear derived stats
- if (initField != null) initField.value = 0;
- if (damageField != null) damageField.value = 0;
- if (spellCastingField != null) spellCastingField.value = 0;
- if (movementSpeedField != null) movementSpeedField.value = 30;
- if (hpField != null) hpField.value = 10;
- if (acField != null) acField.value = 0;
- // Clear attribute UI
- if (creationModeLabel != null) creationModeLabel.text = "Mode: None";
- if (availablePointsLabel != null) availablePointsLabel.text = "Available Points: 0";
- return;
- }
- // Update UI with current character data
- if (characterNameField != null)
- characterNameField.value = currentCharacter.name;
- if (genderDropdown != null)
- genderDropdown.value = currentCharacter.isMale ? "Male" : "Female";
- if (strengthField != null) strengthField.value = currentCharacter.strength;
- if (dexterityField != null) dexterityField.value = currentCharacter.dexterity;
- if (constitutionField != null) constitutionField.value = currentCharacter.constitution;
- if (wisdomField != null) wisdomField.value = currentCharacter.wisdom;
- // Recalculate equipment bonuses from inventory
- currentCharacter.RecalculateEquipmentBonuses();
- UpdateDerivedStats();
- UpdateAttributeUI();
- UpdateInventoryUI();
- }
- private void UpdateAttributeUI()
- {
- if (currentCharacter == null) return;
- // Update creation mode display
- if (creationModeLabel != null)
- {
- creationModeLabel.text = "Mode: Point Buy";
- }
- // Update available points display
- if (availablePointsLabel != null)
- {
- availablePointsLabel.text = $"Available Points: {currentCharacter.availablePoints}";
- }
- // All stat fields are always editable in the new system
- if (strengthField != null) strengthField.SetEnabled(true);
- if (dexterityField != null) dexterityField.SetEnabled(true);
- if (constitutionField != null) constitutionField.SetEnabled(true);
- if (wisdomField != null) wisdomField.SetEnabled(true);
- }
- private void UpdateDerivedStats()
- {
- if (currentCharacter == null) return;
- // Update the read-only derived stats (uses final stats including equipment modifiers)
- if (initField != null) initField.value = currentCharacter.Initiative;
- if (damageField != null) damageField.value = currentCharacter.DamageBonus;
- if (spellCastingField != null) spellCastingField.value = currentCharacter.SpellAC;
- if (movementSpeedField != null) movementSpeedField.value = currentCharacter.MovementSpeed;
- if (hpField != null) hpField.value = currentCharacter.HitPoints;
- if (acField != null) acField.value = currentCharacter.ArmorClass;
- }
- private void UpdateCurrentSlotButton()
- {
- // Update the character card information if we have a current slot selected
- if (currentSlotIndex >= 0 && currentSlotIndex < characterSlotButtons.Count && currentCharacter != null)
- {
- UpdateCharacterCard(currentSlotIndex, currentCharacter);
- }
- }
- private void UpdateCharacterCard(int slotIndex, TeamCharacter character)
- {
- if (slotIndex < 0 || slotIndex >= 4 || character == null) return;
- var root = uiDocument.rootVisualElement;
- // Find the character slot instance based on index
- string[] slotNames = { "Character1", "Character2", "Character3", "Character4" };
- var characterSlot = root.Q<VisualElement>(slotNames[slotIndex]);
- if (characterSlot == null) return;
- // Find the character card button within this slot
- var characterCard = characterSlot.Q<Button>("ViewCharacterButton");
- if (characterCard == null) return;
- // Update character name
- var nameLabel = characterCard.Q<Label>("CharacterNameLabel");
- if (nameLabel != null)
- {
- nameLabel.text = character.name;
- }
- // Update stats
- var strengthLabel = characterCard.Q<Label>("StrengthLabel");
- if (strengthLabel != null) strengthLabel.text = character.strength.ToString();
- var dexterityLabel = characterCard.Q<Label>("DexterityLabel");
- if (dexterityLabel != null) dexterityLabel.text = character.dexterity.ToString();
- var constitutionLabel = characterCard.Q<Label>("ConstitutionLabel");
- if (constitutionLabel != null) constitutionLabel.text = character.constitution.ToString();
- var wisdomLabel = characterCard.Q<Label>("WisdomLabel");
- if (wisdomLabel != null) wisdomLabel.text = character.wisdom.ToString();
- // Update HP and AC
- var hpLabel = characterCard.Q<Label>("HPLabel");
- if (hpLabel != null) hpLabel.text = $"HP: {character.HitPoints}";
- var acLabel = characterCard.Q<Label>("ACLabel");
- if (acLabel != null) acLabel.text = $"AC: {character.ArmorClass}";
- // Show the character card and hide the create button
- var createButton = characterSlot.Q<Button>("CreateNewCharacterButton");
- if (createButton != null)
- {
- createButton.style.display = DisplayStyle.None;
- }
- characterCard.RemoveFromClassList("disabled-card");
- characterCard.style.display = DisplayStyle.Flex;
- characterCard.SetEnabled(true);
- }
- private void SaveCurrentCharacterToSlot()
- {
- // Save the current character data back to its slot
- if (currentSlotIndex >= 0 && currentSlotIndex < characterSlots.Length && currentCharacter != null)
- {
- characterSlots[currentSlotIndex] = currentCharacter.CreateCopy();
- }
- }
- private void UpdateSlotVisualStates()
- {
- var root = uiDocument.rootVisualElement;
- string[] slotNames = { "Character1", "Character2", "Character3", "Character4" };
- // Update visual states of all character slots
- for (int i = 0; i < slotNames.Length; i++)
- {
- var characterSlot = root.Q<VisualElement>(slotNames[i]);
- if (characterSlot == null) continue;
- // Remove all visual state classes first
- characterSlot.RemoveFromClassList("selected-slot");
- // Add selected state if this is the current slot
- if (i == currentSlotIndex)
- {
- characterSlot.AddToClassList("selected-slot");
- }
- // Update character card visibility and data
- if (characterSlots[i] != null)
- {
- // Character exists in this slot
- UpdateCharacterCard(i, characterSlots[i]);
- }
- else
- {
- // No character in this slot - show create button
- var createButton = characterSlot.Q<Button>("CreateNewCharacterButton");
- var characterCard = characterSlot.Q<Button>("ViewCharacterButton");
- if (createButton != null)
- {
- createButton.style.display = DisplayStyle.Flex;
- }
- if (characterCard != null)
- {
- characterCard.style.display = DisplayStyle.None;
- characterCard.AddToClassList("disabled-card");
- characterCard.SetEnabled(false);
- }
- }
- }
- }
- // Example handler if you need to pass data (like an index)
- private void OnCreateNewCharacterButtonClicked(int index)
- {
- // Create a new character with random name
- currentCharacter = new TeamCharacter();
- // Generate name after construction to avoid serialization issues
- currentCharacter.GenerateRandomName();
- // Save character to the slot (create a proper copy)
- characterSlots[index] = currentCharacter.CreateCopy();
- currentSlotIndex = index;
- UpdateCharacterUI();
- UpdateSlotVisualStates();
- // Update navigation buttons immediately after character creation
- UpdateNavigationButtons();
- // Update the character card for this slot
- UpdateCharacterCard(index, currentCharacter);
- // Call UpdateNavigationButtons again after UI updates
- UpdateNavigationButtons();
- }
- private void OnViewCharacterButtonClicked(int index)
- {
- // Check if there's a character in this slot
- if (characterSlots[index] != null)
- {
- // Create a working copy of the character from the slot
- currentCharacter = characterSlots[index].CreateCopy();
- currentSlotIndex = index;
- UpdateCharacterUI();
- UpdateSlotVisualStates();
- UpdateNavigationButtons();
- }
- else
- {
- // Slot is empty, save current character to this slot if we have one
- if (currentCharacter != null)
- {
- // Create a proper copy of the current character data
- characterSlots[index] = currentCharacter.CreateCopy();
- currentSlotIndex = index;
- // Update the character card for this slot
- UpdateCharacterCard(index, currentCharacter);
- UpdateSlotVisualStates();
- UpdateNavigationButtons();
- }
- }
- }
- // Start is called once before the first execution of Update after the MonoBehaviour is created
- void Start()
- {
- // You can keep Start if needed for other initialization
- }
- // Update is called once per frame
- void Update()
- {
- // Debug keys for testing
- if (Input.GetKeyDown(KeyCode.F5))
- {
- DebugCurrentCharacterSlots();
- }
- if (Input.GetKeyDown(KeyCode.F6))
- {
- SaveTeamToGameState();
- }
- if (Input.GetKeyDown(KeyCode.F7))
- {
- TestPlayerPrefsData();
- }
- }
- private void DebugCurrentCharacterSlots()
- {
- for (int i = 0; i < characterSlots.Length; i++)
- {
- if (characterSlots[i] != null)
- {
- var character = characterSlots[i];
- }
- else
- {
- }
- }
- }
- private void TestPlayerPrefsData()
- {
- for (int i = 0; i < 4; i++)
- {
- string existsKey = $"Character{i}_Exists";
- if (PlayerPrefs.HasKey(existsKey))
- {
- int exists = PlayerPrefs.GetInt(existsKey);
- if (exists == 1)
- {
- string prefix = $"Character{i}_";
- string name = PlayerPrefs.GetString(prefix + "Name", "UNKNOWN");
- int str = PlayerPrefs.GetInt(prefix + "Strength", 0);
- int dex = PlayerPrefs.GetInt(prefix + "Dexterity", 0);
- int con = PlayerPrefs.GetInt(prefix + "Constitution", 0);
- int wis = PlayerPrefs.GetInt(prefix + "Wisdom", 0);
- }
- }
- else
- {
- }
- }
- }
- void OnDestroy()
- {
- // Clean up shop manager callbacks to prevent memory leaks
- if (shopManager != null)
- {
- shopManager.OnCharacterDataChanged -= OnShopCharacterDataChanged;
- }
- }
- #region Navigation Methods
- private void OnBackToTitleClicked()
- {
- // Check if team is finalized and this is acting as "New Game" button
- if (IsTeamFinalized())
- {
- // Show confirmation dialog for starting new game
- #if UNITY_EDITOR
- bool confirmed = UnityEditor.EditorUtility.DisplayDialog(
- "Start New Game",
- "This will start a completely new game and overwrite your current progress.\n\nAre you sure you want to continue?",
- "Start New Game",
- "Cancel"
- );
- if (confirmed)
- {
- StartNewGame();
- }
- #else
- // In builds, we'll assume user confirms for now
- // In a real game, implement a proper UI dialog system
- Debug.LogWarning("Starting new game - implement proper dialog for builds");
- StartNewGame();
- #endif
- }
- else
- {
- // Normal back to title behavior
- SceneManager.LoadScene("TitleScreenScene");
- }
- }
- private void StartNewGame()
- {
- // Initialize GameStateManager for new game
- if (GameStateManager.Instance != null)
- {
- GameStateManager.Instance.StartNewGame();
- }
- // Clear all save data
- ClearAllSaveData();
- // Reload the scene to start fresh
- SceneManager.LoadScene("MainTeamSelectScene");
- }
- private void ClearAllSaveData()
- {
- // Clear GameStateManager data
- if (GameStateManager.Instance != null)
- {
- GameStateManager.Instance.teamSetupComplete = false;
- GameStateManager.Instance.hasGeneratedMap = false;
- }
- // Clear PlayerPrefs data
- for (int i = 0; i < 4; i++)
- {
- string prefix = $"Character{i}_";
- PlayerPrefs.DeleteKey($"Character{i}_Exists");
- PlayerPrefs.DeleteKey(prefix + "Name");
- PlayerPrefs.DeleteKey(prefix + "IsMale");
- PlayerPrefs.DeleteKey(prefix + "Strength");
- PlayerPrefs.DeleteKey(prefix + "Dexterity");
- PlayerPrefs.DeleteKey(prefix + "Constitution");
- PlayerPrefs.DeleteKey(prefix + "Wisdom");
- PlayerPrefs.DeleteKey(prefix + "Gold");
- PlayerPrefs.DeleteKey(prefix + "Silver");
- PlayerPrefs.DeleteKey(prefix + "Copper");
- }
- // Clear map data
- PlayerPrefs.DeleteKey("HasGeneratedMap");
- PlayerPrefs.DeleteKey("MapSeed");
- PlayerPrefs.DeleteKey("TeamSize");
- PlayerPrefs.DeleteKey("TeamSetupComplete");
- PlayerPrefs.DeleteKey("GameSaved");
- PlayerPrefs.Save();
- }
- private void OnProceedToBattleClicked()
- {
- // Check if team is already finalized
- if (IsTeamFinalized())
- {
- // Team is finalized, return to MapScene2
- SceneManager.LoadScene("MapScene2");
- return;
- }
- // Check if we have at least one character
- if (!HasAtLeastOneCharacter())
- {
- Debug.LogWarning("Need at least one character to proceed to battle!");
- // TODO: Show message to user
- return;
- }
- // Save all configured characters before proceeding
- SaveTeamToGameState();
- // Mark that the team has proceeded to the map (finalized)
- // Save to both GameStateManager and PlayerPrefs for redundancy
- if (GameStateManager.Instance != null)
- {
- GameStateManager.Instance.teamSetupComplete = true;
- GameStateManager.Instance.SaveGame();
- }
- // Also save to PlayerPrefs as backup
- PlayerPrefs.SetInt("TeamSetupComplete", 1);
- PlayerPrefs.Save();
- SceneManager.LoadScene("MapScene2");
- }
- private void SaveTeamToGameState()
- {
- // Save team data to GameStateManager for persistence
- List<TeamCharacter> configuredCharacters = new List<TeamCharacter>();
- for (int i = 0; i < characterSlots.Length; i++)
- {
- if (characterSlots[i] != null)
- {
- configuredCharacters.Add(characterSlots[i]);
- // Save individual character data
- SaveCharacterToPlayerPrefs(characterSlots[i], i);
- // Verify the save immediately
- PlayerPrefs.SetInt($"Character{i}_Exists", 1);
- string testName = PlayerPrefs.GetString($"Character{i}_Name", "NOT_FOUND");
- }
- else
- {
- // Clear any existing character data for empty slots
- PlayerPrefs.DeleteKey($"Character{i}_Exists");
- }
- }
- // Save team composition info
- PlayerPrefs.SetInt("TeamSize", configuredCharacters.Count);
- // Update GameStateManager if available
- if (GameStateManager.Instance != null)
- {
- // Copy our team to the GameStateManager
- for (int i = 0; i < characterSlots.Length; i++)
- {
- if (characterSlots[i] != null)
- {
- GameStateManager.Instance.savedTeam[i] = characterSlots[i].CreateCopy();
- }
- else
- {
- GameStateManager.Instance.savedTeam[i] = null;
- }
- }
- GameStateManager.Instance.teamSetupComplete = true;
- GameStateManager.Instance.SaveGame();
- }
- else
- {
- Debug.LogWarning("GameStateManager.Instance is null!");
- }
- // Log configured team for MapScene
- foreach (var character in configuredCharacters)
- {
- }
- PlayerPrefs.Save(); // Ensure data is written to disk
- }
- public List<TeamCharacter> GetConfiguredCharacters()
- {
- // Public method to get all configured characters (useful for other scripts)
- List<TeamCharacter> configuredCharacters = new List<TeamCharacter>();
- for (int i = 0; i < characterSlots.Length; i++)
- {
- if (characterSlots[i] != null)
- {
- configuredCharacters.Add(characterSlots[i]);
- }
- }
- return configuredCharacters;
- }
- private void UpdateNavigationButtons()
- {
- // Enable/disable proceed button based on team status
- if (proceedToBattleButton != null)
- {
- bool canProceed = HasAtLeastOneCharacter();
- proceedToBattleButton.SetEnabled(canProceed);
- // Also remove/add visual disabled state
- if (!canProceed)
- {
- proceedToBattleButton.AddToClassList("disabled-button");
- proceedToBattleButton.tooltip = "Create at least one character to proceed";
- }
- else
- {
- proceedToBattleButton.RemoveFromClassList("disabled-button");
- proceedToBattleButton.tooltip = "Start adventure with your team";
- // Force remove any disabled classes that might be interfering
- proceedToBattleButton.RemoveFromClassList("unity-disabled");
- }
- }
- else
- {
- Debug.LogWarning("UpdateNavigationButtons: proceedToBattleButton is null! The button name in the UI might be different than expected.");
- Debug.LogWarning("Please check that a button with name 'ProceedToBattleButton' exists in your UI Document.");
- // Try to find the button again with common alternative names
- var root = uiDocument?.rootVisualElement;
- if (root != null)
- {
- proceedToBattleButton = root.Q<Button>("ProceedButton") ??
- root.Q<Button>("StartButton") ??
- root.Q<Button>("BattleButton") ??
- root.Q<Button>("ProceedToBattleButton");
- if (proceedToBattleButton != null)
- {
- // Recursively call this method now that we found the button
- UpdateNavigationButtons();
- }
- }
- }
- }
- private bool HasAtLeastOneCharacter()
- {
- int characterCount = 0;
- for (int i = 0; i < characterSlots.Length; i++)
- {
- if (characterSlots[i] != null)
- {
- characterCount++;
- }
- else
- {
- }
- }
- bool hasCharacters = characterCount > 0;
- return hasCharacters;
- }
- #endregion
- #region Save/Load Team Data
- private void LoadSavedTeamData()
- {
- // Try to load from GameStateManager first (if available and has data)
- if (GameStateManager.Instance != null && GameStateManager.Instance.savedTeam != null)
- {
- for (int i = 0; i < characterSlots.Length && i < GameStateManager.Instance.savedTeam.Length; i++)
- {
- if (GameStateManager.Instance.savedTeam[i] != null)
- {
- characterSlots[i] = GameStateManager.Instance.savedTeam[i].CreateCopy();
- // Update the slot button
- if (i < characterSlotButtons.Count)
- {
- characterSlotButtons[i].text = characterSlots[i].name;
- characterSlotButtons[i].SetEnabled(true);
- characterSlotButtons[i].RemoveFromClassList("unity-disabled");
- characterSlotButtons[i].RemoveFromClassList("DisabledCharacterCard");
- // Hide the create button
- if (i < createNewCharacterButtons.Count)
- {
- createNewCharacterButtons[i].style.display = DisplayStyle.None;
- }
- }
- }
- }
- }
- // Always also try to load from PlayerPrefs (either as backup or primary)
- for (int i = 0; i < characterSlots.Length; i++)
- {
- // If we haven't loaded this slot from GameStateManager, try PlayerPrefs
- if (characterSlots[i] == null && PlayerPrefs.HasKey($"Character{i}_Exists") && PlayerPrefs.GetInt($"Character{i}_Exists") == 1)
- {
- // Load character data from PlayerPrefs
- characterSlots[i] = LoadCharacterFromPlayerPrefs(i);
- // Update the slot button
- if (i < characterSlotButtons.Count)
- {
- characterSlotButtons[i].text = characterSlots[i].name;
- characterSlotButtons[i].SetEnabled(true);
- characterSlotButtons[i].RemoveFromClassList("unity-disabled");
- characterSlotButtons[i].RemoveFromClassList("DisabledCharacterCard");
- // Hide the create button
- if (i < createNewCharacterButtons.Count)
- {
- createNewCharacterButtons[i].style.display = DisplayStyle.None;
- }
- }
- }
- }
- // Count loaded characters
- int loadedCount = 0;
- for (int i = 0; i < characterSlots.Length; i++)
- {
- if (characterSlots[i] != null) loadedCount++;
- }
- }
- private void SaveCurrentTeamToGameState()
- {
- // Save the current team using PlayerPrefs for now
- for (int i = 0; i < characterSlots.Length; i++)
- {
- if (characterSlots[i] != null)
- {
- SaveCharacterToPlayerPrefs(characterSlots[i], i);
- PlayerPrefs.SetInt($"Character{i}_Exists", 1);
- }
- else
- {
- PlayerPrefs.SetInt($"Character{i}_Exists", 0);
- }
- }
- PlayerPrefs.Save();
- }
- private TeamCharacter LoadCharacterFromPlayerPrefs(int index)
- {
- string prefix = $"Character{index}_";
- var character = new TeamCharacter();
- character.name = PlayerPrefs.GetString(prefix + "Name", "");
- character.isMale = PlayerPrefs.GetInt(prefix + "IsMale", 1) == 1;
- character.strength = PlayerPrefs.GetInt(prefix + "Strength", 10);
- character.dexterity = PlayerPrefs.GetInt(prefix + "Dexterity", 10);
- character.constitution = PlayerPrefs.GetInt(prefix + "Constitution", 10);
- character.wisdom = PlayerPrefs.GetInt(prefix + "Wisdom", 10);
- character.gold = PlayerPrefs.GetInt(prefix + "Gold", 25);
- character.silver = PlayerPrefs.GetInt(prefix + "Silver", 0);
- character.copper = PlayerPrefs.GetInt(prefix + "Copper", 0);
- // Recalculate equipment bonuses from inventory after loading
- character.RecalculateEquipmentBonuses();
- return character;
- }
- private void SaveCharacterToPlayerPrefs(TeamCharacter character, int index)
- {
- string prefix = $"Character{index}_";
- PlayerPrefs.SetString(prefix + "Name", character.name);
- PlayerPrefs.SetInt(prefix + "IsMale", character.isMale ? 1 : 0);
- PlayerPrefs.SetInt(prefix + "Strength", character.strength);
- PlayerPrefs.SetInt(prefix + "Dexterity", character.dexterity);
- PlayerPrefs.SetInt(prefix + "Constitution", character.constitution);
- PlayerPrefs.SetInt(prefix + "Wisdom", character.wisdom);
- PlayerPrefs.SetInt(prefix + "Gold", character.gold);
- PlayerPrefs.SetInt(prefix + "Silver", character.silver);
- PlayerPrefs.SetInt(prefix + "Copper", character.copper);
- // Immediately verify what was saved
- string savedName = PlayerPrefs.GetString(prefix + "Name", "FAILED_TO_SAVE");
- int savedStr = PlayerPrefs.GetInt(prefix + "Strength", -1);
- if (savedName != character.name)
- {
- Debug.LogError($" ERROR: Name save failed! Expected '{character.name}', got '{savedName}'");
- }
- }
- #endregion
- #region Team Finalization
- private bool IsTeamFinalized()
- {
- // Check if the team has been finalized (player clicked "Proceed to Battle" and went to MapScene)
- // This is indicated by TeamSetupComplete being true or HasGeneratedMap being true
- bool hasGeneratedMap = PlayerPrefs.HasKey("HasGeneratedMap") && PlayerPrefs.GetInt("HasGeneratedMap") == 1;
- bool teamSetupCompletePrefs = PlayerPrefs.HasKey("TeamSetupComplete") && PlayerPrefs.GetInt("TeamSetupComplete") == 1;
- bool teamSetupCompleteGameState = false;
- if (GameStateManager.Instance != null)
- {
- teamSetupCompleteGameState = GameStateManager.Instance.teamSetupComplete;
- }
- bool finalized = hasGeneratedMap || teamSetupCompletePrefs || teamSetupCompleteGameState;
- return finalized;
- }
- private void SetTeamFinalizedMode()
- {
- // Disable all character creation and editing
- foreach (var button in createNewCharacterButtons)
- {
- button.SetEnabled(false);
- button.style.opacity = 0.5f;
- button.tooltip = "Team has been finalized - cannot create new characters";
- }
- // Disable character editing fields
- DisableCharacterEditingFields();
- // Change the proceed button to "Return to Adventure"
- if (proceedToBattleButton != null)
- {
- proceedToBattleButton.text = "Return to Adventure";
- proceedToBattleButton.tooltip = "Return to your ongoing adventure";
- }
- // Change the back button to offer new game option
- if (backToTitleButton != null)
- {
- backToTitleButton.text = "New Game";
- backToTitleButton.tooltip = "Start a completely new game (will overwrite current save)";
- }
- // Show a message that team is finalized
- }
- private void DisableCharacterEditingFields()
- {
- // Disable name editing
- if (characterNameField != null)
- {
- characterNameField.SetEnabled(false);
- characterNameField.style.opacity = 0.7f;
- }
- if (randomizeNameButton != null)
- {
- randomizeNameButton.SetEnabled(false);
- randomizeNameButton.style.opacity = 0.5f;
- }
- if (genderDropdown != null)
- {
- genderDropdown.SetEnabled(false);
- genderDropdown.style.opacity = 0.7f;
- }
- // Disable stat editing
- if (strengthField != null) strengthField.SetEnabled(false);
- if (dexterityField != null) dexterityField.SetEnabled(false);
- if (constitutionField != null) constitutionField.SetEnabled(false);
- if (wisdomField != null) wisdomField.SetEnabled(false);
- // Disable attribute buttons
- if (randomizeAttributesButton != null)
- {
- randomizeAttributesButton.SetEnabled(false);
- randomizeAttributesButton.style.opacity = 0.5f;
- }
- if (resetToPointBuyButton != null)
- {
- resetToPointBuyButton.SetEnabled(false);
- resetToPointBuyButton.style.opacity = 0.5f;
- }
- // Disable inventory management
- if (addWeaponButton != null)
- {
- addWeaponButton.SetEnabled(false);
- addWeaponButton.style.opacity = 0.5f;
- }
- if (addArmorButton != null)
- {
- addArmorButton.SetEnabled(false);
- addArmorButton.style.opacity = 0.5f;
- }
- if (addMiscButton != null)
- {
- addMiscButton.SetEnabled(false);
- addMiscButton.style.opacity = 0.5f;
- }
- // Disable bank editing
- if (goldField != null) goldField.SetEnabled(false);
- if (silverField != null) silverField.SetEnabled(false);
- if (copperField != null) copperField.SetEnabled(false);
- }
- #endregion
- private System.Collections.IEnumerator RefreshShopManagerReference()
- {
- // Wait for a short delay to allow for potential late initialization
- yield return new WaitForSeconds(0.1f);
- // Try to find the shop manager again
- var newShopManager = FindFirstObjectByType<SimpleShopManager>();
- if (newShopManager != null)
- {
- shopManager = newShopManager;
- SetupShopManagerCallbacks();
- }
- else
- {
- Debug.LogWarning("Still no SimpleShopManager found after delay. You may need to create one manually using the ShopSystemSetup component.");
- }
- }
- private void SetupShopManagerCallbacks()
- {
- if (shopManager != null)
- {
- // Subscribe to character data changes from the shop
- shopManager.OnCharacterDataChanged += OnShopCharacterDataChanged;
- }
- }
- private void OnShopCharacterDataChanged(TeamCharacter updatedCharacter)
- {
- if (updatedCharacter == null || currentCharacter == null)
- {
- Debug.LogWarning("OnShopCharacterDataChanged: updatedCharacter or currentCharacter is null");
- return;
- }
- // Copy the updated data back to the current character
- // This ensures the character object reference remains the same but data is updated
- currentCharacter.gold = updatedCharacter.gold;
- currentCharacter.silver = updatedCharacter.silver;
- currentCharacter.copper = updatedCharacter.copper;
- // Update inventory lists (create new lists to avoid reference issues)
- currentCharacter.weapons = new System.Collections.Generic.List<string>(updatedCharacter.weapons);
- currentCharacter.armor = new System.Collections.Generic.List<string>(updatedCharacter.armor);
- currentCharacter.miscItems = new System.Collections.Generic.List<string>(updatedCharacter.miscItems);
- // Update the UI to reflect the changes
- UpdateInventoryUI();
- // Save the updated character to the slot
- SaveCurrentCharacterToSlot();
- }
- // Clear all equipment from existing characters to ensure shop-only acquisition
- private void ClearAllCharacterEquipment()
- {
- // Clear equipment from any existing characters in slots
- for (int i = 0; i < characterSlots.Length; i++)
- {
- if (characterSlots[i] != null)
- {
- characterSlots[i].weapons.Clear();
- characterSlots[i].armor.Clear();
- characterSlots[i].miscItems.Clear();
- characterSlots[i].equippedWeapon = "";
- characterSlots[i].equippedArmor = "";
- }
- }
- // Also clear equipment from current character if it exists
- if (currentCharacter != null)
- {
- currentCharacter.weapons.Clear();
- currentCharacter.armor.Clear();
- currentCharacter.miscItems.Clear();
- currentCharacter.equippedWeapon = "";
- currentCharacter.equippedArmor = "";
- }
- }
- }
- [System.Serializable]
- public class TeamCharacter
- {
- public string name = "";
- public bool isMale = true;
- // Base attributes (can be modified by equipment in the future)
- public int strength = 10;
- public int dexterity = 10;
- public int constitution = 10;
- public int wisdom = 10;
- // Character creation mode
- public bool isRandomized = false; // Track if stats were randomized
- public int availablePoints = 18; // Point-buy system (adjusted for 4 stats instead of 6)
- // Equipment modifiers (for future use)
- public int strengthModifier = 0;
- public int dexterityModifier = 0;
- public int constitutionModifier = 0;
- public int wisdomModifier = 0;
- public int acModifier = 0; // Direct AC bonuses from equipment
- // Currency
- public int gold = 25; // Reduced starting money to make shop purchases more strategic
- public int silver = 0;
- public int copper = 0;
- // Equipment/Inventory (simple string-based for now)
- public System.Collections.Generic.List<string> weapons = new System.Collections.Generic.List<string>();
- public System.Collections.Generic.List<string> armor = new System.Collections.Generic.List<string>();
- public System.Collections.Generic.List<string> miscItems = new System.Collections.Generic.List<string>();
- public string equippedWeapon = "";
- public string equippedArmor = "";
- // Final attributes (base + equipment modifiers)
- public int FinalStrength => strength + strengthModifier;
- public int FinalDexterity => dexterity + dexterityModifier;
- public int FinalConstitution => constitution + constitutionModifier;
- public int FinalWisdom => wisdom + wisdomModifier;
- // Derived stats (calculated from final stats)
- public int Initiative => FinalDexterity - 10;
- public int DamageBonus => (FinalStrength - 10) / 2;
- public int SpellAC => FinalWisdom - 10; // Renamed from SpellCastingBonus
- public int MovementSpeed => 30 + (int)(Mathf.Ceil((FinalDexterity - 10) / 5.0f) * 5); // Rounded to closest 5 above
- public int HitPoints => Mathf.Max(10, 10 + (FinalConstitution - 10) * 2 + (FinalStrength - 10) + (FinalDexterity - 10) / 2);
- public int ArmorClass => 10 + (FinalDexterity - 10) / 2 + (FinalConstitution - 10) / 3 + acModifier; // Base 10 + DEX bonus + small CON bonus + equipment AC
- public TeamCharacter()
- {
- // Don't generate random name in constructor to avoid serialization issues
- // Name will be generated explicitly when needed
- }
- public TeamCharacter(string characterName, bool male = true)
- {
- name = characterName;
- isMale = male;
- }
- public void GenerateRandomName()
- {
- // Only generate names when the application is playing to avoid serialization issues
- if (Application.isPlaying)
- {
- name = FantasyNameGenerator.GenerateCharacterName(isMale);
- }
- else
- {
- // Fallback name for serialization/design time
- name = isMale ? "New Male Character" : "New Female Character";
- }
- }
- public void SetGender(bool male)
- {
- isMale = male;
- }
- // Randomize all attributes using point-buy system (18 points)
- public void RandomizeAttributes()
- {
- if (Application.isPlaying)
- {
- // Start with random base values (4-12 range for variety)
- int[] stats = new int[4];
- for (int i = 0; i < 4; i++)
- {
- stats[i] = UnityEngine.Random.Range(4, 13); // Random start between 4-12
- }
- // Calculate how many points we've spent so far
- int pointsSpent = 0;
- for (int i = 0; i < 4; i++)
- {
- pointsSpent += GetStatCost(stats[i]);
- }
- int pointsRemaining = 18 - pointsSpent; // Changed from 27 to 18
- // If we're over budget, reduce some stats
- while (pointsRemaining < 0)
- {
- int randomStat = UnityEngine.Random.Range(0, 4);
- if (stats[randomStat] > 4) // Don't go below 4
- {
- int oldCost = GetStatCost(stats[randomStat]);
- stats[randomStat]--;
- int newCost = GetStatCost(stats[randomStat]);
- pointsRemaining += (oldCost - newCost);
- }
- }
- // Now spend remaining points randomly
- while (pointsRemaining > 0)
- {
- // Pick a random stat to increase
- int randomStat = UnityEngine.Random.Range(0, 4);
- // Check if we can afford to increase this stat
- int currentValue = stats[randomStat];
- if (currentValue >= 18) continue; // Can't go higher than 18
- int currentCost = GetStatCost(currentValue);
- int newCost = GetStatCost(currentValue + 1);
- int costDifference = newCost - currentCost;
- if (pointsRemaining >= costDifference)
- {
- stats[randomStat]++;
- pointsRemaining -= costDifference;
- }
- else
- {
- // If we can't afford any increases, try to find a stat we can afford
- bool foundAffordable = false;
- for (int i = 0; i < 4; i++)
- {
- if (stats[i] < 18)
- {
- int testCurrentCost = GetStatCost(stats[i]);
- int testNewCost = GetStatCost(stats[i] + 1);
- int testCostDiff = testNewCost - testCurrentCost;
- if (pointsRemaining >= testCostDiff)
- {
- foundAffordable = true;
- break;
- }
- }
- }
- // If no affordable increases, break out
- if (!foundAffordable) break;
- }
- }
- // Assign back to properties
- strength = stats[0];
- dexterity = stats[1];
- constitution = stats[2];
- wisdom = stats[3];
- // Set as point-buy mode (not locked like true random)
- isRandomized = false;
- UpdateAvailablePoints();
- }
- } // Alternative: Truly random stats (2-18, locked from editing)
- public void RandomizeAttributesWild()
- {
- if (Application.isPlaying)
- {
- strength = UnityEngine.Random.Range(2, 19); // 2-18 inclusive
- dexterity = UnityEngine.Random.Range(2, 19);
- constitution = UnityEngine.Random.Range(2, 19);
- wisdom = UnityEngine.Random.Range(2, 19);
- isRandomized = true;
- availablePoints = 0; // No points available when randomized
- }
- }
- // Reset attributes to default for point-buy
- public void ResetToPointBuy()
- {
- strength = 10;
- dexterity = 10;
- constitution = 10;
- wisdom = 10;
- isRandomized = false;
- availablePoints = 18; // Reset to full point pool (adjusted for 4 stats)
- }
- // Calculate point cost for a stat value (point-buy system)
- public static int GetStatCost(int statValue)
- {
- // 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
- switch (statValue)
- {
- case 4: return -4;
- case 5: return -2;
- case 6: return -1;
- case 7: return -1;
- case 8: return 0;
- case 9: return 1;
- case 10: return 2;
- case 11: return 3;
- case 12: return 4;
- case 13: return 5;
- case 14: return 7;
- case 15: return 9;
- case 16: return 12;
- case 17: return 16;
- case 18: return 21;
- default: return statValue < 4 ? -4 : 25; // Invalid values
- }
- }
- // Calculate total points spent
- public int GetTotalPointsSpent()
- {
- return GetStatCost(strength) + GetStatCost(dexterity) + GetStatCost(constitution) + GetStatCost(wisdom);
- }
- // Update available points based on current stats
- public void UpdateAvailablePoints()
- {
- if (!isRandomized)
- {
- availablePoints = 18 - GetTotalPointsSpent(); // Changed from 27 to 18
- }
- }
- // Check if we can afford to increase a stat
- public bool CanIncreaseStat(int currentValue)
- {
- if (isRandomized) return false; // Can't change randomized stats
- if (currentValue >= 18) return false; // Max value
- int currentCost = GetStatCost(currentValue);
- int newCost = GetStatCost(currentValue + 1);
- int costDifference = newCost - currentCost;
- return availablePoints >= costDifference;
- }
- // Create a deep copy of this character
- public TeamCharacter CreateCopy()
- {
- var copy = new TeamCharacter(name, isMale)
- {
- strength = this.strength,
- dexterity = this.dexterity,
- constitution = this.constitution,
- wisdom = this.wisdom,
- isRandomized = this.isRandomized,
- availablePoints = this.availablePoints,
- gold = this.gold,
- silver = this.silver,
- copper = this.copper,
- equippedWeapon = this.equippedWeapon,
- equippedArmor = this.equippedArmor
- };
- // Deep copy the lists
- copy.weapons = new System.Collections.Generic.List<string>(this.weapons);
- copy.armor = new System.Collections.Generic.List<string>(this.armor);
- copy.miscItems = new System.Collections.Generic.List<string>(this.miscItems);
- return copy;
- }
- // Recalculate all equipment modifiers from items in inventory (temporary solution)
- public void RecalculateEquipmentBonuses()
- {
- // Reset all modifiers to zero
- strengthModifier = 0;
- dexterityModifier = 0;
- constitutionModifier = 0;
- wisdomModifier = 0;
- acModifier = 0;
- // Get reference to the shop manager to access item definitions
- var shopManager = UnityEngine.Object.FindFirstObjectByType<SimpleShopManager>();
- if (shopManager == null) return;
- // Apply bonuses from all items in inventory
- ApplyBonusesFromItemList(shopManager.weapons, weapons);
- ApplyBonusesFromItemList(shopManager.armor, armor);
- ApplyBonusesFromItemList(shopManager.miscItems, miscItems);
- }
- private void ApplyBonusesFromItemList(System.Collections.Generic.List<SimpleShopItem> shopItems, System.Collections.Generic.List<string> ownedItems)
- {
- foreach (string itemName in ownedItems)
- {
- var shopItem = shopItems.Find(item => item.name == itemName);
- if (shopItem != null && shopItem.stats != null)
- {
- strengthModifier += shopItem.stats.strengthBonus;
- dexterityModifier += shopItem.stats.dexterityBonus;
- constitutionModifier += shopItem.stats.constitutionBonus;
- wisdomModifier += shopItem.stats.wisdomBonus;
- acModifier += shopItem.stats.acBonus;
- }
- }
- }
- // Copy data from another character into this one
- public void CopyFrom(TeamCharacter other)
- {
- if (other == null) return;
- name = other.name;
- isMale = other.isMale;
- strength = other.strength;
- dexterity = other.dexterity;
- constitution = other.constitution;
- wisdom = other.wisdom;
- }
- }
|