diff --git a/Assets/Battle/BattleController.cs b/Assets/Battle/BattleController.cs index a715015..fdc043d 100644 --- a/Assets/Battle/BattleController.cs +++ b/Assets/Battle/BattleController.cs @@ -39,6 +39,7 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe private InsightLevel insightLevel; private HandPlayability heroHandPlayability; private HandPlayability monsterHandPlayability; + private TurnIntentions monsterIntentions; private delegate void BattleStateChangedAction(); private event BattleStateChangedAction OnBattleStateChanged; @@ -137,9 +138,12 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe this.state, this.monsterEnergy, TeamChoice.Monsters, this.monsterDeck); this.OnBattleStateChanged += this.monsterHandPlayability.NotifyBattleStateChanged; + this.monsterIntentions = new TurnIntentions( + this.monsterDeck, this.monsterEnergy); + this.battlePlayerControls.Init( this.heroDeck, this.monsterDeck, this.playArea, this.insightLevel, - this.heroHandPlayability, this.monsterHandPlayability, + this.heroHandPlayability, this.monsterHandPlayability, this.monsterIntentions, this.uiCanvas.transform.localScale.x); this.insightLevel.OnChanged += this.battlePlayerControls.NotifyInsightLevelChanged; } @@ -147,9 +151,9 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe private void PositionSprite(TeamChoice team, GameObject sprite, int i) { Vector3 pos; if (team == TeamChoice.Heroes) { - pos = new Vector3(-1 + -3 + 3 * i, -1.8f, 0); + pos = new Vector3(-0.8f + -3 + 3 * i, -1.8f, 0); } else { - pos = new Vector3(+1 + -3 + 3 * i, 1.2f, 0); + pos = new Vector3(+0.8f + -3 + 3 * i, 1.2f, 0); } sprite.transform.position = pos; } @@ -211,6 +215,7 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe private IEnumerator RunHeroTurn() { // Start of hero turn OnBattleStateChanged(); + this.monsterIntentions.ResumeIntentions(); foreach (BattleHero hero in this.heroes) { hero.ResetBlock(); @@ -242,6 +247,7 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe hero.TickStatuses(); } OnBattleStateChanged(); + this.monsterIntentions.PauseIntentions(); } private IEnumerator RunMonsterTurn() { @@ -313,11 +319,11 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe } public bool CanUseHeroCard(HeroCard card) { - return this.heroHandPlayability.IsPlayable(card); + return this.heroHandPlayability.IsPlayableImmediately(card); } public bool CanUseMonsterCard(MonsterCard card) { - return this.monsterHandPlayability.IsPlayable(card); + return this.monsterHandPlayability.IsPlayableImmediately(card); } public BattleDeck GetHeroDeck() { diff --git a/Assets/Battle/BattlePlayerControls.cs b/Assets/Battle/BattlePlayerControls.cs index 84ec369..277e7ef 100644 --- a/Assets/Battle/BattlePlayerControls.cs +++ b/Assets/Battle/BattlePlayerControls.cs @@ -26,7 +26,8 @@ public class BattlePlayerControls : MonoBehaviour public void Init( BattleDeck heroDeck, BattleDeck monsterDeck, PlayArea playArea, InsightLevel insightLevel, HandPlayability heroHandPlayability, - HandPlayability monsterHandPlayability, float scale) { + HandPlayability monsterHandPlayability, + TurnIntentions monsterIntentions, float scale) { this.heroDeck = heroDeck; this.monsterDeck = monsterDeck; this.playArea = playArea; @@ -35,11 +36,12 @@ public class BattlePlayerControls : MonoBehaviour this.heroHandControls = new HandControls( heroDeck, this.uiCanvas, this.cardPrefab, HandControlsPosition.Bottom, - TeamChoice.Heroes, int.MaxValue, heroHandPlayability, this.scale); + TeamChoice.Heroes, int.MaxValue, heroHandPlayability, null, this.scale); this.heroHandControls.OnCardClicked += OnHeroCardClicked; this.monsterHandControls = new HandControls( monsterDeck, this.uiCanvas, this.cardPrefab, HandControlsPosition.Top, - TeamChoice.Monsters, insightLevel.Level, monsterHandPlayability, this.scale); + TeamChoice.Monsters, insightLevel.Level, monsterHandPlayability, monsterIntentions, + this.scale); this.monsterHandControls.OnCardClicked += OnMonsterCardClicked; this.cardsInPlayUIs = new Dictionary(); diff --git a/Assets/Battle/CheatBattle.cs b/Assets/Battle/CheatBattle.cs index 557c925..7b080c0 100644 --- a/Assets/Battle/CheatBattle.cs +++ b/Assets/Battle/CheatBattle.cs @@ -90,8 +90,10 @@ public class CheatBattle: MonoBehaviour if (this.lastCommands.EndsWith("win")) { this.OnWinCode(); + this.lastCommands = ""; } else if (this.lastCommands.EndsWith("insight")) { this.OnInsightCode(); + this.lastCommands = ""; } } } diff --git a/Assets/Battle/HandControls.cs b/Assets/Battle/HandControls.cs index eb1abcb..64ac18c 100644 --- a/Assets/Battle/HandControls.cs +++ b/Assets/Battle/HandControls.cs @@ -24,11 +24,13 @@ public class HandControls where BaseCardT : BaseCard private TeamChoice team; private int insightLevel; private HandPlayability playability; + private TurnIntentions intentions; private float scale; public HandControls(BattleDeck deck, GameObject uiCanvas, GameObject cardPrefab, HandControlsPosition position, TeamChoice team, int insightLevel, - HandPlayability playability, float scale) { + HandPlayability playability, TurnIntentions intentions, + float scale) { this.deck = deck; this.uiCanvas = uiCanvas; this.cardPrefab = cardPrefab; @@ -36,6 +38,7 @@ public class HandControls where BaseCardT : BaseCard this.team = team; this.insightLevel = insightLevel; this.playability = playability; + this.intentions = intentions; this.scale = scale; deck.OnHandPileChanged += this.UpdateState; @@ -43,6 +46,9 @@ public class HandControls where BaseCardT : BaseCard if (playability != null) { playability.OnPlayabilityChanged += this.UpdateState; } + if (intentions != null) { + intentions.OnIntentionsChanged += this.UpdateState; + } } private Vector3 CalculateHandCardPosition(int index, int count) { @@ -96,18 +102,36 @@ public class HandControls where BaseCardT : BaseCard private void UpdateState() { this.hand = this.deck.GetHandPile().ToList(); RenderHand(); - UpdateCardPlayability(); + UpdateCardPlayabilityAndIntentions(); } - private void UpdateCardPlayability() { - if (this.hand == null || this.playability == null) { + private void UpdateCardPlayabilityAndIntentions() { + if (this.hand == null) { return; } for (int i = 0; i < this.hand.Count; i++) { BaseCardT card = this.hand[i]; CardUI cardUI = this.cardsInHandUIs[i].GetComponent(); - cardUI.Playable = this.playability.IsPlayable(card); + PlayabilityState cardPlayability = this.playability.GetCardPlayability(card); + if (this.intentions == null) { + if (cardPlayability == PlayabilityState.PlayableImmediately) { + cardUI.State = PlayableState.Playable; + } else { + cardUI.State = PlayableState.Unplayable; + } + } else { + if (cardPlayability == PlayabilityState.PlayableImmediately + || cardPlayability == PlayabilityState.PlayableInOwnTurn) { + if (this.intentions.WillUseCard(card)) { + cardUI.State = PlayableState.IntendedToPlay; + } else { + cardUI.State = PlayableState.Playable; + } + } else { + cardUI.State = PlayableState.Unplayable; + } + } } } } diff --git a/Assets/Battle/HandPlayability.cs b/Assets/Battle/HandPlayability.cs index 9ce8ae6..64d55f4 100644 --- a/Assets/Battle/HandPlayability.cs +++ b/Assets/Battle/HandPlayability.cs @@ -3,6 +3,13 @@ using System.Collections.Generic; using System.Linq; using UnityEngine; +public enum PlayabilityState { + None, + PlayableImmediately, + PlayableInOwnTurn, + Unplayable, +} + public class HandPlayability where BaseCardT : BaseCard { public delegate void HandPlayabilityChangedAction(); public event HandPlayabilityChangedAction OnPlayabilityChanged; @@ -10,7 +17,8 @@ public class HandPlayability where BaseCardT : BaseCard { private EnergyPool energyPool; private TeamChoice team; private BattleDeck deck; - private Dictionary playable = new Dictionary(); + private Dictionary playable = + new Dictionary(); public HandPlayability(BattleState battleState, EnergyPool energyPool, TeamChoice team, BattleDeck deck) { @@ -25,11 +33,15 @@ public class HandPlayability where BaseCardT : BaseCard { UpdatePlayability(); } - public bool IsPlayable(BaseCardT card) { - bool value; + public bool IsPlayableImmediately(BaseCardT card) { + return GetCardPlayability(card) == PlayabilityState.PlayableImmediately; + } + + public PlayabilityState GetCardPlayability(BaseCardT card) { + PlayabilityState value; if (!this.playable.TryGetValue(card, out value)) { Debug.Log("Card " + card.GetDisplayName() + " not playable because not in hand!"); - return false; + return PlayabilityState.None; } return value; } @@ -47,19 +59,23 @@ public class HandPlayability where BaseCardT : BaseCard { private void UpdatePlayability() { this.playable.Clear(); foreach (BaseCardT card in this.deck.GetHandPile()) { - bool canPlay; - if (card.Type == CardType.Emotion) { - canPlay = this.battleState.CanPlayEmotion(this.team); - } else { - canPlay = this.energyPool.CanPayForCard(card); + if (!card.Owner.CanUseCard(card)) { + this.playable[card] = PlayabilityState.Unplayable; + continue; } - canPlay = canPlay - && this.battleState.IsTeamsTurn(this.team) - && card.Owner.CanUseCard(card); - this.playable[card] = canPlay; + bool canPlayNow = this.battleState.IsTeamsTurn(this.team); + if (card.Type == CardType.Emotion) { + canPlayNow = canPlayNow && this.battleState.CanPlayEmotion(this.team); + } else { + canPlayNow = canPlayNow && this.energyPool.CanPayForCard(card); + } + if (canPlayNow) { + this.playable[card] = PlayabilityState.PlayableImmediately; + } else { + this.playable[card] = PlayabilityState.PlayableInOwnTurn; + } } TriggerOnPlayabilityChanged(); - } } diff --git a/Assets/Battle/TurnIntentions.cs b/Assets/Battle/TurnIntentions.cs new file mode 100644 index 0000000..c526e01 --- /dev/null +++ b/Assets/Battle/TurnIntentions.cs @@ -0,0 +1,69 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class TurnIntentions where BaseCardT: BaseCard +{ + public delegate void IntentionsChangedAction(); + public event IntentionsChangedAction OnIntentionsChanged; + + private BattleDeck mDeck; + private EnergyPool mEnergyPool; + private bool mActive; + private List mCardsToUse = new List(); + + public TurnIntentions(BattleDeck deck, EnergyPool energyPool) { + mDeck = deck; + mEnergyPool = energyPool; + mActive = true; + + mDeck.OnDrawPileChanged += OnDependencyChanged; + mEnergyPool.OnEnergyChanged += OnDependencyChanged; + } + + public void ResumeIntentions() { + mActive = true; + UpdateState(); + TriggerOnIntentionsChanged(); + } + + public void PauseIntentions() { + mActive = false; + mCardsToUse.Clear(); + TriggerOnIntentionsChanged(); + } + + private void OnDependencyChanged() { + if (mActive) { + UpdateState(); + TriggerOnIntentionsChanged(); + } + } + + public bool WillUseCard(BaseCardT card) { + return mCardsToUse.Contains(card); + } + + private void UpdateState() { + int projectedEnergy = mEnergyPool.Energy; + // TODO: Account for emotions + + mCardsToUse.Clear(); + + List hand = mDeck.GetHandPile(); + for (int i = 0; i < hand.Count; i++) { + BaseCardT card = hand[i]; + if (card.Owner.CanUseCard(card) + && projectedEnergy >= card.GetCost()) { + projectedEnergy -= card.GetCost(); + mCardsToUse.Add(card); + } + } + } + + private void TriggerOnIntentionsChanged() { + if (OnIntentionsChanged != null) { + OnIntentionsChanged(); + } + } +} diff --git a/Assets/Battle/TurnIntentions.cs.meta b/Assets/Battle/TurnIntentions.cs.meta new file mode 100644 index 0000000..f89d398 --- /dev/null +++ b/Assets/Battle/TurnIntentions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ac905ab14100d5149a5aab79cbd9f325 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Battle/UI/CardUI.cs b/Assets/Battle/UI/CardUI.cs index 5cda27d..6a2a277 100644 --- a/Assets/Battle/UI/CardUI.cs +++ b/Assets/Battle/UI/CardUI.cs @@ -3,6 +3,13 @@ using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; + +public enum PlayableState { + Unplayable, + Playable, + IntendedToPlay, +} + public class CardUI : MonoBehaviour { public Text nameText; @@ -55,11 +62,21 @@ public class CardUI : MonoBehaviour } - public bool Playable { + public PlayableState State { set { - if (!this.hidden) { - this.GetComponent().color = value ? Color.white : Color.grey; - this.artImage.color = value ? Color.white : Color.grey; + if (this.hidden) return; + + if (value == PlayableState.Unplayable) { + this.GetComponent().color = Color.grey; + this.artImage.color = Color.grey; + } else if (value == PlayableState.Playable) { + this.GetComponent().color = Color.white; + this.artImage.color = Color.white; + } else if (value == PlayableState.IntendedToPlay) { + this.GetComponent().color = Color.yellow; + this.artImage.color = Color.yellow; + } else { + throw new System.ArgumentException("Unknown PlayableState " + value); } } } diff --git a/TODO.txt b/TODO.txt index f666d54..09e8970 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,7 +1,9 @@ Battle - Animate rearrange hand after card is used - Do not Highlight unusable cards -- Show which cards enemies will use ++ Make enemies play energy before anything else ++ Limit intentions to drop one energy ++ Account for one dropped energy in intentions - Show on who enemies will use the cards - Highlight which card is targeting - Allow cancelling targeting