267 lines
8.3 KiB
C#
267 lines
8.3 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffectResolver, MonsterViewpoint
|
|
{
|
|
public HeroId[] heroIds;
|
|
public MonsterId[] monsterIds;
|
|
public CardId[] cardIds;
|
|
|
|
public HeroInfoUI heroUIPrefab;
|
|
public GameObject uiCanvas;
|
|
public BattlePlayerControls battlePlayerControls;
|
|
|
|
private HeroDeck heroDeck;
|
|
private PlayArea playArea;
|
|
|
|
public BattleHero[] heroes;
|
|
private GameObject[] heroSprites;
|
|
private HeroInfoUI[] heroUIs;
|
|
|
|
public BattleMonster[] monsters;
|
|
private GameObject[] monsterSprites;
|
|
private HeroInfoUI[] monsterUIs;
|
|
|
|
private bool heroTurn;
|
|
private int maxEnergy;
|
|
private int energy;
|
|
|
|
void Awake() {
|
|
heroes = new BattleHero[3];
|
|
heroSprites = new GameObject[3];
|
|
heroUIs = new HeroInfoUI[3];
|
|
for (int i = 0; i < 3; i++) {
|
|
HeroId id = heroIds[i];
|
|
|
|
heroes[i] = new BattleHero(id);
|
|
heroes[i].Init();
|
|
|
|
heroSprites[i] = HeroDatabase.createHeroSprite(id);
|
|
heroSprites[i].name = "Hero" + i + "_Sprite";
|
|
heroSprites[i].transform.position = new Vector3(-1 + -3 + 3 * i, 0, 0);
|
|
BattleParticipantSprite bps = heroSprites[i].AddComponent<BattleParticipantSprite>();
|
|
bps.Init(battlePlayerControls, heroes[i]);
|
|
bps.OnSpriteClicked += battlePlayerControls.NotifyParticipantSpriteClicked;
|
|
|
|
heroUIs[i] = (HeroInfoUI) Instantiate(heroUIPrefab.gameObject, uiCanvas.transform).GetComponent(typeof(HeroInfoUI));
|
|
heroUIs[i].Init(heroSprites[i], heroes[i]);
|
|
}
|
|
|
|
monsters = new BattleMonster[3];
|
|
monsterSprites = new GameObject[3];
|
|
monsterUIs = new HeroInfoUI[3];
|
|
for (int i = 0; i < 3; i++) {
|
|
MonsterId id = monsterIds[i];
|
|
|
|
monsters[i] = MonsterDatabase.createMonsterScript(id);
|
|
monsters[i].Init();
|
|
|
|
monsterSprites[i] = MonsterDatabase.createMonsterSprite(id);
|
|
monsterSprites[i].name = "Monster" + i + "_Sprite";
|
|
monsterSprites[i].transform.position = new Vector3(+1 + -3 + 3 * i, 3, 0);
|
|
BattleParticipantSprite bps = monsterSprites[i].AddComponent<BattleParticipantSprite>();
|
|
bps.Init(battlePlayerControls, monsters[i]);
|
|
bps.OnSpriteClicked += battlePlayerControls.NotifyParticipantSpriteClicked;
|
|
|
|
monsterUIs[i] = (HeroInfoUI) Instantiate(heroUIPrefab.gameObject, uiCanvas.transform).GetComponent(typeof(HeroInfoUI));
|
|
monsterUIs[i].Init(monsterSprites[i], monsters[i]);
|
|
}
|
|
|
|
BattleParticipant[] cardOwners = new BattleParticipant[this.cardIds.Length];
|
|
for (int i = 0; i < this.cardIds.Length; i++) {
|
|
cardOwners[i] = FindHeroByClass(CardDatabase.GetHeroIdOfCard(this.cardIds[i]));
|
|
}
|
|
this.heroDeck = new HeroDeck(this.cardIds, cardOwners);
|
|
|
|
this.playArea = new PlayArea();
|
|
|
|
this.battlePlayerControls.Init(this.heroDeck, this.playArea);
|
|
this.battlePlayerControls.OnCardUsed += this.NotifyHeroCardUsed;
|
|
this.battlePlayerControls.OnTurnPassed += this.NotifyHeroTurnPassed;
|
|
this.heroDeck.OnHandPileChanged += this.battlePlayerControls.NotifyHandPileChanged;
|
|
}
|
|
|
|
private BattleParticipant FindHeroByClass(HeroId heroId) {
|
|
foreach (BattleHero battleHero in this.heroes) {
|
|
if (battleHero.GetId() == heroId) return battleHero;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// Start is called before the first frame update
|
|
void Start()
|
|
{
|
|
StartHeroTurn();
|
|
}
|
|
|
|
// Update is called once per frame
|
|
void Update()
|
|
{
|
|
}
|
|
|
|
private void StartHeroTurn() {
|
|
this.heroTurn = true;
|
|
|
|
this.damageTriggers.RemoveAll(t => t.Expiration == TriggerExpiration.StartOfNextHeroTurn);
|
|
|
|
this.energy = this.maxEnergy;
|
|
foreach (BattleHero hero in this.heroes) {
|
|
hero.ResetBlock();
|
|
}
|
|
this.heroDeck.DrawHand();
|
|
this.battlePlayerControls.NotifyHandPileChanged();
|
|
|
|
if (this.maxEnergy < 9) {
|
|
this.maxEnergy++;
|
|
this.energy++;
|
|
}
|
|
}
|
|
|
|
private void StartEnemyTurn() {
|
|
this.heroTurn = false;
|
|
|
|
this.heroDeck.DiscardHand();
|
|
|
|
foreach (BattleMonster monster in this.monsters) {
|
|
monster.ResetBlock();
|
|
}
|
|
|
|
MonsterCard card = MonsterCardDatabase.CreateCard(MCardId.VampireFangs, this.monsters[0]);
|
|
StartCoroutine(UseMonsterCard(card));
|
|
|
|
StartHeroTurn();
|
|
}
|
|
|
|
public void NotifyHeroCardUsed(HeroCard card) {
|
|
if (!CanUseHeroCard(card)) {
|
|
throw new System.InvalidOperationException("Cannot use card " + card.GetDisplayName());
|
|
}
|
|
StartCoroutine(UseHeroCard(card));
|
|
}
|
|
|
|
public IEnumerator UseHeroCard(HeroCard card) {
|
|
yield return card.Use(this, battlePlayerControls);
|
|
PayCardCost(card);
|
|
this.heroDeck.RemoveCardFromHand(card);
|
|
if (card.IsPermanent()) {
|
|
this.playArea.AddPlayedHeroPermanent(card);
|
|
} else {
|
|
this.heroDeck.MoveCardToDiscard(card);
|
|
}
|
|
}
|
|
|
|
public IEnumerator UseMonsterCard(MonsterCard card) {
|
|
yield return card.Use(this, this);
|
|
// TODO: Manage monster deck.
|
|
}
|
|
|
|
public void NotifyHeroTurnPassed() {
|
|
if (this.heroTurn) {
|
|
StartEnemyTurn();
|
|
}
|
|
}
|
|
|
|
public bool CanUseHeroCard(HeroCard card) {
|
|
return this.heroTurn && this.energy >= card.GetCost();
|
|
}
|
|
|
|
private void PayCardCost(HeroCard card) {
|
|
this.energy -= card.GetCost();
|
|
}
|
|
|
|
public int GetEnergy() {
|
|
return this.energy;
|
|
}
|
|
|
|
public int GetMaxEnergy() {
|
|
return this.maxEnergy;
|
|
}
|
|
|
|
public HeroDeck GetHeroDeck() {
|
|
return this.heroDeck;
|
|
}
|
|
|
|
public PlayArea GetPlayArea() {
|
|
return this.playArea;
|
|
}
|
|
|
|
private void EnqueueActivatedTrigger(Trigger trigger) {
|
|
this.activatedTriggers.Add(trigger);
|
|
}
|
|
|
|
private void RunActivatedTriggers() {
|
|
foreach (Trigger t in this.activatedTriggers) {
|
|
t.Run(this);
|
|
}
|
|
this.activatedTriggers.Clear();
|
|
|
|
// Cleanup expired triggers
|
|
this.damageTriggers.RemoveAll(t => t.Expired);
|
|
}
|
|
|
|
// IBattleEffectApplier
|
|
public void Apply(IBattleEffect effect) {
|
|
effect.Apply(this);
|
|
}
|
|
|
|
// IBattleEffectResolver
|
|
public void IncreaseHeroMaxEnergy(IncreaseMaxEnergyEffect effect) {
|
|
this.maxEnergy += effect.Amount;
|
|
}
|
|
|
|
public void IncreaseMaxHP(IncreaseMaxHPEffect effect) {
|
|
effect.Target.IncreaseMaxHP(effect.Amount);
|
|
}
|
|
|
|
public void AcquireHeroCards(AcquireCardsEffect effect) {
|
|
BattleHero hero = (BattleHero) effect.Participant;
|
|
foreach (CardId cardId in effect.CardIds) {
|
|
BaseCard acquiredCard = CardDatabase.CreateCard(cardId, hero);
|
|
switch (effect.Zone) {
|
|
case BattleZone.DrawPile:
|
|
this.GetHeroDeck().PutCardOnTopOfDrawPile(acquiredCard);
|
|
break;
|
|
default:
|
|
throw new System.NotImplementedException();
|
|
}
|
|
}
|
|
|
|
if (effect.Zone == BattleZone.DrawPile) {
|
|
this.GetHeroDeck().ShuffleDrawPile();
|
|
}
|
|
}
|
|
|
|
private List<Trigger> activatedTriggers = new List<Trigger>();
|
|
private List<DamageTrigger> damageTriggers = new List<DamageTrigger>();
|
|
|
|
public int DealDamage(DealDamageEffect effect) {
|
|
int damageDealt = effect.Target.DealDamage(effect.Amount);
|
|
foreach (DamageTrigger dt in this.damageTriggers) {
|
|
if (dt.IsTriggeredBy(effect)) {
|
|
EnqueueActivatedTrigger(dt);
|
|
}
|
|
}
|
|
|
|
// Do this after the card resolution is over to avoid reentraint effects.
|
|
RunActivatedTriggers();
|
|
|
|
return damageDealt;
|
|
}
|
|
|
|
public int Heal(HealEffect effect) {
|
|
int healedAmount = effect.Target.Heal(effect.Amount);
|
|
return healedAmount;
|
|
}
|
|
|
|
public void AddBlock(BlockEffect effect) {
|
|
effect.Target.AddBlock(effect.Amount);
|
|
}
|
|
|
|
public void ArmDamageTrigger(DamageTrigger damageTrigger) {
|
|
this.damageTriggers.Add(damageTrigger);
|
|
}
|
|
|
|
// MonsterViewpoint
|
|
public BattleHero[] Heroes {get => this.heroes;}
|
|
}
|