Card Abilities
Card ability list
You can find a list of card abilities your version supports by finding the file cardabilites.md in the persistent directory described in the getting started guide for modders.
Using card abilities
When creating a card, the card's JSON data has a section for card abilities:
...
"abilities": [
{
"name": "Play",
"abilityName": "PlayToZoneCardAbility",
"description": "",
"parameters": [
{
"n": "ZONE_NAME",
"t": null,
"dt": 3,
"sv": "ZONE_FIELD"
},
{
"n": "REVEALED",
"t": null,
"dt": 0,
"bv": false
},
{
"n": "EVENT_CONTROLLER_NAME",
"t": null,
"dt": 3,
"sv": ""
}
]
},
...
A typical ability that is added to all cards that are not spells is the PlayToZoneCardAbility, which allows placing a card into a specific zone (after paying its cost).
Ability fields
| Name | Data Type | Description |
|---|---|---|
| name | string | The name you want to give to the ability. This can be as simple as "Play the card" or "Deal damage". Used to keep track of which abilities do what for this specific card. |
| abilityName | string | The name of the ability script. This is case sensitive (so playtozonecardability is not the same as PlayToZoneCardAbility). The parameters depend on what the ability requires. |
| description | string | This field is only used for when an ability will cause a popup to appear for the player to make a choice. For example, if two play effects can be played at the same time, the player will be shown two cards with this description field translated to their local game language. You don't need to add any translation tags, you can write normal text or a translation string. |
| parameters | array | This contains a list of any parameters the ability requires. |
Ability parameter reference
| Name | Data Type | Description |
|---|---|---|
| n | string | Name of the parameter. Due to legacy code when trying to reduce JSON data size, it's reduced to the letter n. |
| t | string | Tag for the parameter. Due to legacy code, it's reduced to the letter t. This is typically only used for custom game modes, so you can ignore it. |
| dt | int | The data type of the parameter the sv field) |
| bv | bool | true/false. Should be used when dt is 0. |
| iv | int | integer (any number without decimals). Should be used when dt is 1. |
| fv | float | float (any number). Should be used when dt is 2. |
| sv | string | string (any text). Should be used when dt is 3. |
Creating a new card ability
You can use Lua scripts to add new card abilities.
To do so, you must create a new mod folder and add the following folder: GameData/CardAbilities/
For example, let's make a new ability called DestroyCardAbility:
First, create a file called DestroyCardAbility.lua, then write the following contents:
export = {
name = "Destroy card", --The name of the ability
parameters = { -- The parameters the ability uses
CardParameter.MakeStringParameter("TAGS", ""), -- Card tags (used to filter targets)
CardParameter.MakeBoolParameter("SELF", false), -- Whether to allow us to target ourselves
CardParameter.MakeBoolParameter("ALLY", false), -- Whether to allow us to target our allies
CardParameter.MakeBoolParameter("ENEMY", false), -- Whether to allow us to target our enemies
},
activeGameZones = { "ZONE_HAND" }, -- Which game zones this ability does something in
availableTargets = function(game, self, selectedTargets) --Get a list of all available targets
return HelperScripts.SearchTagInZones(game, -- Search for all zones
self.GetParameter("TAGS").stringValue, -- With the tags we want
self.card.playerID, -- Our player ID
self.GetParameter("SELF").boolValue, -- Ourselves
self.GetParameter("ALLY").boolValue, -- Allies
self.GetParameter("ENEMY").boolValue, -- Enemies
true, -- Whether to check for protection (Untargetable)
{ "ZONE_FIELD", "ZONE_SET" }); -- In the field and set zones
end,
hasAvailableTargets = function(game, self, selectedTargets) --Checks if we have any available targets
return HelperScripts.IsTagInZones(game, -- Search for all zones
self.GetParameter("TAGS").stringValue, -- With the tags we want
self.card.playerID, -- Our player ID
self.GetParameter("SELF").boolValue, -- Ourselves
self.GetParameter("ALLY").boolValue, -- Allies
self.GetParameter("ENEMY").boolValue, -- Enemies
true, -- Whether to check for protection (Untargetable)
{ "ZONE_FIELD", "ZONE_SET" }); -- In the field and set zones
end,
canPlay = function(game, self) -- Checks if we can play
return HelperScripts.CanPlayCard(game, self.card) and self.HasAvailableTargets(game, nil) -- We check if we can play the card and if we have targets
end,
onPlay = function(game, self, gameEvent) -- Called when we're playing the card
return HelperScripts.SpellOnPlay(game, self, gameEvent) -- We let the spell logic do its thing
end,
onPerformPlay = function(game, self, parameters)
local target = game.GetCard(parameters.GetParameter("TARGET").cardValue) -- Get our target
if target == nil then -- If it's invalid, stop
return
end
HelperScripts.EmitDeaths(game, -- Emit a death event to destroy the card
self.card, -- The source card (ourselves)
{ target } -- The target
)
end
}
Then, copy one of the cards you want to modify by copying the game data sources (for example, the Fireball card)
Make sure to make the copy in a similar path to the other cards (for example, GameData/Sets/AOF/CARD_DESTROY_CARD.json).
You can then modify the card data to suit your needs, and finally add the ability to it.
You want to find the field abilities and replace with your own:
{
"name": "Destroy target",
"abilityName": "DestroyCardAbility",
"description": "",
"parameters": [
{
"n": "TAGS",
"t": null,
"dt": 3,
"sv": "FOLLOWER HERO"
},
{
"n": "SELF",
"t": null,
"dt": 0,
"bv": true
},
{
"n": "ALLY",
"t": null,
"dt": 0,
"bv": true
},
{
"n": "ENEMY",
"t": null,
"dt": 0,
"bv": true
}
]
}
Then you can enable the mod and test if your card works!
Card ability structure reference
Fields
name (String)
The name of the ability (required)
Example:
...
name = "My ability name",
...
parameters (Table)
List of parameters the ability uses. The default values of each parameter are ignored.
Example:
...
parameters = {
CardParameter.MakeBoolParameter("My bool parameter", -- parameter name
false), -- default value
CardParameter.MakeIntParameter("My int parameter", 0),
CardParameter.MakeStringParameter("My string parameter", ""),
},
...
flags (Table)
List of state flags the ability uses.
Example:
...
flags = {
CardParameter.MakeBoolParameter("My bool parameter", -- parameter name
false), -- default value
CardParameter.MakeIntParameter("My int parameter", 0),
CardParameter.MakeStringParameter("My string parameter", ""),
},
...
handledCharacteristics (Table)
List of characteristics the ability modifies. Please note that you must implement onGetCharacteristic if you use this!
Example:
...
handledCharacteristics = {
{
name = "ATTACK", -- Characteristic name
priority = GameCharacteristicLayer.Modifier, -- Type of change (Normal, Set, Modifier)
selfOnly = true, -- Whether it applies to the ability's card only
}
},
...
handledPlayerCharacteristics (Table)
List of player characteristics the ability modifies. Please note that you must implement onGetPlayerCharacteristic if you use this!
Example:
...
handledPlayerCharacteristics = {
{
name = "MAXIMUM_MANA", -- Characteristic name
priority = GameCharacteristicLayer.Modifier, -- Type of change (Normal, Set, Modifier)
selfOnly = true, -- Whether it applies to the ability's card only
}
},
...
handledEvents (Table)
List of events the ability handles. Please note you must implement handlesEvent and onEvent if you use this, and optionally expectedResultForEvent!
Example:
...
handledEvents = {
name = "EVENT_PARTY", -- Event name
phase = EventPhase.After -- Phase of the event (CheckReplacements, Before, During, After)
},
...
activeGameZones (Table)
List of game zones the ability is active.
| Name | Description |
|---|---|
ZONE_HERO | Hero Zone |
ZONE_DECK | Deck Zone |
ZONE_SET | Support Zone |
ZONE_FIELD | Field Zone |
ZONE_DISCARD | Discard zone |
ZONE_EXILE | Exile Zone |
Example:
...
activeGameZones = { "ZONE_FIELD" },
...
activeWhenAttached (Bool)
Whether this ability is active while attached to something.
Example:
...
activeWhenAttached = true,
...
canActivate (function(game, self) -> Bool)
Returns whether this ability can be activated.
Example:
...
canActivate = function(game, self)
return HelperScripts.CanRest(game, self)
end,
...
onActivate (function(game, self) -> CardAbilityActivationPhase)
Called when this ability is activated.
Example:
...
onActivate = function(game, self)
if game.GetPlayer(self.card.playerID).GetState("MANA").intValue < 3 then
return CardAbilityActivationPhase.Cancelled -- Tells the system to cancel the activation
end
return CardAbilityActivationPhase.Continue -- Tells the system to continue (Cancelled, Continue, Finished). You may Finish instead of Continue.
end,
...
onPerformActivation (function(game, self))
Called to perform this ability's activation. This only gets called if onActivate returns Continue.
Example:
...
onPerformActivation = function(game, self)
game.MoveCard(self.card.playerID, self.card.GameZoneName, self.card.playerID, "ZONE_DECK", self.card.IndexInZone, -1)
end,
...