diff --git a/Assets/Battle/BattleController.cs b/Assets/Battle/BattleController.cs index ba4279c..12f0b68 100644 --- a/Assets/Battle/BattleController.cs +++ b/Assets/Battle/BattleController.cs @@ -6,14 +6,14 @@ public class BattleController : MonoBehaviour { public HeroId[] heroIds; public MonsterId[] monsterIds; - public int maxEnergy = 6; + public int maxEnergy; public CardId[] cardIds; public HeroInfoUI heroUIPrefab; public GameObject uiCanvas; public BattlePlayerControls battlePlayerControls; - private List hand; + private HeroDeck heroDeck; public BattleHero[] heroes; private GameObject[] heroSprites; @@ -32,11 +32,7 @@ public class BattleController : MonoBehaviour // Start is called before the first frame update void Start() { - this.hand = new List(); - for (int i = 0; i < cardIds.Length; i++) { - BaseCard newCard = CardDatabase.CreateCard(cardIds[i]); - this.hand.Add(newCard); - } + this.heroDeck = new HeroDeck(cardIds); heroes = new BattleHero[3]; heroSprites = new GameObject[3]; @@ -78,9 +74,10 @@ public class BattleController : MonoBehaviour monsterUIs[i].Init(monsterSprites[i], monsters[i]); } - this.battlePlayerControls.OnCardUsed += this.OnCardUsed; - this.battlePlayerControls.OnTurnPassed += this.OnTurnPassed; - this.battlePlayerControls.SetHand(this.hand); + this.battlePlayerControls.Init(this.heroDeck); + this.battlePlayerControls.OnCardUsed += this.NotifyCardUsed; + this.battlePlayerControls.OnTurnPassed += this.NotifyTurnPassed; + this.heroDeck.OnHandPileChanged += this.battlePlayerControls.NotifyHandPileChanged; DecideEnemyTarget(); StartHeroTurn(); @@ -97,11 +94,15 @@ public class BattleController : MonoBehaviour foreach (BattleHero hero in this.heroes) { hero.ResetBlock(); } + this.heroDeck.DrawHand(); + this.battlePlayerControls.NotifyHandPileChanged(); } private void StartEnemyTurn() { this.heroTurn = false; + this.heroDeck.DiscardHand(); + foreach (BattleMonster monster in this.monsters) { monster.ResetBlock(); } @@ -118,8 +119,8 @@ public class BattleController : MonoBehaviour Debug.Log("Will attack " + this.heroes[this.enemyTarget].GetDisplayName()); } - public void OnCardUsed(BaseCard card) { - Debug.Log("OnCardUsed " + card); + public void NotifyCardUsed(BaseCard card) { + Debug.Log("NotifyCardUsed " + card); if (!CanUseCard(card)) { throw new System.InvalidOperationException("Cannot use card " + card.GetDisplayName()); } @@ -129,11 +130,12 @@ public class BattleController : MonoBehaviour public IEnumerator UseCard(BaseCard card) { yield return card.Use(battlePlayerControls); PayCardCost(card); + this.heroDeck.DiscardPlayedCard(card); } - public void OnTurnPassed() { + public void NotifyTurnPassed() { if (this.heroTurn) { - Debug.Log("OnTurnPassed"); + Debug.Log("NotifyTurnPassed"); StartEnemyTurn(); } } diff --git a/Assets/Battle/BattlePlayerControls.cs b/Assets/Battle/BattlePlayerControls.cs index a2798ee..422f9c8 100644 --- a/Assets/Battle/BattlePlayerControls.cs +++ b/Assets/Battle/BattlePlayerControls.cs @@ -14,9 +14,13 @@ public class BattlePlayerControls : MonoBehaviour public delegate void TurnPassedAction(); public event TurnPassedAction OnTurnPassed; - private List cardsInHand; + private HeroDeck heroDeck; private List cardsInHandUIs; + public void Init(HeroDeck heroDeck) { + this.heroDeck = heroDeck; + } + // Start is called before the first frame update void Start() { @@ -29,7 +33,13 @@ public class BattlePlayerControls : MonoBehaviour } - public void SetHand(List hand) { + private void SetHand(List hand) { + if (this.cardsInHandUIs != null) { + foreach (GameObject cardInHandUI in this.cardsInHandUIs) { + Destroy(cardInHandUI); + } + } + this.cardsInHandUIs = new List(); for (int i = 0; i < hand.Count; i++) { BaseCard card = hand[i]; @@ -87,4 +97,8 @@ public class BattlePlayerControls : MonoBehaviour public bool IsTargeting() { return this.waitingForTarget; } + + public void NotifyHandPileChanged() { + SetHand(this.heroDeck.GetHand()); + } } diff --git a/Assets/Battle/BattleScene.unity b/Assets/Battle/BattleScene.unity index 5dbc922..16933bc 100644 --- a/Assets/Battle/BattleScene.unity +++ b/Assets/Battle/BattleScene.unity @@ -304,7 +304,7 @@ MonoBehaviour: heroIds: 010000000000000002000000 monsterIds: 000000000100000000000000 maxEnergy: 6 - cardIds: 0000000000000000000000000000000001000000 + cardIds: 00000000000000000000000000000000000000000100000001000000010000000100000001000000 heroUIPrefab: {fileID: 6641511084601005557, guid: ef1b469b45cedee418e4c4adf577cd00, type: 3} uiCanvas: {fileID: 35522588} diff --git a/Assets/Battle/HeroDeck.cs b/Assets/Battle/HeroDeck.cs new file mode 100644 index 0000000..b98d364 --- /dev/null +++ b/Assets/Battle/HeroDeck.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class HeroDeck +{ + public const int DEFAULT_HAND_DRAWN = 5; + + public delegate void PileChangedAction(); + public event PileChangedAction OnDrawPileChanged; + public event PileChangedAction OnHandPileChanged; + public event PileChangedAction OnDiscardPileChanged; + + // Piles are sorted from top to bottom. + private List drawPile; + private List handPile; + private List discardPile; + + public HeroDeck(CardId[] cardIds) { + this.drawPile = new List(); + this.handPile = new List(); + this.discardPile = new List(); + + for (int i = 0; i < cardIds.Length; i++) { + BaseCard newCard = CardDatabase.CreateCard(cardIds[i]); + this.drawPile.Add(newCard); + } + this.drawPile.Shuffle(); + } + + public List GetHand() { + return handPile; + } + + public void DrawHand() { + for (int i = 0; i < DEFAULT_HAND_DRAWN; i++) { + DrawCardInternal(); + } + TriggerHandPileChanged(); + TriggerDrawPileChanged(); + } + + public void DrawCard() { + DrawCardInternal(); + TriggerHandPileChanged(); + TriggerDrawPileChanged(); + } + + private void DrawCardInternal() { + if (this.drawPile.Count == 0) { + RemakeDrawPile(); + // If there is still no draw pile, probably because no cards were in the discard pile, just + // skip the draw. + if (this.drawPile.Count == 0) { + return; + } + } + + BaseCard drawnCard = this.drawPile[0]; + this.drawPile.RemoveAt(0); + this.handPile.Add(drawnCard); + } + + public void DiscardPlayedCard(BaseCard card) { + if (!this.handPile.Contains(card)) { + throw new InvalidOperationException("Cannot discard card " + card.GetDisplayName() + + " because not in hand."); + } + + this.discardPile.Insert(0, card); + this.handPile.Remove(card); + TriggerHandPileChanged(); + TriggerDiscardPileChanged(); + } + + public void DiscardHand() { + this.discardPile.InsertRange(0, this.handPile); + this.handPile.Clear(); + TriggerHandPileChanged(); + TriggerDiscardPileChanged(); + } + + private void RemakeDrawPile() { + this.drawPile.AddRange(this.discardPile); + this.discardPile.Clear(); + + this.drawPile.Shuffle(); + TriggerDrawPileChanged(); + TriggerDiscardPileChanged(); + } + + private void TriggerDrawPileChanged() { + if (OnDrawPileChanged != null) OnDrawPileChanged(); + } + private void TriggerHandPileChanged() { + if (OnHandPileChanged != null) OnHandPileChanged(); + } + private void TriggerDiscardPileChanged() { + if (OnDiscardPileChanged != null) OnDiscardPileChanged(); + } +} diff --git a/Assets/Battle/HeroDeck.cs.meta b/Assets/Battle/HeroDeck.cs.meta new file mode 100644 index 0000000..75719d0 --- /dev/null +++ b/Assets/Battle/HeroDeck.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3bbe00a722dbb8641a68911a2b3bf542 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ListShuffle.cs b/Assets/ListShuffle.cs new file mode 100644 index 0000000..e29c4b3 --- /dev/null +++ b/Assets/ListShuffle.cs @@ -0,0 +1,18 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public static class ListShuffle +{ + public static void Shuffle(this IList list) + { + int n = list.Count; + while (n > 1) { + int k = Random.Range(0, n); + n--; + T value = list[k]; + list[k] = list[n]; + list[n] = value; + } + } +} diff --git a/Assets/ListShuffle.cs.meta b/Assets/ListShuffle.cs.meta new file mode 100644 index 0000000..62f6e67 --- /dev/null +++ b/Assets/ListShuffle.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6b9dc1760fb65be41818a2f4372d9c01 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: