//init public IEnumerator Start() { //wait for card type manager to be ready while ((CardTypeManagerScript.instance == null) || (CardTypeManagerScript.instance.areTypesLoaded() == false)) { yield return(null); } unsavedChanges = false; //there are no changes since we just opened the editor XMLDeck openDeck = new XMLDeck(); //create a new deck newDeck = true; //flag the deck as new //default search filter settings filter = new DeckEditorFilter(); filter.searchString = null; filter.type = null; filter.sortBy = DeckEditorFilter.SortingRule.name; filter.baseCards = true; filter.moddedCards = true; BroadcastMessage("filterChanged", filter); //report the new filter settings to children BroadcastMessage("refresh", openDeck); //update interfaces //give things a few frames to stabilize yield return(null); yield return(null); yield return(null); GetComponent <VerticalLayoutGroup>().enabled = false; //disable the layout group on this since it doesnt need to change anymore and its recalculations are slow }
/// <summary> /// Sets the currentDeck based on the XMLDeck /// note that this does NOT shuffle the deck, since there are (rare) instances where this should not happen /// </summary> /// <seealso cref="Shuffle"/> public void SetDeck(XMLDeck newDeck) { //init currentDeckName = newDeck.name; maxDeckCharges = 0; //for each card on the list of cards in the deck... foreach (XMLDeckEntry xde in newDeck.contents) { PlayerCardData type = CardTypeManagerScript.instance.getCardByName(xde.name); //for each individual card to be added... for (int i = 0; i < xde.count; i++) { //setup the data PlayerCard c; c.data = type; c.charges = type.cardMaxCharges; //count the charges maxDeckCharges += type.cardMaxCharges; //and put it in currentDeck.Add(c); } } curDeckCharges = maxDeckCharges; //the deck starts full, so all charges are present deckSize = cardsLeft; }
/// <summary> /// returns the deck of the given name, if it exists /// if it does not exist, a default is returned and produces a warning /// </summary> /// <param name="targetDeck"></param> public XMLDeck getDeckByName(string targetDeck) { //find the deck XMLDeck result = null; foreach (XMLDeck xDeck in decks) { if (xDeck.name == targetDeck) { result = xDeck; break; } } //if the deck did not exist, use a default deck and print a warning if (result == null) { Debug.LogWarning("Deck " + targetDeck + " could not be found. Using a default deck instead"); result = new XMLDeck(); result.contents = new List <XMLDeckEntry>(); result.contents.Add(new XMLDeckEntry("Basic Tower", 60)); } //return the result return(result); }
//handles buttons in the deck list public void DeckSelected(XMLDeck selectedDeck) { //user wants to load a different deck saveChanges(); //save any unsaved changes openDeck = selectedDeck; //change decks newDeck = false; //this deck was loaded from disk, so it is not new BroadcastMessage("refresh", openDeck); //update the menus to reflect it }
//called when the deck changes. Fill the text field with the name of said deck public void refresh(XMLDeck deck) { if (deck == null) { inputField.text = ""; } else { inputField.text = deck.name; } }
//adds card entries to the list. If the card type is in highlightDeck, that button is a different color private void setupTypeEntries(XMLDeck highlightDeck) { //if a filter is set, operate on a list sorted and filtered according to the current settings instead of the full list List <PlayerCardData> listToShow = CardTypeManagerScript.instance.types.cardTypes; if (filter != null) { listToShow = filter.filterAndSortCardData(listToShow); } //one entry for each card type foreach (PlayerCardData type in listToShow) { //skip tokens if (type.isToken) { continue; } //create the button and add it to the list DeckEditorCardTypeEntryScript xButton = Instantiate(entryPrefab).GetComponent <DeckEditorCardTypeEntryScript>(); xButton.setCard(type); xButton.transform.SetParent(this.transform, false); buttons.Add(xButton); //set its color based on its type Color buttonColor; switch (type.cardType) { case PlayerCardType.tower: buttonColor = towerColor; break; case PlayerCardType.upgrade: buttonColor = upgradeColor; break; case PlayerCardType.spell: buttonColor = spellColor; break; default: Debug.LogWarning("card type list doesnt know what color to use for this card."); buttonColor = Color.black; break; } //highlight if it is in the deck if (highlightDeck != null) { foreach (XMLDeckEntry e in highlightDeck.contents) { if (e.name == type.cardName) { buttonColor = Color.Lerp(buttonColor, highlightColor, 0.5f); break; } } } xButton.setColor(buttonColor); } }
/// <summary> /// returns a new XMLDeck from randomly chosen cards /// the deck will contain from 30-60 cards, and each card type can appear 1-5 times. /// will not include modded cards. /// </summary> /// <returns>the new deck</returns> public XMLDeck generateRandomDeck() { int targetCardCount = UnityEngine.Random.Range(30, 61); //.Range() excludes upper bound, so this is actually 30-60 inclusive. XMLDeck randomDeck = new XMLDeck(); randomDeck.name = "randomly generated"; //while there is still room in the deck, add more cards. while (randomDeck.cardCount < targetCardCount) { //start by picking a card type at random PlayerCardData card = CardTypeManagerScript.instance.getRandomCardType(); //skip tokens if (card.isToken) { continue; } //skip modded cards if (card.isModded) { continue; } //skip it if it is already in the deck if (randomDeck.contents.Any(xde => xde.name == card.cardName)) { continue; } //it is not in the deck, so add 1-5 of it int amount = UnityEngine.Random.Range(1, 6); //.Range() excludes upper bound, so this is actually 1-5 inclusive amount = Math.Min(amount, (targetCardCount - randomDeck.cardCount)); //do not exceed target card count randomDeck.contents.Add(new XMLDeckEntry(card.cardName, amount)); } //throw error if the deck is invalid or the wrong size Debug.Assert(randomDeck.isValid(), "Generated deck invalid"); Debug.Assert(randomDeck.cardCount == targetCardCount, "Generated deck wrong size"); return(randomDeck); //done }
//handles all buttons in the editor that only have text attached. public void TextButtonSelected(string text) { //Debug.Log("TextButtonSelected"); //DEBUG ONLY //text contains the text of the button that was clicked, so we use a case statement to differentiate between buttons switch (text) { case "-": //this is a stray message actually intended for DeckEditorCurrentDeckScript, so we can ignore it break; case "+": //this is a stray message actually intended for DeckEditorCurrentDeckScript, so we can ignore it break; case "New Deck": //user wants to make a new deck saveChanges(); //save any unsaved changes openDeck = new XMLDeck(); //make a new deck newDeck = true; //flag this deck as new so that any changes to it get saved as a new deck BroadcastMessage("refresh", openDeck); //inform the lists break; case "Save and return to menu": //user wants to close the editor saveChanges(); //save any unsaved changes SceneManager.LoadScene("Game"); //go back to the game scene break; case "Generate Random Deck": //user wants to get a randomly created deck unsavedChanges = true; //there are no unsaved changes openDeck = DeckManagerScript.instance.generateRandomDeck(); //make a new deck newDeck = true; //flag it as new so that any changes to it get saved as a new deck BroadcastMessage("refresh", openDeck); //show the new deck break; case "Settings": //player wants to see the settings menu StartCoroutine(MessageHandlerScript.ShowSettingsMenu()); break; default: //button has not been implemented. Print warning. Debug.LogError("DeckEditorMainScript doesn't know how to respond to this button"); break; } }
//refreshes the list, highlighting the current deck void refresh(XMLDeck currentDeck) { //remove all deck buttons that no longer have a corresponding deck foreach (MenuButtonScript toRemove in buttons.FindAll(mb => (mb.buttonType == MenuButtonType.deck) && (DeckManagerScript.instance.playerDecks.decks.Contains(mb.xDeck) == false))) { buttons.Remove(toRemove); Destroy(toRemove.gameObject); } //create buttons for decks that do not have a corresponding button foreach (XMLDeck newDeck in DeckManagerScript.instance.playerDecks.decks) { if (buttons.Any(mb => mb.xDeck == newDeck) == false) { MenuButtonScript xButton = Instantiate(buttonPrefab).GetComponent <MenuButtonScript>(); xButton.SendMessage("setDeck", newDeck); //set button color Color targetColor; if (newDeck.isModded()) { targetColor = moddedColor; } else { targetColor = defaultColor; } if (newDeck == currentDeck) { targetColor = Color.Lerp(targetColor, highlightColor, 0.5f); } xButton.setColor(targetColor); xButton.transform.SetParent(this.transform, false); buttons.Add(xButton); } } }
//called when the deck updates public void refresh(XMLDeck openDeck) { int cardCount = 0; if (openDeck != null) { cardCount = openDeck.cardCount; } text.text = "min/cur/max\n"; if (cardCount < DeckRules.MIN_CARDS_IN_DECK) { text.text += "<Color=red> "; } else { text.text += "<Color=green> "; } text.text += DeckRules.MIN_CARDS_IN_DECK + " </Color>/ "; if ((DeckRules.MIN_CARDS_IN_DECK <= cardCount) && (cardCount <= DeckRules.MAX_CARDS_IN_DECK)) { text.text += "<Color=green> "; } else { text.text += "<Color=red> "; } text.text += cardCount + " </Color>/ "; if (cardCount > DeckRules.MAX_CARDS_IN_DECK) { text.text += "<Color=red> "; } else { text.text += "<Color=black> "; } text.text += DeckRules.MAX_CARDS_IN_DECK + " </Color>"; }
//adds deck buttons to the list. If highlightDeck is in the list, that button is a different color void setupDeckButtons(XMLDeck highlightDeck) { //one button for each player deck foreach (XMLDeck xDeck in DeckManagerScript.instance.playerDecks.decks) { MenuButtonScript xButton = Instantiate(buttonPrefab).GetComponent <MenuButtonScript>(); xButton.setDeck(xDeck); //set button color Color targetColor; if (xDeck.isModded()) { targetColor = moddedColor; } else { targetColor = defaultColor; } if (xDeck == highlightDeck) { targetColor = Color.Lerp(targetColor, highlightColor, 0.5f); } xButton.setColor(targetColor); xButton.transform.SetParent(this.transform, false); buttons.Add(xButton); } //another button for making a new deck MenuButtonScript ndButton = Instantiate(buttonPrefab).GetComponent <MenuButtonScript>(); ndButton.setButtonText("New Deck"); ndButton.setColor(menuColor); ndButton.transform.SetParent(this.transform, false); buttons.Add(ndButton); }
/// <summary> /// reloads the deck lists, empties out the deck, and then reloads it /// </summary> private void Reset() { //premade decks if (Application.platform == RuntimePlatform.WebGLPlayer) { StartCoroutine(loadPremadeDecksWeb()); //web player has to use a coroutine for this because it waits for a web request } else { //PC build, however, can load them right here string filePath = Path.Combine(Application.streamingAssetsPath, premadeDeckPath); using (FileStream stream = new FileStream(filePath, FileMode.Open)) premadeDecks = DeckCollection.Load(stream, filePath); } //load player decks if the file exists, or create an empty collection if not try { string filePath = Path.Combine(Application.persistentDataPath, "playerDecks.xml"); using (FileStream stream = new FileStream(filePath, FileMode.Open)) playerDecks = DeckCollection.Load(stream, filePath); } catch (Exception e) { Debug.Log("no deck save file found. (" + e.Message + ")"); playerDecks = new DeckCollection(); } //clear out the current deck currentDeck.Clear(); if (LevelManagerScript.instance.data.usingLevelDeck) { //if we were using the level deck, reload that LevelManagerScript.instance.loadLevelDeck(); //this delegates to level manager so that it can retain control over the level data } else { //otherwise, the player picked a deck. Search the deck lists for a deck of the same name as what we're using and load that. XMLDeck target = null; //deck to reload if (premadeDecks.getNames().Contains(currentDeckName)) { target = premadeDecks.getDeckByName(currentDeckName); } if (playerDecks.getNames().Contains(currentDeckName)) { if (target != null) { Debug.LogError("both deck lists contain a deck of the same name! Unsure which to reload."); } else { target = playerDecks.getDeckByName(currentDeckName); } } if (target == null) { Debug.LogError("could not find the deck to reload it!"); } SetDeck(target); Shuffle(); } }
//sets the deck public void SetDeck(XMLDeck deck) { data = deck; destroyDeckEntries(); setupDeckEntries(); }
//refreshes the list. If deck is not null, also sets that as the new deck public void refresh(XMLDeck deck) { if (deck != null) { data = deck; } //update existing entries as needed and keep a list of which ones no longer exist List <DeckEditorCurrentDeckEntryScript> toRemove = new List <DeckEditorCurrentDeckEntryScript>(); foreach (DeckEditorCurrentDeckEntryScript entry in deckEntries) { XMLDeckEntry xde = data.contents.FirstOrDefault(x => x.name == entry.cardName); if (xde != null) { //this entry still corresponds to a card that is in the deck. Update it //update count if (entry.cardCount != xde.count) { entry.cardCount = xde.count; } //figure out what color it should be Color buttonColor; switch (CardTypeManagerScript.instance.getCardByName(xde.name).cardType) { case PlayerCardType.tower: buttonColor = towerColor; break; case PlayerCardType.upgrade: buttonColor = upgradeColor; break; case PlayerCardType.spell: buttonColor = spellColor; break; default: Debug.LogWarning("current deck list doesnt know what color to use for this card. (" + xde.name + ")"); buttonColor = Color.black; break; } //highlight if it does not match the current filter if (filter != null) { if (filter.match(xde) == false) { buttonColor = Color.Lerp(buttonColor, highlightColor, 0.5f); } } //update color entry.setColor(buttonColor); } else { //the card for this entry is no longer in the deck toRemove.Add(entry); } } //get rid of the ones that no longer exist foreach (DeckEditorCurrentDeckEntryScript e in toRemove) { deckEntries.Remove(e); Destroy(e.gameObject); } //create new entries for cards that dont have them yet foreach (XMLDeckEntry xEntry in data.contents) { if (deckEntries.Any(de => de.cardName == xEntry.name) == false) { //create the entry and add it to the list DeckEditorCurrentDeckEntryScript entry = Instantiate(currentDeckEntryPrefab).GetComponent <DeckEditorCurrentDeckEntryScript>(); entry.setData(xEntry); entry.transform.SetParent(this.transform, false); deckEntries.Add(entry); //set its color based on its type Color buttonColor; switch (CardTypeManagerScript.instance.getCardByName(xEntry.name).cardType) { case PlayerCardType.tower: buttonColor = towerColor; break; case PlayerCardType.upgrade: buttonColor = upgradeColor; break; case PlayerCardType.spell: buttonColor = spellColor; break; default: Debug.LogWarning("current deck list doesnt know what color to use for this card. (" + xEntry.name + ")"); buttonColor = Color.black; break; } //highlight if it does not match the current filter if (filter != null) { if (filter.match(xEntry) == false) { buttonColor = Color.Lerp(buttonColor, highlightColor, 0.5f); } } entry.setColor(buttonColor); } } }
//refreshes the list, highlighting the current deck public void refresh(XMLDeck currentDeck) { //if a filter is set, operate on a list sorted and filtered according to the current settings instead of the full list List <PlayerCardData> listToShow = CardTypeManagerScript.instance.types.cardTypes; if (filter != null) { listToShow = filter.filterAndSortCardData(listToShow); } //dont include tokens listToShow.RemoveAll(pcd => pcd.isToken); //create/remove entries as needed so that we have as many as we need to show. data will be set in a second pass. while (buttons.Count < listToShow.Count) { DeckEditorCardTypeEntryScript newButton = Instantiate(entryPrefab).GetComponent <DeckEditorCardTypeEntryScript>(); newButton.transform.SetParent(this.transform, false); buttons.Add(newButton); } while (buttons.Count > listToShow.Count) { DeckEditorCardTypeEntryScript toRemove = buttons[0]; buttons.Remove(toRemove); Destroy(toRemove.gameObject); } //update entries for (int i = 0; i < buttons.Count; i++) { //ensure it has the right data if (buttons[i].type != listToShow[i]) { buttons[i].setCard(listToShow[i]); } //set its color based on its type Color buttonColor; switch (buttons[i].type.cardType) { case PlayerCardType.tower: buttonColor = towerColor; break; case PlayerCardType.upgrade: buttonColor = upgradeColor; break; case PlayerCardType.spell: buttonColor = spellColor; break; default: Debug.LogWarning("card type list doesnt know what color to use for this card."); buttonColor = Color.black; break; } //highlight if it is in the deck if (currentDeck != null) { if (currentDeck.contents.Any(xde => xde.name == buttons[i].type.cardName)) { buttonColor = Color.Lerp(buttonColor, highlightColor, 0.5f); } } buttons[i].setColor(buttonColor); } }
/// <summary> /// the button is set up to correspond to the given XMLDeck /// </summary> public void setDeck(XMLDeck newXDeck) { xDeck = newXDeck; //set deck buttonText.text = xDeck.name; buttonType = MenuButtonType.deck; }