MagicWars 1.2.0 - Script your card - Part II
by nantuko84
Moderators: nantuko84, CCGHQ Admins
MagicWars 1.2.0 - Script your card - Part II
by nantuko84 » 14 Dec 2009, 20:51
Here is the next part of the article cycle describing scripting engine in MagicWars that allows you to create your own cards.
As I promised, today we will take a look at setting parameters at just created spells and abilities. Here the base list that is available at the moment:
setTarget(pattern)
setTargetCount(count)
setTargetsAreOptional(isOptional)
setTargetsUnique(isUnique)
setSpecificTarget(String description, String pattern)
setSpecificTarget(String description, Closure closure)
setTrigger(pattern)
setCondition(closure)
setLimit(limit)
setCanPlay(closure)
setDescription(String description)
setStackDescription(String description)
setInvisible(Boolean isInvisible)
addCost(Cost cost)
also we'll take a look at
addKicker(cost)
addFlashback(cost)
addTrap(spell, closure, cost)
addUnearth(cost)
and some specific cases:
@upkeepEachTurn(closure)
@effect(Closure apply, Closure discard)
@entersTheBattlefield(closure)
@leavesTheBattlefield(closure)
Let's start!
setTarget(pattern) - indicates that spellability (let's write it so, instead of long "spell or ability") targets smth in the game
pattern is constant string that represent simple variants of targets, and for this function it can be "Creature", "Creature|Player" or "Player".
note: all targeting spells can access selected target(s) by injected $target and $targets variables
example: //Shock
setTargetsAreOptional(isOptional) - indicates whether you can cancel targeting or not, default is true (usually you can cancel targeting). For default cases, no need to set this parameter. Used for abilities only.
example for setTargetsAreOptional(false) would be Flametongue Kavu that _must_ target any creature when comes into play (even itself if no other creature exists)
setTargetsUnique(isUnique) - if target count is more than 1, then this parameter says whether you can choose one target twice
setSpecificTarget(String description, String pattern) - if target is more complicated just creature in play, use this method to set target type
description - what will be shown to play when he is asked to choose the target
pattern - string that uses "zone=(.*),type=(.*)[,color=(.*)]" pattern
now only zone=Battlefield is available, for types and color you can combine them using & and ^ symbols
examples:
but it's also for simple cases, as you have more universal method for targeting:
setSpecificTarget(String description, Closure closure)
description - what will be shown to play when he is asked to choose the target
closure - that returns true or false for $permanent
few examples:
setTrigger(pattern) - is used for addAbilityTriggered, sets the trigger condition when ability will be triggered. Some of triggers available now:
"@creatureAttacks" - triggers when any create attacks (once for every creature attacking)
"@moveToZone,from=,to=" - when any object moves from one zone to another
is a constant of GameZone type:
setCondition(closure) - filters objects for trigger (in case we don't want to handle all of them)
examples:
setCanPlay(closure) - set the conditions when ability can be played
addCost(Cost cost) - experimental, adds additionaly cost to spellability. at the moment it can be only SacrificeCost() that sacrifices card it self
// from Zektar Shrine Expedition (ZEN): sacrifice and put 7/1 token if there are 3 quest counters
setStackDescription(String description) - add message that will be displayed to opponent in stack
you can specify message as string or reference to text from card description:
setInvisible(Boolean isInvisible) - if true, opponent won't be asked to response, false by default
...
some coffee here
...
addKicker(cost)
addFlashback(cost)
addTrap(spell, closure[, cost]) (closure indicates the case when it will be available for its trap cost)
addUnearth(cost)
- all of them are rather easy and just adds kicker, flashback, trap and unearth.
@upkeepEachTurn(closure) - executed at every your upkeep
first closure will be applyed to existing and new permanents, the second will applyed when effect owner will leave player or change controller
@leavesTheBattlefield(closure) - is called when card leaves the battlefield
That's it for today.
Next time we'll get to know what objects (from the game and engine) we can use in our spells.
See you
As I promised, today we will take a look at setting parameters at just created spells and abilities. Here the base list that is available at the moment:
setTarget(pattern)
setTargetCount(count)
setTargetsAreOptional(isOptional)
setTargetsUnique(isUnique)
setSpecificTarget(String description, String pattern)
setSpecificTarget(String description, Closure closure)
setTrigger(pattern)
setCondition(closure)
setLimit(limit)
setCanPlay(closure)
setDescription(String description)
setStackDescription(String description)
setInvisible(Boolean isInvisible)
addCost(Cost cost)
also we'll take a look at
addKicker(cost)
addFlashback(cost)
addTrap(spell, closure, cost)
addUnearth(cost)
and some specific cases:
@upkeepEachTurn(closure)
@effect(Closure apply, Closure discard)
@entersTheBattlefield(closure)
@leavesTheBattlefield(closure)
Let's start!
setTarget(pattern) - indicates that spellability (let's write it so, instead of long "spell or ability") targets smth in the game
pattern is constant string that represent simple variants of targets, and for this function it can be "Creature", "Creature|Player" or "Player".
note: all targeting spells can access selected target(s) by injected $target and $targets variables
example: //Shock
- Code: Select all
addSpell({
dealDamage($target, 2, $this)
})
setTarget("Creature|Player")
setTargetsAreOptional(isOptional) - indicates whether you can cancel targeting or not, default is true (usually you can cancel targeting). For default cases, no need to set this parameter. Used for abilities only.
example for setTargetsAreOptional(false) would be Flametongue Kavu that _must_ target any creature when comes into play (even itself if no other creature exists)
setTargetsUnique(isUnique) - if target count is more than 1, then this parameter says whether you can choose one target twice
setSpecificTarget(String description, String pattern) - if target is more complicated just creature in play, use this method to set target type
description - what will be shown to play when he is asked to choose the target
pattern - string that uses "zone=(.*),type=(.*)[,color=(.*)]" pattern
now only zone=Battlefield is available, for types and color you can combine them using & and ^ symbols
examples:
- Code: Select all
//Doom Blade
setSpecificTarget("Select nonblack creature to destroy.", "zone=Battlefield,type=Creature,color=^Black")
- Code: Select all
//Terror
setSpecificTarget("Select nonartifact, nonblack creature to destroy.", "zone=Battlefield,type=Creature&^Artifact,color=^Black")
- Code: Select all
//Creeping Mold
setSpecificTarget("Select artifact, enchantment, or land to destroy.", "zone=Battlefield,type=Land&Artifact&Enchantment") // <-- short pattern without color
but it's also for simple cases, as you have more universal method for targeting:
setSpecificTarget(String description, Closure closure)
description - what will be shown to play when he is asked to choose the target
closure - that returns true or false for $permanent
few examples:
- Code: Select all
// royal assasin
setSpecificTarget("Select target tapped creature to destroy.", {
return $permanent.isCreature() && $permanent.isTapped()
})
- Code: Select all
// royal assasin
setSpecificTarget("Select target tapped creature to destroy.", {
return $permanent.creature && $permanent.tapped
})
- Code: Select all
abilityTriggered.setSpecificTarget("Select nonbasic land to destroy.", {
return $permanent.isLand() && !$permanent.isBasicLand()
})
- Code: Select all
setSpecificTarget("Select target creature without flying.", {
return $permanent.creature && !$permanent.hasKeyword(KEYWORD_FLYING_SA)
})
setTrigger(pattern) - is used for addAbilityTriggered, sets the trigger condition when ability will be triggered. Some of triggers available now:
"@creatureAttacks" - triggers when any create attacks (once for every creature attacking)
"@moveToZone,from=,to=" - when any object moves from one zone to another
is a constant of GameZone type:
- Code: Select all
GameZone {
Library,
Hand,
Battlefield,
Stack,
Graveyard,
Exile,
Any
}
setCondition(closure) - filters objects for trigger (in case we don't want to handle all of them)
examples:
- Code: Select all
//Hagra Crocodile (ZEN) and Landfall
addAbilityTriggered(text[1], {
pumpUntilEOT($this, 2, 2)
})
setCondition({
return $card.isLand() && $card.controller == $this.controller
})
setTrigger("@moveToZone,from=Any,to=Battlefield")
- Code: Select all
//Deathgreeter (M10)
addAbilityTriggered(text[0], {
gainLife($this.controller, 1, $this)
}, "gain 1 life?")
setCondition({
return $card.creature && !$card.equals($this)
})
setTrigger("@moveToZone,from=Battlefield,to=Graveyard")
setCanPlay(closure) - set the conditions when ability can be played
addCost(Cost cost) - experimental, adds additionaly cost to spellability. at the moment it can be only SacrificeCost() that sacrifices card it self
// from Zektar Shrine Expedition (ZEN): sacrifice and put 7/1 token if there are 3 quest counters
- Code: Select all
addCost(SacrificeCost())
setCanPlay({
$this.getCounters(CounterType.QUEST) >= 3
})
setStackDescription(String description) - add message that will be displayed to opponent in stack
you can specify message as string or reference to text from card description:
- Code: Select all
text = [ "Flying", "Other Faerie creatures you control get +1/+1."]
setInvisible(Boolean isInvisible) - if true, opponent won't be asked to response, false by default
...
some coffee here
...
addKicker(cost)
addFlashback(cost)
addTrap(spell, closure[, cost]) (closure indicates the case when it will be available for its trap cost)
addUnearth(cost)
- all of them are rather easy and just adds kicker, flashback, trap and unearth.
- Code: Select all
def spell = spells($this)
addTrap(spell[0], {
return $opponent.getGameStatistics().hasSearchedLibraryForACardThisTurn();
}) // <-- cost is "0" here
@upkeepEachTurn(closure) - executed at every your upkeep
- Code: Select all
//Vampire Lacerator (ZEN)
@upkeepEachTurn({
if ($oppLife > 10) {
loseLife($this.controller, 1, $this)
mwprint("Upkeep, {Vampire Lacerator}: " + nickname($this.controller) + " loses 1 life.");
}
})
first closure will be applyed to existing and new permanents, the second will applyed when effect owner will leave player or change controller
- Code: Select all
// Scion of Oona
@effect({
if ($permanent.isCreature() && $permanent.type('Faerie')
&& $permanent.controller == $this.controller && !$permanent.equals($this)) {
$permanent.addAttack(1);
$permanent.addDefense(1);
$permanent.addKeyword(KEYWORD_SHROUD_SA);
}
},{
if ($permanent.isCreature() && $permanent.type('Faerie')
&& $permanent.controller == $this.controller && !$permanent.equals($this)) {
$permanent.subAttack(1);
$permanent.subDefense(1);
$permanent.removeKeyword(KEYWORD_SHROUD_SA);
}
})
@leavesTheBattlefield(closure) - is called when card leaves the battlefield
- Code: Select all
// Flametongue Kavu
@entersTheBattlefield({
def abilityTriggered = TriggeredAbility($this, {
dealDamage($target, 4, $this);
})
abilityTriggered.setNeedsTargetCreature(true)
abilityTriggered.setTargetsAreOptional(false)
stack.add(abilityTriggered)
})
That's it for today.
Next time we'll get to know what objects (from the game and engine) we can use in our spells.
See you
Re: MagicWars 1.2.0 - Script your card - Part II
by Marek14 » 14 Dec 2009, 22:17
"usually you can cancel targeting"? I'm not quite sure what you mean.
Compare Flametongue Kavu to Gempalm Incinerator. The difference is that you have to deal damage with Flametongue Kavu, while with Gempalm Incinerator you can eventually decide to not deal damage, but in both cases you HAVE to target something (and if, say, Horobi, Death's Whisper is in play, something dies).
Compare Flametongue Kavu to Gempalm Incinerator. The difference is that you have to deal damage with Flametongue Kavu, while with Gempalm Incinerator you can eventually decide to not deal damage, but in both cases you HAVE to target something (and if, say, Horobi, Death's Whisper is in play, something dies).
Re: MagicWars 1.2.0 - Script your card - Part II
by nantuko84 » 15 Dec 2009, 06:48
this question made me deep in thought (you know what questions to ask)
you are right saying that all spells without "may" HAVE to target anything in the game. I've reviewed all cards implemented with using setTargetsAreOptional(false) and now I understand that the core reason for that is some type of undo action. Let me explain
Whenever you play any spell from hand that targets something, you are being asked to choose target. At such point, you're able to press "Cancel" that does not mean that you play the spell without any target, but just canceling the whole spell to play.
But in some cases, you can't go back to revert that was already done. Two most common examples:
Flametongue Kavu - once it entered onto battlefield, you MUST choose a target and no option to cancel it (as you can't cancel playing the whole spell, Flametongue Kavu is already on battlefield)
Before the next example, I need to explain a little how some choosing and searching spells work now. After spell is resolved, if it needs some chosen card, it puts another object (inherited from SpellAbility) to the stack - some sort of subspell that is invisible to players and can't be responded (that is what setInvisible() does). But here there are some differences: you can cancel searching card for Nissa Revane (saying I didn't find anything though there are Nissa's Chosen cards in your deck), but can't cancel choosing card for Duress where at first you target a player (here you can cancel playing it), but once a player was chosen and you saw all his cards, you can't refuse playing Duress and need to choose a card to discard
at the moment, have no idea how to implement it other way
regards
you are right saying that all spells without "may" HAVE to target anything in the game. I've reviewed all cards implemented with using setTargetsAreOptional(false) and now I understand that the core reason for that is some type of undo action. Let me explain
Whenever you play any spell from hand that targets something, you are being asked to choose target. At such point, you're able to press "Cancel" that does not mean that you play the spell without any target, but just canceling the whole spell to play.
But in some cases, you can't go back to revert that was already done. Two most common examples:
Flametongue Kavu - once it entered onto battlefield, you MUST choose a target and no option to cancel it (as you can't cancel playing the whole spell, Flametongue Kavu is already on battlefield)
Before the next example, I need to explain a little how some choosing and searching spells work now. After spell is resolved, if it needs some chosen card, it puts another object (inherited from SpellAbility) to the stack - some sort of subspell that is invisible to players and can't be responded (that is what setInvisible() does). But here there are some differences: you can cancel searching card for Nissa Revane (saying I didn't find anything though there are Nissa's Chosen cards in your deck), but can't cancel choosing card for Duress where at first you target a player (here you can cancel playing it), but once a player was chosen and you saw all his cards, you can't refuse playing Duress and need to choose a card to discard
at the moment, have no idea how to implement it other way
regards
Re: MagicWars 1.2.0 - Script your card - Part II
by Marek14 » 15 Dec 2009, 08:59
The issue, basically, is that sometimes you are allowed to cancel the spell or ability and not cast/activate it (game "rewinds" to state just before you started), and sometimes not. But there is an easy way to differ between the two: things that can't be rewound like that are triggered abilities, and only those. (Plus spells cast with suspend - they MUST be cast when time counters run out, if possible). And even in case of triggered abilities, you might want to go back to where the ability triggered and put the abilities in different order.nantuko84 wrote:this question made me deep in thought (you know what questions to ask)
you are right saying that all spells without "may" HAVE to target anything in the game. I've reviewed all cards implemented with using setTargetsAreOptional(false) and now I understand that the core reason for that is some type of undo action. Let me explain
Whenever you play any spell from hand that targets something, you are being asked to choose target. At such point, you're able to press "Cancel" that does not mean that you play the spell without any target, but just canceling the whole spell to play.
But in some cases, you can't go back to revert that was already done. Two most common examples:
Flametongue Kavu - once it entered onto battlefield, you MUST choose a target and no option to cancel it (as you can't cancel playing the whole spell, Flametongue Kavu is already on battlefield)
Before the next example, I need to explain a little how some choosing and searching spells work now. After spell is resolved, if it needs some chosen card, it puts another object (inherited from SpellAbility) to the stack - some sort of subspell that is invisible to players and can't be responded (that is what setInvisible() does). But here there are some differences: you can cancel searching card for Nissa Revane (saying I didn't find anything though there are Nissa's Chosen cards in your deck), but can't cancel choosing card for Duress where at first you target a player (here you can cancel playing it), but once a player was chosen and you saw all his cards, you can't refuse playing Duress and need to choose a card to discard
at the moment, have no idea how to implement it other way
regards
Also, why having the cancel only in targeting? The cancel button should be available during the whole announcement, up to (and especially during) the part where you actually pay the costs. And this make it useful even for triggered abilities, as some of them make you choose modes, for example (Quiet Disrepair or Blizzard Specter come to mind).
So, I'd say that the basic template should ALWAYS allow cancelling - but if you cancel a mandatory action, like triggered ability, you won't get rid of it, and you must announce it again. Even if you choose to leave mandatory actions without cancel button, the suspend interaction means that this shouldn't be specified at the card level, but at the rules engine level.
Re: MagicWars 1.2.0 - Script your card - Part II
by Incantus » 15 Dec 2009, 14:17
Also, you are confusing targeting with choosing a card (targeting happens when playing the spell/ability, choosing when you resolve - so there is no canceling, since you can't cancel the resolution).
Re: MagicWars 1.2.0 - Script your card - Part II
by nantuko84 » 15 Dec 2009, 20:00
Yes, the second example was about choosing, but you still can cancel choosing (e.g. choosing what creature to sacrifice as a cost). from the other side, you can't cancel choosing card for Duress (as you said, it is when you resolve), but again - you can cancel choosing when search any card (still on resolve) though there are cards that you can choose
6 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 3 guests