Mark cards that are not playable

This commit is contained in:
henriquenakashima 2020-09-24 23:00:36 -04:00
parent aa78658949
commit 45b91ed352
9 changed files with 162 additions and 14 deletions

View file

@ -27,11 +27,15 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe
private Dictionary<BattleMonster, GameObject> monsterSprites;
private Dictionary<BattleMonster, HeroInfoUI> monsterUIs;
private bool heroTurn;
private BattleState state;
private bool heroPassedTurn;
private EnergyPool heroEnergy;
private EnergyPool monsterEnergy;
private InsightLevel insightLevel;
private HandPlayability<HeroCard> heroHandPlayability;
private delegate void BattleStateChangedAction();
private event BattleStateChangedAction OnBattleStateChanged;
void Awake() {
HeroId[] heroIds = new HeroId[3] {
@ -93,6 +97,8 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe
this.heroCardDatabase = new HeroCardDatabase();
this.monsterCardDatabase = new MonsterCardDatabase();
this.state = new BattleState();
this.heroEnergy = new EnergyPool();
this.heroEnergyUI.Init(this.heroEnergy);
this.heroEnergy.OnEnergyChanged += this.heroEnergyUI.NotifyEnergyChanged;
@ -169,14 +175,18 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe
this.monsterCardDatabase, mCardIds.Cast<int>().ToArray(), mCardOwners);
this.playArea = new PlayArea();
this.heroHandPlayability = new HandPlayability<HeroCard>(
this.state, this.heroEnergy, TeamChoice.Heroes, this.heroDeck);
this.battlePlayerControls.Init(
this.heroDeck, this.monsterDeck, this.playArea, this.insightLevel);
this.heroDeck, this.monsterDeck, this.playArea, this.insightLevel,
this.heroHandPlayability);
this.battlePlayerControls.OnCardUsed += this.NotifyHeroCardUsed;
this.battlePlayerControls.OnTurnPassed += this.NotifyHeroTurnPassed;
this.insightLevel.OnChanged += this.battlePlayerControls.NotifyInsightLevelChanged;
this.heroDeck.OnHandPileChanged += this.battlePlayerControls.NotifyHeroHandPileChanged;
this.monsterDeck.OnHandPileChanged += this.battlePlayerControls.NotifyMonsterHandPileChanged;
this.OnBattleStateChanged += this.heroHandPlayability.NotifyBattleStateChanged;
}
private void PositionSprite(TeamChoice team, GameObject sprite, int i) {
@ -214,7 +224,7 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe
}
private IEnumerator RunBattleRound() {
this.heroTurn = true;
this.state.HeroTurn = true;
this.damageTriggers.RemoveAll(t => t.Expiration == TriggerExpiration.StartOfNextHeroTurn);
@ -225,12 +235,13 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe
yield return RunHeroTurn();
this.heroTurn = false;
this.state.HeroTurn = false;
yield return RunMonsterTurn();
}
private IEnumerator RunHeroTurn() {
// Start of hero turn
OnBattleStateChanged();
// TODO: Play emotions from hand
if (this.heroEnergy.MaxEnergy < 9) {
@ -239,6 +250,7 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe
foreach (BattleHero hero in this.heroes) {
hero.ResetBlock();
}
OnBattleStateChanged();
// Heroes act until they pass
while (!this.heroPassedTurn) {
@ -251,9 +263,11 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe
foreach (BattleHero hero in this.heroes) {
hero.TickStatuses();
}
OnBattleStateChanged();
}
private IEnumerator RunMonsterTurn() {
OnBattleStateChanged();
yield return new WaitForSeconds(0.5f);
// Start of monster turn
@ -263,6 +277,7 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe
foreach (BattleMonster monster in this.monsters) {
monster.ResetBlock();
}
OnBattleStateChanged();
// Monsters act until they pass
List<MonsterCard> monsterHand = this.monsterDeck.GetHandPile();
@ -270,6 +285,7 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe
MonsterCard monsterCard = monsterHand[i];
if (CanUseMonsterCard(monsterCard)) {
yield return UseMonsterCard(monsterCard);
OnBattleStateChanged();
}
}
@ -278,6 +294,7 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe
foreach (BattleMonster monster in this.monsters) {
monster.TickStatuses();
}
OnBattleStateChanged();
}
public void NotifyHeroCardUsed(HeroCard card) {
@ -298,6 +315,7 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe
}
yield return new WaitForSeconds(0.5f);
OnBattleStateChanged();
CheckState();
}
@ -316,17 +334,17 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe
}
public void NotifyHeroTurnPassed() {
if (this.heroTurn) {
if (this.state.HeroTurn) {
this.heroPassedTurn = true;
}
}
public bool CanUseHeroCard(HeroCard card) {
return this.heroTurn && card.Owner.CanUseCard(card) && this.heroEnergy.CanPayForCard(card);
return this.heroHandPlayability.IsPlayable(card);
}
public bool CanUseMonsterCard(MonsterCard card) {
return !this.heroTurn && card.Owner.CanUseCard(card) && this.monsterEnergy.CanPayForCard(card);
return !this.state.HeroTurn && card.Owner.CanUseCard(card) && this.monsterEnergy.CanPayForCard(card);
}
public BattleDeck<HeroCard> GetHeroDeck() {

View file

@ -28,15 +28,18 @@ public class BattlePlayerControls : MonoBehaviour
public void Init(
BattleDeck<HeroCard> heroDeck, BattleDeck<MonsterCard> monsterDeck, PlayArea playArea,
InsightLevel insightLevel) {
InsightLevel insightLevel, HandPlayability<HeroCard> heroHandPlayability) {
this.heroDeck = heroDeck;
this.monsterDeck = monsterDeck;
this.playArea = playArea;
this.insightLevel = insightLevel;
this.heroHandControls = new HandControls<HeroCard>(this.uiCanvas, this.cardPrefab, HandControlsPosition.Bottom, int.MaxValue);
this.heroHandControls = new HandControls<HeroCard>(
this.uiCanvas, this.cardPrefab, HandControlsPosition.Bottom, TeamChoice.Heroes,
int.MaxValue, heroHandPlayability);
this.heroHandControls.OnCardClicked += OnHeroCardClicked;
this.monsterHandControls = new HandControls<MonsterCard>(this.uiCanvas, this.cardPrefab, HandControlsPosition.Top, 1);
this.monsterHandControls = new HandControls<MonsterCard>(
this.uiCanvas, this.cardPrefab, HandControlsPosition.Top, TeamChoice.Monsters, 1, null);
this.monsterHandControls.OnCardClicked += OnMonsterCardClicked;
this.cardsInPlayUIs = new Dictionary<BaseCard, GameObject>();

View file

@ -0,0 +1,21 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BattleState
{
// public delegate void BattleStateChangedAction();
// public event BattleStateChangedAction OnBattleStateChanged;
private bool heroTurn;
public bool IsTeamsTurn(TeamChoice team) {
if (team == TeamChoice.Heroes) {
return this.HeroTurn;
} else {
return !this.HeroTurn;
}
}
public bool HeroTurn {get => this.heroTurn; set => this.heroTurn = value;}
}

View file

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

View file

@ -20,19 +20,27 @@ public class HandControls<BaseCardT> where BaseCardT : BaseCard
private List<BaseCardT> hand;
private List<GameObject> cardsInHandUIs;
private TeamChoice team;
private int insightLevel;
private HandPlayability<BaseCardT> playability;
public HandControls(GameObject uiCanvas, GameObject cardPrefab, HandControlsPosition position,
int insightLevel) {
TeamChoice team, int insightLevel, HandPlayability<BaseCardT> playability) {
this.uiCanvas = uiCanvas;
this.cardPrefab = cardPrefab;
this.position = position;
this.team = team;
this.insightLevel = insightLevel;
this.playability = playability;
if (playability != null) {
playability.OnPlayabilityChanged += UpdateCardPlayability;
}
}
public void SetHand(List<BaseCardT> hand) {
this.hand = hand;
DrawHand();
RenderHand();
}
private Vector3 CalculateHandCardPosition(int index, int count) {
@ -51,11 +59,11 @@ public class HandControls<BaseCardT> where BaseCardT : BaseCard
get => this.insightLevel;
set {
this.insightLevel = value;
DrawHand();
RenderHand();
}
}
private void DrawHand() {
private void RenderHand() {
if (this.hand == null) {
return;
}
@ -81,5 +89,18 @@ public class HandControls<BaseCardT> where BaseCardT : BaseCard
int cardIndex = i;
cardUI.GetComponent<Button>().onClick.AddListener(delegate {OnCardClicked(card);});
}
UpdateCardPlayability();
}
private void UpdateCardPlayability() {
if (this.hand == null || this.playability == null) {
return;
}
for (int i = 0; i < this.hand.Count; i++) {
BaseCardT card = this.hand[i];
CardUI cardUI = this.cardsInHandUIs[i].GetComponent<CardUI>();
cardUI.Playable = this.playability.IsPlayable(card);
}
}
}

View file

@ -0,0 +1,58 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class HandPlayability<BaseCardT> where BaseCardT : BaseCard {
public delegate void HandPlayabilityChangedAction();
public event HandPlayabilityChangedAction OnPlayabilityChanged;
private BattleState battleState;
private EnergyPool energyPool;
private TeamChoice team;
private BattleDeck<BaseCardT> deck;
private Dictionary<BaseCardT, bool> playable = new Dictionary<BaseCardT, bool>();
public HandPlayability(BattleState battleState, EnergyPool energyPool, TeamChoice team,
BattleDeck<BaseCardT> deck) {
this.battleState = battleState;
this.energyPool = energyPool;
this.team = team;
this.deck = deck;
deck.OnHandPileChanged += NotifyHeroHandPileChanged;
}
public void NotifyBattleStateChanged() {
UpdatePlayability();
}
public bool IsPlayable(BaseCardT card) {
bool value;
if (!this.playable.TryGetValue(card, out value)) {
Debug.Log("Card " + card.GetDisplayName() + " not playable because not in hand!");
return false;
}
return value;
}
private void TriggerOnPlayabilityChanged() {
if (this.OnPlayabilityChanged != null) {
this.OnPlayabilityChanged();
}
}
private void NotifyHeroHandPileChanged() {
UpdatePlayability();
}
private void UpdatePlayability() {
this.playable.Clear();
foreach (BaseCardT card in this.deck.GetHandPile()) {
this.playable[card] =
this.battleState.IsTeamsTurn(this.team)
&& card.Owner.CanUseCard(card)
&& this.energyPool.CanPayForCard(card);
}
TriggerOnPlayabilityChanged();
}
}

View file

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

View file

@ -36,4 +36,8 @@ public class CardUI : MonoBehaviour
{
}
public bool Playable {
set {this.nameText.color = value ? Color.black : Color.red;}
}
}

View file

@ -2,3 +2,4 @@
- Make hero cards be used in sequence Coroutines, not in parallel
- Do not Highlight unusable cards
- Dim unusable cards
- Extend BattleState to be more than hero turn true/false