Class CardDesc

java.lang.Object
net.demilich.metastone.game.cards.desc.CardDesc
All Implemented Interfaces:
java.io.Serializable, java.lang.Cloneable, HasEntrySet<CardDescArg,​java.lang.Object>, AbstractEnchantmentDesc<Enchantment>

public final class CardDesc
extends java.lang.Object
implements java.io.Serializable, java.lang.Cloneable, HasEntrySet<CardDescArg,​java.lang.Object>, AbstractEnchantmentDesc<Enchantment>
The class that card JSON files deserialize (get decoded) into.

All types of cards are encoded as a CardDesc; spells, secrets, hero cards, hero powers, minions, etc. This class should only store the data related to the card, not card functionality itself.

Each of the fields in this class correspond exactly to the fields in a .json file located in the cards directory. A card JSON looks like:

           {
             "name": "Angry Primate",
             "baseManaCost": 1,
             "type": "MINION",
             "heroClass": "ANY",
             "baseAttack": 1,
             "baseHp": 2,
             "rarity": "COMMON",
             "race": "BEAST",
             "description": "Battlecry: Add a Banana to your hand.",
  line 63:   "battlecry": {
               "targetSelection": "NONE",
               "spell": {
                 "class": "ReceiveCardSpell",
  line 67:       "cards": [
                   "spell_bananas"
                 ]
               }
             },
  line 72:   "attributes": {
               "BATTLECRY": true
             },
             "collectible": true,
             "set": "CUSTOM",
             "fileFormatVersion": 1
           }
 
Observe that each of the keys in the JSON, or the text matching the quotation marks, matches a field in this class. So "name" corresponds to the name field, "battlecry" corresponds to the battlecry field, etc.

To figure out the format of the value of complex objects like "battlecry" on line 63 in the example above, look at the type of the field in this class. In the case of battlecry, the type is a OpenerDesc, and it appears to also have fields that exactly correspond to the keys that appear in the JSON object that is the value of "battlecry."

Some objects, like "spell", are Desc classes: these use a corresponding "argument" enumeration to determine the names and types of the fields. In the case of SpellDesc, the keys are SpellArg names, except written in camelCase. In the example of Angry Primate above, the "cards" key on line 67 inside the SpellDesc corresponds to the SpellArg.CARDS enum name. Observe that "cards" is just SpellArg.CARDS except lowercase.

The only exception to this rule is the AttributeMap object located on line 72 in the example above. The keys (left hand part in quotation marks of the JSON object) should always be capitalized, and correspond exactly to the names in Attribute.

