Implement statuses, GolemCharge, GolemBerserk, stun
This commit is contained in:
parent
caf782c884
commit
ef9ec43c8a
16 changed files with 260 additions and 38 deletions
|
|
@ -175,6 +175,9 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe
|
|||
|
||||
// End of hero turn
|
||||
this.heroDeck.DiscardHand();
|
||||
foreach (BattleHero hero in this.heroes) {
|
||||
hero.TickStatuses();
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator RunMonsterTurn() {
|
||||
|
|
@ -199,6 +202,9 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe
|
|||
|
||||
// End of monster turn
|
||||
this.monsterDeck.DiscardHand();
|
||||
foreach (BattleMonster monster in this.monsters) {
|
||||
monster.TickStatuses();
|
||||
}
|
||||
}
|
||||
|
||||
public void NotifyHeroCardUsed(HeroCard card) {
|
||||
|
|
@ -243,11 +249,11 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe
|
|||
}
|
||||
|
||||
public bool CanUseHeroCard(HeroCard card) {
|
||||
return this.heroTurn && card.Owner.IsAlive() && this.heroEnergy.CanPayForCard(card);
|
||||
return this.heroTurn && card.Owner.CanUseCard(card) && this.heroEnergy.CanPayForCard(card);
|
||||
}
|
||||
|
||||
public bool CanUseMonsterCard(MonsterCard card) {
|
||||
return !this.heroTurn && card.Owner.IsAlive() && this.monsterEnergy.CanPayForCard(card);
|
||||
return !this.heroTurn && card.Owner.CanUseCard(card) && this.monsterEnergy.CanPayForCard(card);
|
||||
}
|
||||
|
||||
public BattleDeck<HeroCard> GetHeroDeck() {
|
||||
|
|
@ -305,14 +311,29 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe
|
|||
effect.Target.IncreaseMaxHP(effect.Amount);
|
||||
}
|
||||
|
||||
public void AcquireHeroCards(AcquireCardsEffect effect) {
|
||||
public void AcquireCards(AcquireCardsEffect effect) {
|
||||
if (effect.Participant == null) return;
|
||||
BattleHero hero = (BattleHero) effect.Participant;
|
||||
foreach (CardId cardId in effect.CardIds) {
|
||||
HeroCard acquiredCard = this.heroCardDatabase.CreateCard((int) cardId, hero);
|
||||
|
||||
if (effect.Participant.IsHero()) {
|
||||
this.AcquireCardsTyped(effect, this.heroDeck, this.heroCardDatabase);
|
||||
} else {
|
||||
this.AcquireCardsTyped(effect, this.monsterDeck, this.monsterCardDatabase);
|
||||
}
|
||||
}
|
||||
|
||||
private void AcquireCardsTyped<BaseCardT>(
|
||||
AcquireCardsEffect effect,
|
||||
BattleDeck<BaseCardT> deck,
|
||||
CardDatabase<BaseCardT> cardDatabase)
|
||||
where BaseCardT : BaseCard {
|
||||
foreach (int cardId in effect.CardIds) {
|
||||
BaseCardT acquiredCard = cardDatabase.CreateCard(cardId, effect.Participant);
|
||||
switch (effect.Zone) {
|
||||
case BattleZone.DrawPile:
|
||||
this.heroDeck.PutCardOnTopOfDrawPile(acquiredCard);
|
||||
deck.PutCardOnTopOfDrawPile(acquiredCard);
|
||||
break;
|
||||
case BattleZone.DiscardPile:
|
||||
deck.MoveCardToDiscard(acquiredCard);
|
||||
break;
|
||||
default:
|
||||
throw new System.NotImplementedException();
|
||||
|
|
@ -320,7 +341,7 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe
|
|||
}
|
||||
|
||||
if (effect.Zone == BattleZone.DrawPile) {
|
||||
this.heroDeck.ShuffleDrawPile();
|
||||
deck.ShuffleDrawPile();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -328,9 +349,11 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe
|
|||
private List<DamageTrigger> damageTriggers = new List<DamageTrigger>();
|
||||
|
||||
public int DealDamage(DealDamageEffect effect) {
|
||||
Debug.Log("DealDamage to " + effect.Target.GetDisplayName() + " " + effect.Amount);
|
||||
if (effect.Target == null) return 0;
|
||||
|
||||
int damageDealt = effect.Target.DealDamage(effect.Amount);
|
||||
Debug.Log("damageDealt " + damageDealt);
|
||||
foreach (DamageTrigger dt in this.damageTriggers) {
|
||||
if (dt.IsTriggeredBy(effect)) {
|
||||
EnqueueActivatedTrigger(dt);
|
||||
|
|
@ -355,6 +378,11 @@ public class BattleController : MonoBehaviour, IBattleEffectApplier, IBattleEffe
|
|||
effect.Target.AddBlock(effect.Amount);
|
||||
}
|
||||
|
||||
public void AddStatus(StatusEffect effect) {
|
||||
if (effect.Target == null) return;
|
||||
effect.Target.AddStatus(effect.Status, effect.Amount);
|
||||
}
|
||||
|
||||
public void ArmDamageTrigger(DamageTrigger damageTrigger) {
|
||||
this.damageTriggers.Add(damageTrigger);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,9 +14,11 @@ public class BattleParticipant
|
|||
protected int maxHP;
|
||||
protected int block;
|
||||
protected bool dead;
|
||||
protected Dictionary<BattleStatus, int> statuses;
|
||||
|
||||
public BattleParticipant(bool isHero) {
|
||||
this.isHero = isHero;
|
||||
this.statuses = new Dictionary<BattleStatus, int>();
|
||||
}
|
||||
|
||||
public void Init() {
|
||||
|
|
@ -95,4 +97,29 @@ public class BattleParticipant
|
|||
this.OnDeath(this);
|
||||
}
|
||||
}
|
||||
|
||||
public int AddStatus(BattleStatus status, int amount) {
|
||||
int currentAmount;
|
||||
this.statuses.TryGetValue(status, out currentAmount);
|
||||
this.statuses[status] = currentAmount + amount;
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void TickStatuses() {
|
||||
Dictionary<BattleStatus, int> newStatuses = new Dictionary<BattleStatus, int>();
|
||||
foreach (KeyValuePair<BattleStatus, int> pair in this.statuses) {
|
||||
if (pair.Value >= 1) {
|
||||
newStatuses[pair.Key] = pair.Value - 1;
|
||||
}
|
||||
}
|
||||
this.statuses = newStatuses;
|
||||
}
|
||||
|
||||
public bool CanUseCard(BaseCard card) {
|
||||
return IsAlive() && !HasStatus(BattleStatus.Stun);
|
||||
}
|
||||
|
||||
public bool HasStatus(BattleStatus status) {
|
||||
return this.statuses.ContainsKey(status);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -304,10 +304,10 @@ MonoBehaviour:
|
|||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
heroIds: 010000000000000002000000
|
||||
monsterIds: 000000000100000000000000
|
||||
cardIds: 00000000000000000000000000000000010000000100000001000000030000000300000004000000
|
||||
mCardIds: 01000000010000000100000001000000010000000100000005000000050000000500000005000000
|
||||
mCardOwnerIndexes: 00000000000000000000000002000000020000000200000001000000010000000100000001000000
|
||||
monsterIds: 010000000000000000000000
|
||||
cardIds: 00000000000000000000000001000000010000000100000004000000030000000300000000000000
|
||||
mCardIds: 0800000008000000080000000800000008000000
|
||||
mCardOwnerIndexes: 0000000000000000000000000000000000000000
|
||||
heroUIPrefab: {fileID: 6641511084601005557, guid: ef1b469b45cedee418e4c4adf577cd00,
|
||||
type: 3}
|
||||
uiCanvas: {fileID: 35522588}
|
||||
|
|
|
|||
3
Assets/Battle/BattleStatus.cs
Normal file
3
Assets/Battle/BattleStatus.cs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
public enum BattleStatus {
|
||||
Stun,
|
||||
}
|
||||
11
Assets/Battle/BattleStatus.cs.meta
Normal file
11
Assets/Battle/BattleStatus.cs.meta
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6fae0f0d5eccf2e41a949f4ccfca501f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
27
Assets/Battle/CardsMonsters/GolemBerserkMCard.cs
Normal file
27
Assets/Battle/CardsMonsters/GolemBerserkMCard.cs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class GolemBerserkMCard : MonsterCard
|
||||
{
|
||||
public GolemBerserkMCard(BattleParticipant owner)
|
||||
: base(owner, MCardId.GolemBerserk, "Golem Berserk", 7, CardType.Attack,
|
||||
"Deals 8 damage to target and 4 damage to other enemies."
|
||||
+ "Target: nearest hero.") {
|
||||
}
|
||||
|
||||
public override IEnumerator Use(IBattleEffectApplier effectApplier, MonsterViewpoint monsterViewpoint) {
|
||||
BattleParticipant target = AIUtils.GetNearestHero(monsterViewpoint, this.owner);
|
||||
|
||||
effectApplier.Apply(new DealDamageEffect(target, 8));
|
||||
yield return new WaitForSeconds(1f);
|
||||
foreach (BattleHero hero in monsterViewpoint.Heroes) {
|
||||
if (hero != target) {
|
||||
effectApplier.Apply(new DealDamageEffect(hero, 4));
|
||||
}
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(1f);
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
11
Assets/Battle/CardsMonsters/GolemBerserkMCard.cs.meta
Normal file
11
Assets/Battle/CardsMonsters/GolemBerserkMCard.cs.meta
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8989d6bcb159b934f903860d3bc33c31
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
24
Assets/Battle/CardsMonsters/GolemChargeMCard.cs
Normal file
24
Assets/Battle/CardsMonsters/GolemChargeMCard.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class GolemChargeMCard : MonsterCard
|
||||
{
|
||||
public GolemChargeMCard(BattleParticipant owner)
|
||||
: base(owner, MCardId.GolemCharge, "Golem Charge", 5, CardType.Attack,
|
||||
"Deals 4 damage to target and stuns it. Acquire a Golem Berserk. "
|
||||
+ "Target: farthest hero.") {
|
||||
}
|
||||
|
||||
public override IEnumerator Use(IBattleEffectApplier effectApplier, MonsterViewpoint monsterViewpoint) {
|
||||
BattleParticipant target = AIUtils.GetFarthestHero(monsterViewpoint, this.owner);
|
||||
DealDamageEffect damageEffect = new DealDamageEffect(target, 4);
|
||||
effectApplier.Apply(damageEffect);
|
||||
StatusEffect statusEffect = new StatusEffect(target, BattleStatus.Stun);
|
||||
effectApplier.Apply(statusEffect);
|
||||
AcquireCardsEffect acquireEffect = new AcquireCardsEffect(
|
||||
MCardId.GolemBerserk, BattleZone.DiscardPile, this.owner);
|
||||
effectApplier.Apply(acquireEffect);
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
11
Assets/Battle/CardsMonsters/GolemChargeMCard.cs.meta
Normal file
11
Assets/Battle/CardsMonsters/GolemChargeMCard.cs.meta
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 227631868e2bca746a7fa186c249248c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,28 +1,41 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
public class AcquireCardsEffect : IBattleEffect
|
||||
{
|
||||
private CardId[] cardIds;
|
||||
private int[] cardIds;
|
||||
private BattleZone zone;
|
||||
private BattleParticipant participant;
|
||||
|
||||
public AcquireCardsEffect(CardId cardId, BattleZone zone, BattleParticipant participant) {
|
||||
Initialize(new int[1] {(int) cardId}, zone, participant);
|
||||
}
|
||||
|
||||
public AcquireCardsEffect(CardId[] cardIds, BattleZone zone, BattleParticipant participant) {
|
||||
Initialize(cardIds.Cast<int>().ToArray(), zone, participant);
|
||||
}
|
||||
|
||||
public AcquireCardsEffect(MCardId mCardId, BattleZone zone, BattleParticipant participant) {
|
||||
Initialize(new int[1] {(int) mCardId}, zone, participant);
|
||||
}
|
||||
|
||||
public AcquireCardsEffect(MCardId[] mCardIds, BattleZone zone, BattleParticipant participant) {
|
||||
Initialize(mCardIds.Cast<int>().ToArray(), zone, participant);
|
||||
}
|
||||
|
||||
private void Initialize(int[] cardIds, BattleZone zone, BattleParticipant participant) {
|
||||
this.cardIds = cardIds;
|
||||
this.zone = zone;
|
||||
this.participant = participant;
|
||||
}
|
||||
|
||||
public void Apply(IBattleEffectResolver resolver) {
|
||||
if (this.participant.IsHero()) {
|
||||
resolver.AcquireHeroCards(this);
|
||||
} else {
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
resolver.AcquireCards(this);
|
||||
}
|
||||
|
||||
public CardId[] CardIds {get => this.cardIds;}
|
||||
public int[] CardIds {get => this.cardIds;}
|
||||
public BattleZone Zone {get => this.zone;}
|
||||
public BattleParticipant Participant {get => this.participant;}
|
||||
}
|
||||
|
|
|
|||
30
Assets/Battle/Effects/StatusEffect.cs
Normal file
30
Assets/Battle/Effects/StatusEffect.cs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class StatusEffect : IBattleEffect
|
||||
{
|
||||
private BattleParticipant target;
|
||||
private BattleStatus status;
|
||||
private int amount;
|
||||
|
||||
public StatusEffect(BattleParticipant target, BattleStatus status) {
|
||||
this.target = target;
|
||||
this.status = status;
|
||||
this.amount = 1;
|
||||
}
|
||||
|
||||
public StatusEffect(BattleParticipant target, BattleStatus status, int amount) {
|
||||
this.target = target;
|
||||
this.status = status;
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public void Apply(IBattleEffectResolver resolver) {
|
||||
resolver.AddStatus(this);
|
||||
}
|
||||
|
||||
public BattleParticipant Target {get => this.target;}
|
||||
public BattleStatus Status {get => this.status;}
|
||||
public int Amount {get => this.amount;}
|
||||
}
|
||||
11
Assets/Battle/Effects/StatusEffect.cs.meta
Normal file
11
Assets/Battle/Effects/StatusEffect.cs.meta
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b5c00b59e47f93143aae014a3351c16b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -6,9 +6,10 @@ public interface IBattleEffectResolver {
|
|||
int DealDamage(DealDamageEffect effect);
|
||||
int Heal(HealEffect effect);
|
||||
void AddBlock(BlockEffect effect);
|
||||
void AddStatus(StatusEffect effect);
|
||||
void IncreaseHeroMaxEnergy(IncreaseMaxEnergyEffect delta);
|
||||
void IncreaseMaxHP(IncreaseMaxHPEffect effect);
|
||||
void AcquireHeroCards(AcquireCardsEffect effect);
|
||||
void AcquireCards(AcquireCardsEffect effect);
|
||||
|
||||
void ArmDamageTrigger(DamageTrigger damageTrigger);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,43 +3,63 @@ using System.Collections.Generic;
|
|||
using UnityEngine;
|
||||
|
||||
public class AIUtils {
|
||||
public static BattleHero GetNearestHero(MonsterViewpoint monsterViewpoint,
|
||||
public static BattleHero GetNearestHero(MonsterViewpoint viewpoint,
|
||||
BattleParticipant owner) {
|
||||
int ownerPosition = GetMonsterPosition(monsterViewpoint, owner);
|
||||
int ownerPosition = GetMonsterPosition(viewpoint, owner);
|
||||
|
||||
int nearestHeroIndex = -1;
|
||||
int nearestDistance = int.MaxValue;
|
||||
for (int i = 0; i < monsterViewpoint.Heroes.Length; i++) {
|
||||
if (!monsterViewpoint.Heroes[i].IsAlive()) continue;
|
||||
for (int i = 0; i < viewpoint.Heroes.Length; i++) {
|
||||
if (!viewpoint.Heroes[i].IsAlive()) continue;
|
||||
int distance = System.Math.Abs(i - ownerPosition);
|
||||
if (distance < nearestDistance) {
|
||||
nearestHeroIndex = i;
|
||||
nearestDistance = distance;
|
||||
}
|
||||
}
|
||||
if (nearestHeroIndex == -1) return null;
|
||||
return monsterViewpoint.Heroes[nearestHeroIndex];
|
||||
return HeroAtIndex(nearestHeroIndex, viewpoint);
|
||||
}
|
||||
|
||||
public static int GetMonsterPosition(MonsterViewpoint monsterViewpoint, BattleParticipant monster) {
|
||||
for (int i = 0; i < monsterViewpoint.Monsters.Length; i++) {
|
||||
if (monsterViewpoint.Monsters[i] == monster) return i;
|
||||
public static BattleHero GetFarthestHero(MonsterViewpoint viewpoint,
|
||||
BattleParticipant owner) {
|
||||
int ownerPosition = GetMonsterPosition(viewpoint, owner);
|
||||
|
||||
int farthestHeroIndex = -1;
|
||||
int farthestDistance = -1;
|
||||
for (int i = 0; i < viewpoint.Heroes.Length; i++) {
|
||||
if (!viewpoint.Heroes[i].IsAlive()) continue;
|
||||
int distance = System.Math.Abs(i - ownerPosition);
|
||||
if (distance > farthestDistance) {
|
||||
farthestHeroIndex = i;
|
||||
farthestDistance = distance;
|
||||
}
|
||||
}
|
||||
return HeroAtIndex(farthestHeroIndex, viewpoint);
|
||||
}
|
||||
|
||||
private static int GetMonsterPosition(MonsterViewpoint viewpoint, BattleParticipant monster) {
|
||||
for (int i = 0; i < viewpoint.Monsters.Length; i++) {
|
||||
if (viewpoint.Monsters[i] == monster) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static BattleHero GetHeroWithHighestHP(MonsterViewpoint monsterViewpoint) {
|
||||
public static BattleHero GetHeroWithHighestHP(MonsterViewpoint viewpoint) {
|
||||
int highestHPHeroIndex = -1;
|
||||
int highestHP = -1;
|
||||
for (int i = 0; i < monsterViewpoint.Heroes.Length; i++) {
|
||||
if (!monsterViewpoint.Heroes[i].IsAlive()) continue;
|
||||
int heroHP = monsterViewpoint.Heroes[i].GetHP();
|
||||
for (int i = 0; i < viewpoint.Heroes.Length; i++) {
|
||||
if (!viewpoint.Heroes[i].IsAlive()) continue;
|
||||
int heroHP = viewpoint.Heroes[i].GetHP();
|
||||
if (heroHP > highestHP) {
|
||||
highestHPHeroIndex = i;
|
||||
highestHP = heroHP;
|
||||
}
|
||||
}
|
||||
if (highestHPHeroIndex == -1) return null;
|
||||
return monsterViewpoint.Heroes[highestHPHeroIndex];
|
||||
return HeroAtIndex(highestHPHeroIndex, viewpoint);
|
||||
}
|
||||
|
||||
private static BattleHero HeroAtIndex(int index, MonsterViewpoint viewpoint) {
|
||||
if (index == -1) return null;
|
||||
return viewpoint.Heroes[index];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,12 +21,16 @@ public class MonsterCardDatabase : CardDatabase<MonsterCard>
|
|||
MCardId monsterCardId = (MCardId) id;
|
||||
switch (monsterCardId)
|
||||
{
|
||||
case MCardId.QuickSwiftDeath:
|
||||
return new QuickSwiftDeathMCard(owner);
|
||||
case MCardId.VampireFangs:
|
||||
return new VampireFangsMCard(owner);
|
||||
case MCardId.GolemFist:
|
||||
return new GolemFistMCard(owner);
|
||||
case MCardId.QuickSwiftDeath:
|
||||
return new QuickSwiftDeathMCard(owner);
|
||||
case MCardId.GolemCharge:
|
||||
return new GolemChargeMCard(owner);
|
||||
case MCardId.GolemBerserk:
|
||||
return new GolemBerserkMCard(owner);
|
||||
default:
|
||||
throw new System.ArgumentException("MCardId unknown", "id");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue