internal void SetPlayRequirements(Dictionary <PlayReq, int> playReqs) { PlayRequirements = playReqs; bool needsTarget = false; TargetingType type = TargetingType.All; foreach (KeyValuePair <PlayReq, int> requirement in playReqs) { switch (requirement.Key) { case PlayReq.REQ_TARGET_TO_PLAY: MustHaveTargetToPlay = true; needsTarget = true; break; case PlayReq.REQ_DRAG_TO_PLAY: // TODO case PlayReq.REQ_NONSELF_TARGET: case PlayReq.REQ_TARGET_IF_AVAILABLE: needsTarget = true; break; case PlayReq.REQ_MINION_TARGET: type &= ~TargetingType.Hero; break; case PlayReq.REQ_FRIENDLY_TARGET: type &= ~TargetingType.Enemy; break; case PlayReq.REQ_ENEMY_TARGET: type &= ~TargetingType.Friendly; break; case PlayReq.REQ_HERO_TARGET: type &= ~TargetingType.Minion; break; case PlayReq.REQ_TARGET_WITH_RACE: TargetingPredicate += TargetingPredicates.ReqTargetWithRace(requirement.Value); break; case PlayReq.REQ_FROZEN_TARGET: TargetingPredicate += TargetingPredicates.ReqFrozenTarget; break; case PlayReq.REQ_DAMAGED_TARGET: TargetingPredicate += TargetingPredicates.ReqDamagedTarget; break; case PlayReq.REQ_UNDAMAGED_TARGET: TargetingPredicate += TargetingPredicates.ReqUndamagedTarget; break; case PlayReq.REQ_TARGET_MAX_ATTACK: TargetingPredicate += TargetingPredicates.ReqTargetMaxAttack(requirement.Value); break; case PlayReq.REQ_TARGET_MIN_ATTACK: TargetingPredicate += TargetingPredicates.ReqTargetMinAttack(requirement.Value); break; case PlayReq.REQ_MUST_TARGET_TAUNTER: TargetingPredicate += TargetingPredicates.ReqMustTargetTaunter; break; case PlayReq.REQ_STEALTHED_TARGET: TargetingPredicate += TargetingPredicates.ReqStealthedTarget; break; case PlayReq.REQ_TARGET_WITH_DEATHRATTLE: TargetingPredicate += TargetingPredicates.ReqTargetWithDeathrattle; break; case PlayReq.REQ_LEGENDARY_TARGET: TargetingPredicate += TargetingPredicates.ReqLegendaryTarget; break; case PlayReq.REQ_TARGET_FOR_COMBO: needsTarget = true; TargetingAvailabilityPredicate += TargetingPredicates.ReqTargetForCombo; break; case PlayReq.REQ_TARGET_IF_AVAILABE_AND_ELEMENTAL_PLAYED_LAST_TURN: needsTarget = true; TargetingAvailabilityPredicate += TargetingPredicates.ElementalPlayedLastTurn; break; case PlayReq.REQ_TARGET_IF_AVAILABLE_AND_DRAGON_IN_HAND: needsTarget = true; TargetingAvailabilityPredicate += TargetingPredicates.DragonInHand; break; case PlayReq.REQ_TARGET_IF_AVAILABLE_AND_MINIMUM_FRIENDLY_MINIONS: needsTarget = true; TargetingAvailabilityPredicate += TargetingPredicates.MinimumFriendlyMinions(requirement.Value); break; case PlayReq.REQ_TARGET_IF_AVAILABLE_AND_MINIMUM_FRIENDLY_SECRETS: needsTarget = true; TargetingAvailabilityPredicate += TargetingPredicates.MinimumFriendlySecrets(requirement.Value); break; case PlayReq.REQ_TARGET_IF_AVAILABLE_AND_NO_3_COST_CARD_IN_DECK: // TODO TargetingType = TargetingType.AllMinions; break; case PlayReq.REQ_TARGET_IF_AVAILABLE_AND_HERO_HAS_ATTACK: needsTarget = true; TargetingAvailabilityPredicate += TargetingPredicates.ReqHeroHasAttack; break; case PlayReq.REQ_NUM_MINION_SLOTS: PlayAvailabilityPredicate += TargetingPredicates.ReqNumMinionSlots; break; case PlayReq.REQ_MINIMUM_ENEMY_MINIONS: PlayAvailabilityPredicate += TargetingPredicates.ReqMinimumEnemyMinions(requirement.Value); break; case PlayReq.REQ_MINIMUM_TOTAL_MINIONS: PlayAvailabilityPredicate += TargetingPredicates.ReqMinimumTotalMinions(requirement.Value); break; case PlayReq.REQ_HAND_NOT_FULL: PlayAvailabilityPredicate += TargetingPredicates.ReqHandNotFull; break; case PlayReq.REQ_WEAPON_EQUIPPED: PlayAvailabilityPredicate += TargetingPredicates.ReqWeaponEquipped; break; case PlayReq.REQ_ENTIRE_ENTOURAGE_NOT_IN_PLAY: PlayAvailabilityPredicate += TargetingPredicates.ReqEntireEntourageNotInPlay(AssetId); break; case PlayReq.REQ_FRIENDLY_MINION_DIED_THIS_GAME: PlayAvailabilityPredicate += TargetingPredicates.ReqFriendlyMinionDiedThisGame; break; case PlayReq.REQ_FRIENDLY_MINION_OF_RACE_DIED_THIS_TURN: PlayAvailabilityPredicate += TargetingPredicates.ReqFriendlyMinionOfRaceDiedThisTurn((Race)requirement.Value); break; case PlayReq.REQ_MUST_PLAY_OTHER_CARD_FIRST: PlayAvailabilityPredicate += (c, card) => false; break; // REQ_STEADY_SHOT // REQ_MINION_OR_ENEMY_HERO // Steady Shot // REQ_MINION_SLOT_OR_MANA_CRYSTAL_SLOT // Jade Blossom case PlayReq.REQ_SECRET_ZONE_CAP_FOR_NON_SECRET: PlayAvailabilityPredicate += TargetingPredicates.ReqSecretZoneCapForNonSecret; break; } } if (needsTarget) { //if ((type & TargetingType.Enemy) != TargetingType.Enemy && // (type & TargetingType.Friendly) != TargetingType.Friendly) //{ // type |= TargetingType.Enemy; // type |= TargetingType.Friendly; //} TargetingType = type; } }
internal Card(string id, int assetId, Tag[] tags, Dictionary <PlayReq, int> playRequirements, string[] entourage, Tag[] refTags) { Id = id; AssetId = assetId; Entourage = entourage; PlayRequirements = playRequirements; var tagDict = new Dictionary <GameTag, int>(); var refTagDict = new Dictionary <GameTag, int>(); #region Preprocessing tags. foreach (Tag tag in tags) { if (tag.TagValue.HasIntValue) { tagDict.Add(tag.GameTag, tag.TagValue); switch (tag.GameTag) { case GameTag.COST: Cost = tag.TagValue; break; case GameTag.ATK: ATK = tag.TagValue; break; case GameTag.HEALTH: Health = tag.TagValue; break; case GameTag.OVERLOAD: HasOverload = true; Overload = tag.TagValue; break; case GameTag.SPELLPOWER: SpellPower = tag.TagValue; break; case GameTag.CHOOSE_ONE: ChooseOne = true; break; case GameTag.COMBO: Combo = true; break; case GameTag.TAUNT: Taunt = true; break; case GameTag.CHARGE: Charge = true; break; case GameTag.STEALTH: Stealth = true; break; case GameTag.POISONOUS: Poisonous = true; break; case GameTag.DIVINE_SHIELD: DivineShield = true; break; case GameTag.WINDFURY: Windfury = true; break; case GameTag.LIFESTEAL: LifeSteal = true; break; case GameTag.ECHO: Echo = true; break; case GameTag.RUSH: Rush = true; break; case GameTag.OVERKILL: Overkill = true; break; case GameTag.TWINSPELL: TwinSpell = true; break; case GameTag.CANT_BE_TARGETED_BY_SPELLS: CantBeTargetedBySpells = true; break; case GameTag.CANT_ATTACK: CantAttack = true; break; case GameTag.MODULAR: Modular = true; break; case GameTag.SECRET: IsSecret = true; break; case GameTag.QUEST: IsQuest = true; break; case GameTag.DEATHRATTLE: Deathrattle = true; break; case GameTag.UNTOUCHABLE: Untouchable = true; break; case GameTag.HIDE_STATS: HideStat = true; break; case GameTag.RECEIVES_DOUBLE_SPELLDAMAGE_BONUS: ReceivesDoubleSpelldamageBonus = true; break; case GameTag.FREEZE: Freeze = true; break; case GameTag.CARDRACE: Race = (Race)(int)tag.TagValue; break; case GameTag.CLASS: Class = (CardClass)(int)tag.TagValue; break; case GameTag.CARDTYPE: Type = (CardType)(int)tag.TagValue; break; } } else if (tag.TagValue.HasBoolValue) { tagDict.Add(tag.GameTag, tag.TagValue ? 1 : 0); } else if (tag.TagValue.HasStringValue) { switch (tag.GameTag) { case GameTag.CARDNAME: Name = tag.TagValue; break; case GameTag.CARDTEXT: Text = tag.TagValue; break; } } } foreach (Tag tag in refTags) { if (refTagDict.ContainsKey(tag.GameTag)) { continue; } if (tag.TagValue.HasIntValue) { refTagDict.Add(tag.GameTag, tag.TagValue); } else if (tag.TagValue.HasBoolValue) { refTagDict.Add(tag.GameTag, tag.TagValue ? 1 : 0); } } #endregion #region Preprocessing requirements int characterType = 0; int friendlyCheck = 0; bool needsTarget = false; foreach (KeyValuePair <PlayReq, int> requirement in playRequirements) { switch (requirement.Key) { case PlayReq.REQ_TARGET_TO_PLAY: MustHaveTargetToPlay = true; needsTarget = true; break; case PlayReq.REQ_DRAG_TO_PLAY: // TODO case PlayReq.REQ_NONSELF_TARGET: case PlayReq.REQ_TARGET_IF_AVAILABLE: needsTarget = true; break; case PlayReq.REQ_MINION_TARGET: characterType = 1; break; case PlayReq.REQ_FRIENDLY_TARGET: friendlyCheck = 1; break; case PlayReq.REQ_ENEMY_TARGET: friendlyCheck = -1; break; case PlayReq.REQ_HERO_TARGET: characterType = -1; break; case PlayReq.REQ_TARGET_WITH_RACE: TargetingPredicate += TargetingPredicates.ReqTargetWithRace(requirement.Value); break; case PlayReq.REQ_FROZEN_TARGET: TargetingPredicate += TargetingPredicates.ReqFrozenTarget; break; case PlayReq.REQ_DAMAGED_TARGET: TargetingPredicate += TargetingPredicates.ReqDamagedTarget; break; case PlayReq.REQ_UNDAMAGED_TARGET: TargetingPredicate += TargetingPredicates.ReqUndamagedTarget; break; case PlayReq.REQ_TARGET_MAX_ATTACK: TargetingPredicate += TargetingPredicates.ReqTargetMaxAttack(requirement.Value); break; case PlayReq.REQ_TARGET_MIN_ATTACK: TargetingPredicate += TargetingPredicates.ReqTargetMinAttack(requirement.Value); break; case PlayReq.REQ_MUST_TARGET_TAUNTER: TargetingPredicate += TargetingPredicates.ReqMustTargetTaunter; break; case PlayReq.REQ_STEALTHED_TARGET: TargetingPredicate += TargetingPredicates.ReqStealthedTarget; break; case PlayReq.REQ_TARGET_WITH_DEATHRATTLE: TargetingPredicate += TargetingPredicates.ReqTargetWithDeathrattle; break; case PlayReq.REQ_LEGENDARY_TARGET: TargetingPredicate += TargetingPredicates.ReqLegendaryTarget; break; case PlayReq.REQ_TARGET_FOR_COMBO: needsTarget = true; TargetingAvailabilityPredicate += TargetingPredicates.ReqTargetForCombo; break; case PlayReq.REQ_TARGET_IF_AVAILABE_AND_ELEMENTAL_PLAYED_LAST_TURN: needsTarget = true; TargetingAvailabilityPredicate += TargetingPredicates.ElementalPlayedLastTurn; break; case PlayReq.REQ_TARGET_IF_AVAILABLE_AND_DRAGON_IN_HAND: needsTarget = true; TargetingAvailabilityPredicate += TargetingPredicates.DragonInHand; break; case PlayReq.REQ_TARGET_IF_AVAILABLE_AND_MINIMUM_FRIENDLY_MINIONS: needsTarget = true; TargetingAvailabilityPredicate += TargetingPredicates.MinimumFriendlyMinions(requirement.Value); break; case PlayReq.REQ_TARGET_IF_AVAILABLE_AND_MINIMUM_FRIENDLY_SECRETS: needsTarget = true; TargetingAvailabilityPredicate += TargetingPredicates.MinimumFriendlySecrets(requirement.Value); break; case PlayReq.REQ_TARGET_IF_AVAILABLE_AND_NO_3_COST_CARD_IN_DECK: // TODO TargetingType = TargetingType.AllMinions; break; case PlayReq.REQ_TARGET_IF_AVAILABLE_AND_HERO_HAS_ATTACK: needsTarget = true; TargetingAvailabilityPredicate += TargetingPredicates.ReqHeroHasAttack; break; case PlayReq.REQ_NUM_MINION_SLOTS: PlayAvailabilityPredicate += TargetingPredicates.ReqNumMinionSlots; break; case PlayReq.REQ_MINIMUM_ENEMY_MINIONS: PlayAvailabilityPredicate += TargetingPredicates.ReqMinimumEnemyMinions(requirement.Value); break; case PlayReq.REQ_MINIMUM_TOTAL_MINIONS: PlayAvailabilityPredicate += TargetingPredicates.ReqMinimumTotalMinions(requirement.Value); break; case PlayReq.REQ_HAND_NOT_FULL: PlayAvailabilityPredicate += TargetingPredicates.ReqHandNotFull; break; case PlayReq.REQ_WEAPON_EQUIPPED: PlayAvailabilityPredicate += TargetingPredicates.ReqWeaponEquipped; break; case PlayReq.REQ_ENTIRE_ENTOURAGE_NOT_IN_PLAY: PlayAvailabilityPredicate += TargetingPredicates.ReqEntireEntourageNotInPlay(assetId); break; case PlayReq.REQ_FRIENDLY_MINION_DIED_THIS_GAME: PlayAvailabilityPredicate += TargetingPredicates.ReqFriendlyMinionDiedThisGame; break; case PlayReq.REQ_FRIENDLY_MINION_OF_RACE_DIED_THIS_TURN: PlayAvailabilityPredicate += TargetingPredicates.ReqFriendlyMinionOfRaceDiedThisTurn((Race)requirement.Value); break; case PlayReq.REQ_MUST_PLAY_OTHER_CARD_FIRST: PlayAvailabilityPredicate += (c, card) => false; break; // REQ_STEADY_SHOT // REQ_MINION_OR_ENEMY_HERO // Steady Shot // REQ_MINION_SLOT_OR_MANA_CRYSTAL_SLOT // Jade Blossom case PlayReq.REQ_SECRET_ZONE_CAP_FOR_NON_SECRET: PlayAvailabilityPredicate += TargetingPredicates.ReqSecretZoneCapForNonSecret; break; } } if (needsTarget) { if (characterType > 0) { if (friendlyCheck == 0) { TargetingType = TargetingType.AllMinions; } else if (friendlyCheck == 1) { TargetingType = TargetingType.FriendlyMinions; } else { TargetingType = TargetingType.EnemyMinions; } } else if (characterType == 0) { if (friendlyCheck == 0) { TargetingType = TargetingType.All; } else if (friendlyCheck == 1) { TargetingType = TargetingType.FriendlyCharacters; } else { TargetingType = TargetingType.EnemyCharacters; } } else { TargetingType = TargetingType.Heroes; } } #endregion Tags = tagDict; RefTags = refTagDict; // spell damage information add ... if (Text != null && (Text.Contains("$") || tagDict.ContainsKey(GameTag.AFFECTED_BY_SPELL_POWER))) { Text += " @spelldmg"; IsAffectedBySpellDamage = true; } }