Create TurnIntentions

This commit is contained in:
henriquenakashima 2020-09-30 23:56:59 -04:00
parent 838c30af99
commit 94b3309bb7
9 changed files with 181 additions and 32 deletions

View file

@ -39,6 +39,7 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe
private InsightLevel insightLevel; private InsightLevel insightLevel;
private HandPlayability<HeroCard> heroHandPlayability; private HandPlayability<HeroCard> heroHandPlayability;
private HandPlayability<MonsterCard> monsterHandPlayability; private HandPlayability<MonsterCard> monsterHandPlayability;
private TurnIntentions<MonsterCard> monsterIntentions;
private delegate void BattleStateChangedAction(); private delegate void BattleStateChangedAction();
private event BattleStateChangedAction OnBattleStateChanged; private event BattleStateChangedAction OnBattleStateChanged;
@ -137,9 +138,12 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe
this.state, this.monsterEnergy, TeamChoice.Monsters, this.monsterDeck); this.state, this.monsterEnergy, TeamChoice.Monsters, this.monsterDeck);
this.OnBattleStateChanged += this.monsterHandPlayability.NotifyBattleStateChanged; this.OnBattleStateChanged += this.monsterHandPlayability.NotifyBattleStateChanged;
this.monsterIntentions = new TurnIntentions<MonsterCard>(
this.monsterDeck, this.monsterEnergy);
this.battlePlayerControls.Init( this.battlePlayerControls.Init(
this.heroDeck, this.monsterDeck, this.playArea, this.insightLevel, this.heroDeck, this.monsterDeck, this.playArea, this.insightLevel,
this.heroHandPlayability, this.monsterHandPlayability, this.heroHandPlayability, this.monsterHandPlayability, this.monsterIntentions,
this.uiCanvas.transform.localScale.x); this.uiCanvas.transform.localScale.x);
this.insightLevel.OnChanged += this.battlePlayerControls.NotifyInsightLevelChanged; 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) { private void PositionSprite(TeamChoice team, GameObject sprite, int i) {
Vector3 pos; Vector3 pos;
if (team == TeamChoice.Heroes) { 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 { } 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; sprite.transform.position = pos;
} }
@ -211,6 +215,7 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe
private IEnumerator RunHeroTurn() { private IEnumerator RunHeroTurn() {
// Start of hero turn // Start of hero turn
OnBattleStateChanged(); OnBattleStateChanged();
this.monsterIntentions.ResumeIntentions();
foreach (BattleHero hero in this.heroes) { foreach (BattleHero hero in this.heroes) {
hero.ResetBlock(); hero.ResetBlock();
@ -242,6 +247,7 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe
hero.TickStatuses(); hero.TickStatuses();
} }
OnBattleStateChanged(); OnBattleStateChanged();
this.monsterIntentions.PauseIntentions();
} }
private IEnumerator RunMonsterTurn() { private IEnumerator RunMonsterTurn() {
@ -313,11 +319,11 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe
} }
public bool CanUseHeroCard(HeroCard card) { public bool CanUseHeroCard(HeroCard card) {
return this.heroHandPlayability.IsPlayable(card); return this.heroHandPlayability.IsPlayableImmediately(card);
} }
public bool CanUseMonsterCard(MonsterCard card) { public bool CanUseMonsterCard(MonsterCard card) {
return this.monsterHandPlayability.IsPlayable(card); return this.monsterHandPlayability.IsPlayableImmediately(card);
} }
public BattleDeck<HeroCard> GetHeroDeck() { public BattleDeck<HeroCard> GetHeroDeck() {

View file

@ -26,7 +26,8 @@ public class BattlePlayerControls : MonoBehaviour
public void Init( public void Init(
BattleDeck<HeroCard> heroDeck, BattleDeck<MonsterCard> monsterDeck, PlayArea playArea, BattleDeck<HeroCard> heroDeck, BattleDeck<MonsterCard> monsterDeck, PlayArea playArea,
InsightLevel insightLevel, HandPlayability<HeroCard> heroHandPlayability, InsightLevel insightLevel, HandPlayability<HeroCard> heroHandPlayability,
HandPlayability<MonsterCard> monsterHandPlayability, float scale) { HandPlayability<MonsterCard> monsterHandPlayability,
TurnIntentions<MonsterCard> monsterIntentions, float scale) {
this.heroDeck = heroDeck; this.heroDeck = heroDeck;
this.monsterDeck = monsterDeck; this.monsterDeck = monsterDeck;
this.playArea = playArea; this.playArea = playArea;
@ -35,11 +36,12 @@ public class BattlePlayerControls : MonoBehaviour
this.heroHandControls = new HandControls<HeroCard>( this.heroHandControls = new HandControls<HeroCard>(
heroDeck, this.uiCanvas, this.cardPrefab, HandControlsPosition.Bottom, 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.heroHandControls.OnCardClicked += OnHeroCardClicked;
this.monsterHandControls = new HandControls<MonsterCard>( this.monsterHandControls = new HandControls<MonsterCard>(
monsterDeck, this.uiCanvas, this.cardPrefab, HandControlsPosition.Top, 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.monsterHandControls.OnCardClicked += OnMonsterCardClicked;
this.cardsInPlayUIs = new Dictionary<BaseCard, GameObject>(); this.cardsInPlayUIs = new Dictionary<BaseCard, GameObject>();

View file

@ -90,8 +90,10 @@ public class CheatBattle: MonoBehaviour
if (this.lastCommands.EndsWith("win")) { if (this.lastCommands.EndsWith("win")) {
this.OnWinCode(); this.OnWinCode();
this.lastCommands = "";
} else if (this.lastCommands.EndsWith("insight")) { } else if (this.lastCommands.EndsWith("insight")) {
this.OnInsightCode(); this.OnInsightCode();
this.lastCommands = "";
} }
} }
} }

View file

@ -24,11 +24,13 @@ public class HandControls<BaseCardT> where BaseCardT : BaseCard
private TeamChoice team; private TeamChoice team;
private int insightLevel; private int insightLevel;
private HandPlayability<BaseCardT> playability; private HandPlayability<BaseCardT> playability;
private TurnIntentions<BaseCardT> intentions;
private float scale; private float scale;
public HandControls(BattleDeck<BaseCardT> deck, GameObject uiCanvas, GameObject cardPrefab, public HandControls(BattleDeck<BaseCardT> deck, GameObject uiCanvas, GameObject cardPrefab,
HandControlsPosition position, TeamChoice team, int insightLevel, HandControlsPosition position, TeamChoice team, int insightLevel,
HandPlayability<BaseCardT> playability, float scale) { HandPlayability<BaseCardT> playability, TurnIntentions<BaseCardT> intentions,
float scale) {
this.deck = deck; this.deck = deck;
this.uiCanvas = uiCanvas; this.uiCanvas = uiCanvas;
this.cardPrefab = cardPrefab; this.cardPrefab = cardPrefab;
@ -36,6 +38,7 @@ public class HandControls<BaseCardT> where BaseCardT : BaseCard
this.team = team; this.team = team;
this.insightLevel = insightLevel; this.insightLevel = insightLevel;
this.playability = playability; this.playability = playability;
this.intentions = intentions;
this.scale = scale; this.scale = scale;
deck.OnHandPileChanged += this.UpdateState; deck.OnHandPileChanged += this.UpdateState;
@ -43,6 +46,9 @@ public class HandControls<BaseCardT> where BaseCardT : BaseCard
if (playability != null) { if (playability != null) {
playability.OnPlayabilityChanged += this.UpdateState; playability.OnPlayabilityChanged += this.UpdateState;
} }
if (intentions != null) {
intentions.OnIntentionsChanged += this.UpdateState;
}
} }
private Vector3 CalculateHandCardPosition(int index, int count) { private Vector3 CalculateHandCardPosition(int index, int count) {
@ -96,18 +102,36 @@ public class HandControls<BaseCardT> where BaseCardT : BaseCard
private void UpdateState() { private void UpdateState() {
this.hand = this.deck.GetHandPile().ToList(); this.hand = this.deck.GetHandPile().ToList();
RenderHand(); RenderHand();
UpdateCardPlayability(); UpdateCardPlayabilityAndIntentions();
} }
private void UpdateCardPlayability() { private void UpdateCardPlayabilityAndIntentions() {
if (this.hand == null || this.playability == null) { if (this.hand == null) {
return; return;
} }
for (int i = 0; i < this.hand.Count; i++) { for (int i = 0; i < this.hand.Count; i++) {
BaseCardT card = this.hand[i]; BaseCardT card = this.hand[i];
CardUI cardUI = this.cardsInHandUIs[i].GetComponent<CardUI>(); CardUI cardUI = this.cardsInHandUIs[i].GetComponent<CardUI>();
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;
}
}
} }
} }
} }

View file

@ -3,6 +3,13 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using UnityEngine; using UnityEngine;
public enum PlayabilityState {
None,
PlayableImmediately,
PlayableInOwnTurn,
Unplayable,
}
public class HandPlayability<BaseCardT> where BaseCardT : BaseCard { public class HandPlayability<BaseCardT> where BaseCardT : BaseCard {
public delegate void HandPlayabilityChangedAction(); public delegate void HandPlayabilityChangedAction();
public event HandPlayabilityChangedAction OnPlayabilityChanged; public event HandPlayabilityChangedAction OnPlayabilityChanged;
@ -10,7 +17,8 @@ public class HandPlayability<BaseCardT> where BaseCardT : BaseCard {
private EnergyPool energyPool; private EnergyPool energyPool;
private TeamChoice team; private TeamChoice team;
private BattleDeck<BaseCardT> deck; private BattleDeck<BaseCardT> deck;
private Dictionary<BaseCardT, bool> playable = new Dictionary<BaseCardT, bool>(); private Dictionary<BaseCardT, PlayabilityState> playable =
new Dictionary<BaseCardT, PlayabilityState>();
public HandPlayability(BattleState battleState, EnergyPool energyPool, TeamChoice team, public HandPlayability(BattleState battleState, EnergyPool energyPool, TeamChoice team,
BattleDeck<BaseCardT> deck) { BattleDeck<BaseCardT> deck) {
@ -25,11 +33,15 @@ public class HandPlayability<BaseCardT> where BaseCardT : BaseCard {
UpdatePlayability(); UpdatePlayability();
} }
public bool IsPlayable(BaseCardT card) { public bool IsPlayableImmediately(BaseCardT card) {
bool value; return GetCardPlayability(card) == PlayabilityState.PlayableImmediately;
}
public PlayabilityState GetCardPlayability(BaseCardT card) {
PlayabilityState value;
if (!this.playable.TryGetValue(card, out value)) { if (!this.playable.TryGetValue(card, out value)) {
Debug.Log("Card " + card.GetDisplayName() + " not playable because not in hand!"); Debug.Log("Card " + card.GetDisplayName() + " not playable because not in hand!");
return false; return PlayabilityState.None;
} }
return value; return value;
} }
@ -47,19 +59,23 @@ public class HandPlayability<BaseCardT> where BaseCardT : BaseCard {
private void UpdatePlayability() { private void UpdatePlayability() {
this.playable.Clear(); this.playable.Clear();
foreach (BaseCardT card in this.deck.GetHandPile()) { foreach (BaseCardT card in this.deck.GetHandPile()) {
bool canPlay; if (!card.Owner.CanUseCard(card)) {
if (card.Type == CardType.Emotion) { this.playable[card] = PlayabilityState.Unplayable;
canPlay = this.battleState.CanPlayEmotion(this.team); continue;
} else {
canPlay = this.energyPool.CanPayForCard(card);
} }
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(); TriggerOnPlayabilityChanged();
} }
} }

View file

@ -0,0 +1,69 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TurnIntentions<BaseCardT> where BaseCardT: BaseCard
{
public delegate void IntentionsChangedAction();
public event IntentionsChangedAction OnIntentionsChanged;
private BattleDeck<BaseCardT> mDeck;
private EnergyPool mEnergyPool;
private bool mActive;
private List<BaseCardT> mCardsToUse = new List<BaseCardT>();
public TurnIntentions(BattleDeck<BaseCardT> 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<BaseCardT> 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();
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ac905ab14100d5149a5aab79cbd9f325
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -3,6 +3,13 @@ using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
public enum PlayableState {
Unplayable,
Playable,
IntendedToPlay,
}
public class CardUI : MonoBehaviour public class CardUI : MonoBehaviour
{ {
public Text nameText; public Text nameText;
@ -55,11 +62,21 @@ public class CardUI : MonoBehaviour
} }
public bool Playable { public PlayableState State {
set { set {
if (!this.hidden) { if (this.hidden) return;
this.GetComponent<Image>().color = value ? Color.white : Color.grey;
this.artImage.color = value ? Color.white : Color.grey; if (value == PlayableState.Unplayable) {
this.GetComponent<Image>().color = Color.grey;
this.artImage.color = Color.grey;
} else if (value == PlayableState.Playable) {
this.GetComponent<Image>().color = Color.white;
this.artImage.color = Color.white;
} else if (value == PlayableState.IntendedToPlay) {
this.GetComponent<Image>().color = Color.yellow;
this.artImage.color = Color.yellow;
} else {
throw new System.ArgumentException("Unknown PlayableState " + value);
} }
} }
} }

View file

@ -1,7 +1,9 @@
Battle Battle
- Animate rearrange hand after card is used - Animate rearrange hand after card is used
- Do not Highlight unusable cards - 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 - Show on who enemies will use the cards
- Highlight which card is targeting - Highlight which card is targeting
- Allow cancelling targeting - Allow cancelling targeting