See Also:
for the gameplay functionality of a card that consults data stored in a ., for a walk through on how deserialization of card JSON works on complex types like spells, value providers, etc., Serialized Form
  • Constructor Details

  • Method Details

    • create

      public Card create()
      Creates a Card entity with no ID or location backed by this CardDesc.
      Returns:
      A card.
    • getCollectible

      public boolean getCollectible()
    • clone

      public CardDesc clone()
      Overrides:
      clone in class java.lang.Object
    • getId

      public java.lang.String getId()
      The ID of the card when referred to by other cards and other places in the game engine.

      Typically, the ID is not specified inside the card file. It is assumed to be the file name of the card file, minus the JSON extension. For example, the card minion_bloodfen_raptor.json will have its ID field assigned to minion_bloodfen_raptor.

      IDs should not be changed after a public server release is made, even when there is a misspelling or other issue. Player's inventories store references to the underlying cards using the IDs, and changing the IDs will damage those references. The Spellsource migrations system provides a mechanism for changing IDs of cards after they have been given to players; see the net module's Spellsource class for details.

    • setId

      public void setId​(java.lang.String id)
    • getName

      public java.lang.String getName()
      The name of the card that should be rendered in the client. The name is also used for some card mechanics, like The Caverns Below. The name can be overridden by Attribute.NAME on the card entity.
      See Also:
      for the complete usage of the name field.
    • setName

      public void setName​(java.lang.String name)
    • getDescription

      public java.lang.String getDescription()
      A description of the card that should be rendered in the client. This field does not support formatting specifiers like bolding, italics, etc.
      See Also:
      for the complete usage of the description field.
    • setDescription

      public void setDescription​(java.lang.String description)
    • getLegacy

      public java.lang.Boolean getLegacy()
      Indicates whether this card will participate in the determination of legacy mechanics, the storing of data about cards across all matches.
      See Also:
      for an example of a legacy mechanic.
    • setLegacy

      public void setLegacy​(java.lang.Boolean legacy)
    • getType

      public com.hiddenswitch.spellsource.client.models.CardType getType()
      The type of card this instance describes.
    • setType

      public void setType​(com.hiddenswitch.spellsource.client.models.CardType type)
    • getHeroClass

      public java.lang.String getHeroClass()
      The hero class this card belongs to.

      Choose HeroClass.ANY for a neutral card.

    • setHeroClass

      public void setHeroClass​(java.lang.String heroClass)
    • getHeroClasses

      public java.lang.String[] getHeroClasses()
      For tri-class cards from the MSOG Hearthstone expansion, this field contains their three classes. Typically uninteresting to use for custom cards.
    • setHeroClasses

      public void setHeroClasses​(java.lang.String[] heroClasses)
    • getRarity

      public com.hiddenswitch.spellsource.client.models.Rarity getRarity()
      The rarity of the card. Use Rarity.FREE for tokens, and Rarity.ALLIANCE for legacy cards.
    • setRarity

      public void setRarity​(com.hiddenswitch.spellsource.client.models.Rarity rarity)
    • getSet

      public java.lang.String getSet()
      The set this card belongs to. Unless the card's author designed this card in the context of a greater set, use CardSet.CUSTOM for community cards.

      Eventually, a set will be immutable and represent a particular release or expansion, while a DeckFormat will represent a certain set of rules of play.

    • getSets

      public java.lang.String[] getSets()
    • setSet

      public void setSet​(java.lang.String set)
    • getBaseManaCost

      public int getBaseManaCost()
      The base mana cost of the card. All cards should have this field set, even if they are virtual / non-acting cards. Use 0 as the cost of those cards.

      Choice cards for CardType.CHOOSE_ONE cards and CardType.MINION cards with choose-one battlecries that transform into another Minion should have the same cost as the parent card. For example, the choice card of Wrath should still have Wrath's cost, not 0.

    • setBaseManaCost

      public void setBaseManaCost​(int baseManaCost)
    • isCollectible

      public boolean isCollectible()
      Indicates whether or not the card should appear in discovers and in the collection browser. Choose one choice cards, virtual choice cards, tokens, base heroes, and previous versions of other cards ("unnerfed" cards) should not be collectible.
    • setCollectible

      public void setCollectible​(boolean collectible)
    • getAttributes

      public AttributeMap getAttributes()
      Represents a key-value collection of Attribute. AttributeMap is a Map type, so in JSON, it will be represented by a bracketed object.

      For example, a spell with lifesteal will have a field "attributes" that looks like:

           "attributes": {
               "LIFESTEAL": true
           }
       
      Not all attributes are Boolean. For example, an Attribute.OVERLOAD card that reads, "Overload: 3" will have a value equal to amount of overload the card will give:
           "attributes": {
               "OVERLOAD": 3
           }
       
      See Also:
      for a full description of attributes. Some of them are not appropriate to put on a card, because they are ephemeral (that is, they are only on a while it is in play, not on a card definition like ).
    • setAttributes

      public void setAttributes​(AttributeMap attributes)
    • getFileFormatVersion

      public int getFileFormatVersion()
      Indicates the version of this card description. Defaults to 1. When new expansions are released, this number should be incremented for the new cards to help the game record traces and reproduce bugs (only the cards that were around for a particular release of the code should participate in a game trace's lookup of cards in the CardCatalogue, for example).
    • setFileFormatVersion

      public void setFileFormatVersion​(int fileFormatVersion)
    • getManaCostModifier

      public ValueProviderDesc getManaCostModifier()
      Indicates an amount the card's cost should be subtracted by while the card is in the player's hand.

      For example, to decrease the card's cost for each other card in the player's hand, the "manaCostModifier" field in the CardDesc would look like:

       "manaCostModifier": {
            "class": "PlayerAttributeValueProvider",
            "offset": -1,
            "playerAttribute": "HAND_COUNT",
            "targetPlayer": "SELF"
       }
       
    • setManaCostModifier

      public void setManaCostModifier​(ValueProviderDesc manaCostModifier)
    • getPassiveTrigger

      public EnchantmentDesc getPassiveTrigger()
      Describes an Enchantment that is active while the card is in the player's Zones.HAND.

      For example, to reduce the cost of a card each turn the card is in the player's hand, the "passiveTrigger" field should look like:

           "passiveTrigger": {
                "eventTrigger": {
                    "class": "TurnStartTrigger",
                    "targetPlayer": "SELF"
                },
                "spell": {
                    "class": "CardCostModifierSpell",
                    "target": "SELF",
                    "cardCostModifier": {
                        "class": "CardCostModifier",
                        "target": "SELF",
                        "value": 1,
                        "operation": "SUBTRACT"
                    }
                }
            }
       
      See Also:
      for more about enchantments.
    • setPassiveTrigger

      public void setPassiveTrigger​(EnchantmentDesc passiveTrigger)
    • getPassiveTriggers

      public EnchantmentDesc[] getPassiveTriggers()
      Describes an array of Enchantments that are active while the card is in the player's Zones.HAND.

      Arrays in JSON are specified using []. Place what you would ordinarily put in the value part (to the right of the colon) for passiveTrigger into the brackets here. For example:

           "passiveTriggers": [
                {
                    ...
                },
                {
                    ...
                }
           ]
       
    • setPassiveTriggers

      public void setPassiveTriggers​(EnchantmentDesc[] passiveTriggers)
    • getDeckTrigger

      public EnchantmentDesc getDeckTrigger()
      Indiciates an Enchantment that is active while the card is in the player's Zones.DECK.
    • setDeckTrigger

      public void setDeckTrigger​(EnchantmentDesc deckTrigger)
    • getGameTriggers

      public EnchantmentDesc[] getGameTriggers()
      Indicates an Enchantment that is active as soon as the game begins (just after GameLogic.handleMulligan(Player, boolean, List), in the GameLogic.startGameForPlayer(Player) phase.

      Note that the GameStartEvent is raised twice, once for each player, so your EventTriggerDesc should specify a EventTriggerArg.TARGET_PLAYER.

      For example, consider the text, "Passive: You draw an extra card at the start of every turn." A passive is implemented as a game trigger, and typically it puts another enchantment into play. Observe that the GameStartTrigger is used to do something when the game starts, while the actual effect is implemented by a different enchantment:

           "gameTriggers": [{
               "eventTrigger": {
                   "class": "GameStartTrigger",
                   "targetPlayer": "SELF"
               },
               "spell": {
                   "class": "AddEnchantmentSpell",
                   "trigger": {
                       "eventTrigger": {
                           "class": "TurnStartTrigger",
                           "targetPlayer": "SELF"
                       },
                       "spell": {
                           "class": "DrawCardSpell"
                       }
                   }
               }
           }]
       
    • setGameTriggers

      public void setGameTriggers​(EnchantmentDesc[] gameTriggers)
    • getAuthor

      public java.lang.String getAuthor()
      Indicates the author of this card.

      This field will be migrated to indicate where this username originated from (e.g., Discord versus Reddit versus Spellsource).

    • setAuthor

      public void setAuthor​(java.lang.String author)
    • getFlavor

      public java.lang.String getFlavor()
      Stores flavor text provided by the author.
    • setFlavor

      public void setFlavor​(java.lang.String flavor)
    • getWiki

      public java.lang.String getWiki()
      Stores notes about the card's implementation or behaviour. Use this field to explain surprising rules or to do a FAQ.

      This field will be migrated to support Markdown syntax in the future for better rendering controls in the client.

    • getHero

      public java.lang.String getHero()
    • setWiki

      public void setWiki​(java.lang.String wiki)
    • getBattlecry

      public OpenerDesc getBattlecry()
      Specifies the minion, hero or weapon's battlecry.

      Battlecries are always executed whenever the Card is played from the hand.

      In order to be counted as a "Battlecry" minion, the card's attributes must contain a Attribute.BATTLECRY key with true.

      See Also:
      for more about battlecries.
    • setBattlecry

      public void setBattlecry​(OpenerDesc battlecry)
    • getDeathrattle

      public SpellDesc getDeathrattle()
      Specifies the minion, hero or weapon's deathrattle.
      See Also:
      for more about deathrattles.
    • setDeathrattle

      public void setDeathrattle​(SpellDesc deathrattle)
    • getTrigger

      public EnchantmentDesc getTrigger()
      Specifies the minion, hero, or weapon's Enchantment that become active when the actor goes into an in-play zone (Zones.BATTLEFIELD, Zones.WEAPON, Zones.HERO).

      CardType.HERO_POWER should have its passiveTrigger or passiveTriggers fields set instead of this one, because hero powers behave like an extension of your hand and not like a place in the battlefield.

    • setTrigger

      public void setTrigger​(EnchantmentDesc trigger)
    • getTriggers

      public EnchantmentDesc[] getTriggers()
      Multiple trigger objects that should come into play whenever the actor comes into an in-play zone.
    • setTriggers

      public void setTriggers​(EnchantmentDesc[] triggers)
    • getAura

      public AuraDesc getAura()
      The aura that is active whenever the actor is in a in-play zone (Zones.BATTLEFIELD, Zones.WEAPON, Zones.HERO). Card entities do not support auras, since they are not in play.

      Auras describe ongoing effects on other cards. They are updated at the end of a sequence (i.e., when actors are removed from the battlefield) and whenever the "board" (the three in-play zones) change. Updated means the affected actors are recalculated.

      Auras are appropriate for effects like Ironwood Golem, which reads "Taunt. Can only attack if you have 3 or more Armor.":

            "aura": {
                "class": "AttributeAura",
                "target": "SELF",
                "condition": {
                    "class": "AttributeCondition",
                    "target": "FRIENDLY_HERO",
                    "value": 3,
                    "attribute": "ARMOR",
                    "operation": "LESS"
                },
                "attribute": "AURA_CANNOT_ATTACK",
                "secondaryTrigger": {
                    "class": "ArmorChangedTrigger",
                    "targetPlayer": "SELF"
                }
       }
       
      Observe that this aura, an AttributeAura, has a condition to indicate when the specified attribute should or should not be present on the target (EntityReference.SELF). Also observe that the attribute is prefixed with AURA_ indicating that, as opposed to an effect that is applied once (e.g Attribute.CANNOT_ATTACK), it is an "aura" effect, and it won't be removed by a silence.
      See Also:
      for more about auras.
    • setAura

      public void setAura​(AuraDesc aura)
    • getAuras

      public AuraDesc[] getAuras()
      The auras that are active whenever the actor is in play.
    • setAuras

      public void setAuras​(AuraDesc[] auras)
    • getRace

      public java.lang.String getRace()
      The actor's race, or "tribe."
    • setRace

      public void setRace​(java.lang.String race)
    • getCardCostModifier

      public CardCostModifierDesc getCardCostModifier()
      A card cost modifier that is active whenever the actor is in play.
    • setCardCostModifier

      public void setCardCostModifier​(CardCostModifierDesc cardCostModifier)
    • getBaseAttack

      public int getBaseAttack()
      The base attack of the minion. This will be the Actor.getBaseAttack() value.
    • setBaseAttack

      public void setBaseAttack​(int baseAttack)
    • getBaseHp

      public int getBaseHp()
      The base HP of the minion. This will be the Actor.getBaseHp() value.
    • setBaseHp

      public void setBaseHp​(int baseHp)
    • getChooseOneBattlecries

      public OpenerDesc[] getChooseOneBattlecries()
      Whenever a CardType.MINION has choose one battlecries, the player will be given an option of which battlecry will be played for the minion.

      Typically, choose one battlecries that put a "different" minion into play will be implemented using a TransformMinionSpell. In this common situation, the client will render the choice card as the SpellArg.CARD argument of the spell, i.e., the minion the base minion will transform into.

      The SpellArg.CARD specified by the transform spell should not be collectible.

    • setChooseOneBattlecries

      public void setChooseOneBattlecries​(OpenerDesc[] chooseOneBattlecries)
    • getChooseBothBattlecry

      public OpenerDesc getChooseBothBattlecry()
      Indicates the battlecry that will be played when Fandral Staghelm is in play, if this CardType.MINION has chooseOneBattlecries specified.
    • setChooseBothBattlecry

      public void setChooseBothBattlecry​(OpenerDesc chooseBothBattlecry)
    • getChooseOneCardIds

      public java.lang.String[] getChooseOneCardIds()
      Whenever the card is a CardType.CHOOSE_ONE and this field is specified, the player will get to choose between these two cards for their effects. The choice card is put into the Zones.SET_ASIDE_ZONE, cast, and then put into Zones.REMOVED_FROM_PLAY, while the base card is moved to the Zones.GRAVEYARD.

      These choice cards should not be collectible.

    • setChooseOneCardIds

      public void setChooseOneCardIds​(java.lang.String[] chooseOneCardIds)
    • getChooseBothCardId

      public java.lang.String getChooseBothCardId()
      Indicates the spell card that will be cast when Fandral Staghelm is in play, if this is a CardType.CHOOSE_ONE card.
    • setChooseBothCardId

      public void setChooseBothCardId​(java.lang.String chooseBothCardId)
    • getDamage

      public int getDamage()
      Indicates the amount of damage this CardType.WEAPON will deal (add to the attack of the equipping Hero).
    • setDamage

      public void setDamage​(int damage)
    • getDurability

      public int getDurability()
      Indicates the durability of this CardType.WEAPON.
    • setDurability

      public void setDurability​(int durability)
    • getOnEquip

      public SpellDesc getOnEquip()
      Indicates a spell that should be cast when the weapon enters the battlefield/an in-play zone, regardless of how it is put into play (i.e., unlike a battlecry, which is only activated by cards played from the hand).

      Contemporaneously, such effects are better implemented by aura.

    • setOnEquip

      public void setOnEquip​(SpellDesc onEquip)
    • getOnUnequip

      public SpellDesc getOnUnequip()
      Indicates a spell taht shoudl be cast when the weapon exits the battlefield/an in-play zone, regardless of how it is removed.

      Contemporaneously, such effects are better implemented by aura.

    • setOnUnequip

      public void setOnUnequip​(SpellDesc onUnequip)
    • getHeroPower

      public java.lang.String getHeroPower()
      Indicates a CardType.HERO_POWER that this CardType.HERO should put into play for the player.
      See Also:
      for more about how heroes come into play.
    • setHeroPower

      public void setHeroPower​(java.lang.String heroPower)
    • getTargetSelection

      public TargetSelection getTargetSelection()
      Indicates what kind of target selection this CardType.SPELL or CardType.HERO_POWER has. Any choice other than TargetSelection.NONE will prompt the user to pick a target as filtered by the spell field's SpellArg.FILTER field.

      For example, to indicate a spell should prompt the user to choose any Murloc on the battlefield:

           "targetSelection": "MINIONS",
           "spell": {
               "class": "...",
               "filter": {
                   "class": "RaceFilter",
                   "race": "MURLOC"
               },
               "..."
           }
       
      Observe that a "target" of EntityReference.ALL_MINIONS is not specified on the "spell" field; the target is set to the player's choice, as filtered by "filter".
    • setTargetSelection

      public void setTargetSelection​(TargetSelection targetSelection)
    • getSpell

      public SpellDesc getSpell()
      Indicates the spell that this CardType.SPELL or CardType.HERO_POWER should cast when Card.play().

      For CardType.SPELL that contain a secret or quest field set, this spell is cast when the secret or quest is activated.

    • setSpell

      public void setSpell​(SpellDesc spell)
    • getCondition

      public ConditionDesc getCondition()
      The Condition that must be met in order for this CardType.SPELL to be playable.
    • setCondition

      public void setCondition​(ConditionDesc condition)
    • getGroup

      public SpellDesc[] getGroup()
      Indicates the subspells/subcards of this CardType.GROUP.

      Used for Adaptation effects.

    • setGroup

      public void setGroup​(SpellDesc[] group)
    • getSecret

      public EventTriggerDesc getSecret()
      Indicates the EventTrigger for this secret.
    • setSecret

      public void setSecret​(EventTriggerDesc secret)
    • getQuest

      public EventTriggerDesc getQuest()
      Indicates the EventTrigger that will increase the number of fires of the quest by one.
    • setQuest

      public void setQuest​(EventTriggerDesc quest)
    • getCountUntilCast

      public int getCountUntilCast()
      Indicates the number of times the quest trigger needs to fire until this quest's spell is cast.
    • isCountByValue

      public boolean isCountByValue()
    • setCountUntilCast

      public void setCountUntilCast​(int countUntilCast)
    • getTooltips

      public com.hiddenswitch.spellsource.client.models.Tooltip[] getTooltips()
      Specifies tooltips for this card.

      If Tooltip.getKeywords() is written on a card's tooltip, the game will make the tooltip appear wherever the keyword appears in any card's getDescription().

    • setTooltips

      public CardDesc setTooltips​(com.hiddenswitch.spellsource.client.models.Tooltip[] tooltips)
    • setGlowConditions

      public CardDesc setGlowConditions​(java.util.List<Condition> glowConditions)
    • entrySet

      public java.util.Set<java.util.Map.Entry<CardDescArg,​java.lang.Object>> entrySet()
      This makes it possible to iterate through a CardDesc.
      Specified by:
      entrySet in interface HasEntrySet<CardDescArg,​java.lang.Object>
      Returns:
      An entry set for this instance.
    • getDeckTriggers

      public EnchantmentDesc[] getDeckTriggers()
    • getGlowConditions

      public java.util.stream.Stream<Condition> getGlowConditions()
      Iterates through the most important conditions on the card, heuristically.

      This includes spell conditions (getCondition(), opener conditions OpenerDesc.getCondition(), ComboSpell and condition arguments specified on subspells.

      Returns:
      A stream.
    • revealsSelf

      public boolean revealsSelf()
      Indicates whether, based on the code written on this card, this card ever reveals itself.
      Returns:
      true if any spell written on the card is a RevealCardSpell with target EntityReference.SELF
    • getDynamicDescription

      public DynamicDescriptionDesc[] getDynamicDescription()
    • getSecondPlayerBonusCards

      public java.lang.String[] getSecondPlayerBonusCards()
    • setSecondPlayerBonusCards

      public void setSecondPlayerBonusCards​(java.lang.String[] secondPlayerBonusCards)
    • getTargetSelectionCondition

      public ConditionDesc getTargetSelectionCondition()
    • getTargetSelectionOverride

      public TargetSelection getTargetSelectionOverride()
    • setTargetSelectionCondition

      public void setTargetSelectionCondition​(ConditionDesc targetSelectionCondition)
    • setTargetSelectionOverride

      public void setTargetSelectionOverride​(TargetSelection targetSelectionOverride)
    • setCountByValue

      public void setCountByValue​(boolean countByValue)
    • setDeckTriggers

      public void setDeckTriggers​(EnchantmentDesc[] deckTriggers)
    • setSets

      public void setSets​(java.lang.String[] sets)
    • setDynamicDescription

      public void setDynamicDescription​(DynamicDescriptionDesc[] dynamicDescription)
    • setHero

      public void setHero​(java.lang.String hero)
    • getEnchantmentDescs

      public java.util.stream.Stream<AbstractEnchantmentDesc<?>> getEnchantmentDescs()
    • tryCreate

      public java.util.Optional<Enchantment> tryCreate​(GameContext context, Player player, Entity effectSource, Card enchantmentSource, Entity host, boolean force)
      Specified by:
      tryCreate in interface AbstractEnchantmentDesc<Enchantment>
    • getArt

      public com.hiddenswitch.spellsource.client.models.Art getArt()
    • setArt

      public CardDesc setArt​(com.hiddenswitch.spellsource.client.models.Art art)