Help implementing a card
Moderators: North, BetaSteward, noxx, jeffwadsworth, JayDi, TheElk801, LevelX, CCGHQ Admins
Re: Help implementing a card
by escplan9 » 29 Feb 2016, 13:39
Hello, I work as a developer and wanted to contribute to XMage. I decided I try to implement a card I use in my Rakdos, Lord of Riots EDH deck, Dread Cacodemon. I looked at cards programmed in XMage with similar effects, like Plague Wind for destroying all creatures you don't control, and Timbermare for tapping all other creatures. However, I'm not sure how to combine all of these to get the correct effect from the card.
This is what I have so far:
1) How to make the filter for "other creatures you control" - other than Dread Cacodemon.
2) How to add the TapAllEffect into the EntersBattlefieldTriggeredAbility function afterwords. Should I just add another ability variable with a new EBTA object for the tap all portion? I'm not sure what would happen with two EBTA functions on the same card? Perhaps that is the correct way to do it since the card reads "destroy all creatures your opponents control, then tap all other creatures you control." Then again, I need all those effects to be dependent on the card being cast from the hand.
Any help would be appreciated here. Thanks.
This is what I have so far:
- Code: Select all
private static final FilterCreaturePermanent filterCreaturesDontControl = new FilterCreaturePermanent("creatures you don't control");
static {
filterCreaturesDontControl.add(new ControllerPredicate(TargetController.NOT_YOU));
}
// perhaps way to filter for all other creatures you control?
private static final FilterCreaturePermanent filterOtherCreaturesYouControl = new FilterCreaturePermanent("other creatures you control");
static {
filterOtherCreaturesYouControl.add(new ControllerPredicate(TargetController.YOU));
// add predicate for Creature != Dread Cacodemon?
}
public DreadCacodemon(UUID ownerId) {
super(ownerId, 79, "Dread Cacodemon", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{7}{B}{B}{B}");
this.expansionSetCode = "CMD";
this.subtype.add("Demon");
this.power = new MageInt(8);
this.toughness = new MageInt(8);
// When Dread Cacodemon enters the battlefield,
// if you cast it from your hand, destroy all creatures your opponents control,
// then tap all other creatures you control.
Ability ability = new EntersBattlefieldTriggeredAbility(
new ConditionalOneShotEffect(new DestroyAllEffect(filterCreaturesDontControl, false), new CastFromHandCondition(),
" if you cast it from your hand, destroy all creatures your opponents control, then tap all other creatures you control."));
this.addAbility(ability, new CastFromHandWatcher());
/**
* perhaps? Once I get the filter right.
this.addAbility(new EntersBattlefieldTriggeredAbility(new TapAllEffect(filterOtherCreaturesYouControl)));
*/
}
1) How to make the filter for "other creatures you control" - other than Dread Cacodemon.
2) How to add the TapAllEffect into the EntersBattlefieldTriggeredAbility function afterwords. Should I just add another ability variable with a new EBTA object for the tap all portion? I'm not sure what would happen with two EBTA functions on the same card? Perhaps that is the correct way to do it since the card reads "destroy all creatures your opponents control, then tap all other creatures you control." Then again, I need all those effects to be dependent on the card being cast from the hand.
Any help would be appreciated here. Thanks.
Last edited by escplan9 on 29 Feb 2016, 15:48, edited 1 time in total.
Re: Help implementing a card
by LevelX » 29 Feb 2016, 14:29
Try it this way:escplan9 wrote:1) How to make the filter for "other creatures you control" - other than Dread Cacodemon.
2) How to add the TapAllEffect into the EntersBattlefieldTriggeredAbility function afterwords. Should
- Code: Select all
private static final FilterCreaturePermanent opponentsCreatures = new FilterCreaturePermanent("creatures your opponents control");
static {
opponentsCreatures.add(new ControllerPredicate(TargetController.OPPONENT));
}
private static final FilterCreaturePermanent filterOtherCreaturesYouControl = new FilterCreaturePermanent("other creatures you control");
static {
filterOtherCreaturesYouControl.add(new ControllerPredicate(TargetController.YOU));
filterOtherCreaturesYouControl.add(new AnotherPredicate());
}
...
TriggeredAbility triggeredAbility = new EntersBattlefieldTriggeredAbility(new DestroyAllEffect(opponentsCreatures, false));
Effect effect = new TapAllEffect(filterOtherCreaturesYouControl);
effect.setText("then tap all other creatures you control");
triggeredAbility.addEffect(effect);
this.addAbility(new ConditionalTriggeredAbility(triggeredAbility, new CastFromHandCondition(),
"When {this} enters the battlefield, if you cast it from your hand, destroy all creatures your opponents control, then tap all other creatures you control."));
-
LevelX - DEVELOPER
- Posts: 1677
- Joined: 08 Dec 2011, 15:08
- Has thanked: 174 times
- Been thanked: 374 times
Re: Help implementing a card
by escplan9 » 29 Feb 2016, 15:46
Thanks for the help! I think the card is nearly done (if not already). Now I want to test the card to be sure but I'm not seeing it within the Deck Editor.
I've followed the instructions to start the server in test mode, I have a test.dck and cheat.dck in Mage.Client directory. I also have init.txt in the Mage.Server/config directory. So from NetBeans I ran the Mage Server in test mode, then I run the Client and check the "Force Database Update" and connect to local host. When it tries to load the test.dck where I have the recently added card Dread Cacodemon:
1 [CMD:79] Dread Cacodemon
I see this error in the Client log: "FATAL 2016-02-29 10:39:00,159 Could not find card '' at line 82: 1 [CMD:79] Dread Cacodemon =>[AWT-EventQueue-0] DeckImporter.importDeck "
And when I open the Deck Editor and search for the card, it does not show up either. Am I missing a step for this card to be available in the database? And is my line in test.dck correct for the card?
I've followed the instructions to start the server in test mode, I have a test.dck and cheat.dck in Mage.Client directory. I also have init.txt in the Mage.Server/config directory. So from NetBeans I ran the Mage Server in test mode, then I run the Client and check the "Force Database Update" and connect to local host. When it tries to load the test.dck where I have the recently added card Dread Cacodemon:
1 [CMD:79] Dread Cacodemon
I see this error in the Client log: "FATAL 2016-02-29 10:39:00,159 Could not find card '' at line 82: 1 [CMD:79] Dread Cacodemon =>[AWT-EventQueue-0] DeckImporter.importDeck "
And when I open the Deck Editor and search for the card, it does not show up either. Am I missing a step for this card to be available in the database? And is my line in test.dck correct for the card?
Re: Help implementing a card
by LevelX » 29 Feb 2016, 16:11
The server and the client has a DB that hold all cards.escplan9 wrote:Thanks for the help! I think the card is nearly done (if not already). Now I want to test the card to be sure but I'm not seeing it within the Deck Editor.
I've followed the instructions to start the server in test mode, I have a test.dck and cheat.dck in Mage.Client directory. I also have init.txt in the Mage.Server/config directory. So from NetBeans I ran the Mage Server in test mode, then I run the Client and check the "Force Database Update" and connect to local host. When it tries to load the test.dck where I have the recently added card Dread Cacodemon:
1 [CMD:79] Dread Cacodemon
I see this error in the Client log: "FATAL 2016-02-29 10:39:00,159 Could not find card '' at line 82: 1 [CMD:79] Dread Cacodemon =>[AWT-EventQueue-0] DeckImporter.importDeck "
And when I open the Deck Editor and search for the card, it does not show up either. Am I missing a step for this card to be available in the database? And is my line in test.dck correct for the card?
As the server starts, it checks if there are new cards added to the classes and adds the new cards to the server db.
To get it to the client db you have to check on the option "force DB update" in the connection dialog. We've done it this way to prevent a complete DB check up on everyy connect to the server. Because in the majority of connect actions there is no need for a DB checkup and update.
-
LevelX - DEVELOPER
- Posts: 1677
- Joined: 08 Dec 2011, 15:08
- Has thanked: 174 times
- Been thanked: 374 times
Re: Help implementing a card
by escplan9 » 29 Feb 2016, 18:14
In testing Dread Cacodemon with the adjustments Level X mentioned, nothing happens when it enters the battlefield. When I go back to simplifying the code, I can get it to do the "destroy all creatures you don't control" fine:
edit: Nevermind, found a way to mix the two. Now I have opponent's creatures dying and my other ones tapped as expected. What I did:
- Code: Select all
Ability ability = new EntersBattlefieldTriggeredAbility(
new ConditionalOneShotEffect(new DestroyAllEffect(opponentsCreatures, false), new CastFromHandCondition(),
" if you cast it from your hand, destroy all creatures your opponents control, then tap all other creatures you control."));
this.addAbility(ability, new CastFromHandWatcher());
- Code: Select all
private static final FilterCreaturePermanent opponentsCreatures = new FilterCreaturePermanent("creatures your opponents control");
static {
opponentsCreatures.add(new ControllerPredicate(TargetController.OPPONENT));
}
private static final FilterCreaturePermanent otherCreaturesYouControl = new FilterCreaturePermanent("other creatures you control");
static {
otherCreaturesYouControl.add(new ControllerPredicate(TargetController.YOU));
otherCreaturesYouControl.add(new AnotherPredicate());
}
public DreadCacodemon(UUID ownerId) {
super(ownerId, 79, "Dread Cacodemon", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{7}{B}{B}{B}");
this.expansionSetCode = "CMD";
this.subtype.add("Demon");
this.power = new MageInt(8);
this.toughness = new MageInt(8);
// When Dread Cacodemon enters the battlefield,
// if you cast it from your hand, destroy all creatures your opponents control,
// then tap all other creatures you control.
TriggeredAbility triggeredAbility = new EntersBattlefieldTriggeredAbility(new DestroyAllEffect(opponentsCreatures, false));
Effect effect = new TapAllEffect(otherCreaturesYouControl);
effect.setText("then tap all other creatures you control");
triggeredAbility.addEffect(effect);
this.addAbility(new ConditionalTriggeredAbility(triggeredAbility, new CastFromHandCondition(),
"When {this} enters the battlefield, if you cast it from your hand, destroy all creatures your opponents control, then tap all other creatures you control."));
}
edit: Nevermind, found a way to mix the two. Now I have opponent's creatures dying and my other ones tapped as expected. What I did:
- Code: Select all
Ability ability = new EntersBattlefieldTriggeredAbility(
new ConditionalOneShotEffect(new DestroyAllEffect(opponentsCreatures, false), new CastFromHandCondition(),
" if you cast it from your hand, destroy all creatures your opponents control, then tap all other creatures you control."));
Effect effect = new TapAllEffect(otherCreaturesYouControl);
ability.addEffect(effect);
this.addAbility(ability, new CastFromHandWatcher());
Re: Help implementing a card
by escplan9 » 29 Feb 2016, 18:29
Damn... just when I thought "ah hah! looks good!" I had to go test the "when cast from hand" part and
What I currently have, where the only remaining issue is my other creatures are still being tapped when I do not cast this card from my hand (i.e. I reanimate it):
edit: Looks like the ConditionalOneShotEffect already has a constructor taking 2 Effect variables, though it does something different than what I would want here:
public ConditionalOneShotEffect(OneShotEffect effect, OneShotEffect otherwiseEffect, Condition condition, String text)
I want both effects to be the same when the condition is true or false, not what this would do.
edit2: Actually, not sure the rules handing for the "then" clause on the card. Would there ever be a case where Dread Cacodemon resolves, ETB, and his trigger for destroying other creatures goes off but it then does not also tap your own creatures? I was thinking of cards like Stifle and Trickbind - I mean I guess someone could let their own creatures die, and then Stifle to counter the "then tap all other creatures you control" part? Not sure if that is even possible or not. If it doesn't matter... then yeah, just need a way to have both effects happen on ETB when cast from hand.
What I currently have, where the only remaining issue is my other creatures are still being tapped when I do not cast this card from my hand (i.e. I reanimate it):
- Code: Select all
Ability ability = new EntersBattlefieldTriggeredAbility(
new ConditionalOneShotEffect(new DestroyAllEffect(opponentsCreatures, false), new CastFromHandCondition(),
" if you cast it from your hand, destroy all creatures your opponents control, then tap all other creatures you control."));
Effect effect = new TapAllEffect(otherCreaturesYouControl);
ability.addEffect(effect);
this.addAbility(ability, new CastFromHandWatcher());
edit: Looks like the ConditionalOneShotEffect already has a constructor taking 2 Effect variables, though it does something different than what I would want here:
public ConditionalOneShotEffect(OneShotEffect effect, OneShotEffect otherwiseEffect, Condition condition, String text)
I want both effects to be the same when the condition is true or false, not what this would do.
edit2: Actually, not sure the rules handing for the "then" clause on the card. Would there ever be a case where Dread Cacodemon resolves, ETB, and his trigger for destroying other creatures goes off but it then does not also tap your own creatures? I was thinking of cards like Stifle and Trickbind - I mean I guess someone could let their own creatures die, and then Stifle to counter the "then tap all other creatures you control" part? Not sure if that is even possible or not. If it doesn't matter... then yeah, just need a way to have both effects happen on ETB when cast from hand.
Re: Help implementing a card
by escplan9 » 29 Feb 2016, 19:49
Well... thinking about it more... I can't just hack it together with adding a tap effect to the ETB. This is one where the effect should stack properly.
Dread Cacodemon is cast from hand when he enters the battlefield...
STACK
Destroy all creatures you do not control
Tap all other creatures you control
I'll look around for other cards that have specific ordering for some ideas how to do this right. Or see if I can figure out what went wrong with LevelX's suggestions at the start.
Dread Cacodemon is cast from hand when he enters the battlefield...
STACK
Destroy all creatures you do not control
Tap all other creatures you control
I'll look around for other cards that have specific ordering for some ideas how to do this right. Or see if I can figure out what went wrong with LevelX's suggestions at the start.
Re: Help implementing a card
by escplan9 » 29 Feb 2016, 20:19
Sorry for all the posts... very eager to get this card working. Looking back at LevelX's recommendation, that's more along the lines of what needs to be done. I think the only issue with that code was it used "CastFromHandCondition" without using "CastFromHandWatcher" - like if you look at CastFromHandCondition docs, it states:
Warning: CastFromHandWatcher must be installed to card for proper working.
I'll work on fixing it up. Thanks for the help everyone.
edit: I have LevelX's version doing something - but again the TapAllEffect is happening regardless of cast from hand or not. edit2: Huh... looks like it completely ignores the Cast From Hand check entirely. I reanimate and both triggers still happen. The only difference is when Cast From Hand, I get the small window asking me to organize the two triggers - which still doesn't seem right for that anyways. When reanimated, I do not get the window asking me to order the triggers.
Warning: CastFromHandWatcher must be installed to card for proper working.
I'll work on fixing it up. Thanks for the help everyone.
edit: I have LevelX's version doing something - but again the TapAllEffect is happening regardless of cast from hand or not. edit2: Huh... looks like it completely ignores the Cast From Hand check entirely. I reanimate and both triggers still happen. The only difference is when Cast From Hand, I get the small window asking me to organize the two triggers - which still doesn't seem right for that anyways. When reanimated, I do not get the window asking me to order the triggers.
- Code: Select all
TriggeredAbility triggeredAbility = new EntersBattlefieldTriggeredAbility(new DestroyAllEffect(opponentsCreatures, false));
Effect effect = new TapAllEffect(otherCreaturesYouControl);
effect.setText("then tap all other creatures you control");
triggeredAbility.addEffect(effect);
this.addAbility(new ConditionalTriggeredAbility(triggeredAbility, new CastFromHandCondition(),
"When {this} enters the battlefield, if you cast it from your hand, destroy all creatures your opponents control, then tap all other creatures you control."));
this.addAbility(triggeredAbility, new CastFromHandWatcher());
Re: Help implementing a card
by Doctor Weird » 29 Feb 2016, 21:13
This might be of no help, mind you, as I don't really do Java and have never contributed with the implementation of cards myself (mostly because I know that once I let myself try and learn how to implement one card I'll just never stop and then there goes all of my free time, been there, done that with other similar coding endeavors, haha).
But I figured I would mention two already implemented cards that may, or may not help you learning by observation: Scion of Vitu-Ghazi, from Dragon's Maze, and Breaching Leviathan, from Commander 2014, as both of those have "cast from hand" requirements and subsequent effects that are split into two different actions. Have a look at their source code, you might find some light there.
And you absolutely do want to make sure the ability is done correctly, as in not making it two different effects going separately on the stack. Not only because that is how the rules demand it ("then" in card's rule texts means you do the next action after the previous but never with any other thing happening in between), but also because even if it might sound unlikely at first glance, there are always situations where these things could matter. From the top of my head I could already make up some scenarios. For example: you're in a multiplayer game, someone has a Iona, Shield of Emeria in play set to red, you have a Steely Resolve set to "Demon" and one non-demon creature in play, you cast your Dread Cacodemon, killing said Iona, but now, before your other creature was tapped, squeezed in there, between those two separate triggers on the stack, another player pulls out a Backlash aimed at that non-demon creature you control, dealing enough damage to kill you. Suddenly it mattered. Sure, absolutely crazy and convoluted scenario I just made up there, but theoretically possible, which is what matters in the end. I could also just go on with the myriad of possible consequences from things that would trigger when a creature dies going on top and resolving before your creatures are ever tapped. The list goes on and on.
Anyway, I'm sure you'll get it right eventually, keep it up and thanks for being another contributor.
But I figured I would mention two already implemented cards that may, or may not help you learning by observation: Scion of Vitu-Ghazi, from Dragon's Maze, and Breaching Leviathan, from Commander 2014, as both of those have "cast from hand" requirements and subsequent effects that are split into two different actions. Have a look at their source code, you might find some light there.
And you absolutely do want to make sure the ability is done correctly, as in not making it two different effects going separately on the stack. Not only because that is how the rules demand it ("then" in card's rule texts means you do the next action after the previous but never with any other thing happening in between), but also because even if it might sound unlikely at first glance, there are always situations where these things could matter. From the top of my head I could already make up some scenarios. For example: you're in a multiplayer game, someone has a Iona, Shield of Emeria in play set to red, you have a Steely Resolve set to "Demon" and one non-demon creature in play, you cast your Dread Cacodemon, killing said Iona, but now, before your other creature was tapped, squeezed in there, between those two separate triggers on the stack, another player pulls out a Backlash aimed at that non-demon creature you control, dealing enough damage to kill you. Suddenly it mattered. Sure, absolutely crazy and convoluted scenario I just made up there, but theoretically possible, which is what matters in the end. I could also just go on with the myriad of possible consequences from things that would trigger when a creature dies going on top and resolving before your creatures are ever tapped. The list goes on and on.
Anyway, I'm sure you'll get it right eventually, keep it up and thanks for being another contributor.
- Doctor Weird
- Posts: 180
- Joined: 25 May 2015, 01:33
- Has thanked: 7 times
- Been thanked: 52 times
Re: Help implementing a card
by escplan9 » 29 Feb 2016, 21:22
This is ugly, but works. If someone can confirm this is the proper handling according to the rules text for Dread Cacodemon , awesome:
- Code: Select all
Ability tapAllOtherCreaturesYouControl = new EntersBattlefieldTriggeredAbility(
new ConditionalOneShotEffect(new TapAllEffect(otherCreaturesYouControl), new CastFromHandCondition(),
" if you cast it from your hand, destroy all creatures your opponents control, then tap all other creatures you control."));
Ability destroyAllOpponentsCreatures = new EntersBattlefieldTriggeredAbility(
new ConditionalOneShotEffect(new DestroyAllEffect(opponentsCreatures, false), new CastFromHandCondition(),
" if you cast it from your hand, destroy all creatures your opponents control, then tap all other creatures you control."));
this.addAbility(tapAllOtherCreaturesYouControl, new CastFromHandWatcher());
this.addAbility(destroyAllOpponentsCreatures, new CastFromHandWatcher());
Re: Help implementing a card
by escplan9 » 29 Feb 2016, 22:01
Thanks DoctorWeird, though it just makes me completely stumped. I've looked over various cards like Scion and Deathbringer Regent and the likes to get better ideas of how this is done. Scion was just like this:
edit: uh nevermind. Now I cannot consistently get any version to enforce the "when cast from hand" condition. I give up for tonight. My best guess is at this point that the "cast from hand" watchers are bugged.
edit2: No clue. Works again consistently with the 2 ETB trigger version - though the ability ordering is messed up, taps my guys then kills their creatures. Head hurts from trying to figure out this mess.
- Code: Select all
Ability ability = new EntersBattlefieldTriggeredAbility(
new ConditionalOneShotEffect(new TapAllEffect(otherCreaturesYouControl), new CastFromHandCondition(),
" if you cast it from your hand, destroy all creatures your opponents control, THEN tap all other creatures you control."));
ability.addEffect(new DestroyAllEffect(opponentsCreatures, false));
this.addAbility(ability, new CastFromHandWatcher());
edit: uh nevermind. Now I cannot consistently get any version to enforce the "when cast from hand" condition. I give up for tonight. My best guess is at this point that the "cast from hand" watchers are bugged.
edit2: No clue. Works again consistently with the 2 ETB trigger version - though the ability ordering is messed up, taps my guys then kills their creatures. Head hurts from trying to figure out this mess.
Re: Help implementing a card
by escplan9 » 01 Mar 2016, 00:09
Perhaps some of my issues is sometimes I may not have stopped the server instance. I've been trying to alter the tooltip text so I can know it is the version I believe I am testing. So I make the change to the tooltip to let me know, then I save the file and rebuild Mage set. Then I rebuild MAge server. then I run the server and finally the client to test.
The results:
Version 1: two ETB effects
Version 2: 1 ETB Effect, Destroy then add effect for Tap
Version 3: 1 ETB Effect, Tap then add effect for Destroy
Any thoughts on this? What is wrong with the code I'm doing?
I haven't tested with cards like Scion for instance to see if perhaps there is a bigger bug with cards like Scion which use the code formatting of version 2 and 3 - there may be a bug with the card when it is not cast from the hand. It will still do the addEffect portion when it is NOT cast from hand I suspect.
Version 1 is the closest, but I should not be able to order the triggers.
edit: For reference here is the Scion of Vitu-Ghazi code -
The results:
Version 1: two ETB effects
- Code: Select all
Ability tapAllOtherCreaturesYouControl = new EntersBattlefieldTriggeredAbility(
new ConditionalOneShotEffect(new TapAllEffect(otherCreaturesYouControl), new CastFromHandCondition(),
" TAP STUFF"));
Ability destroyAllOpponentsCreatures = new EntersBattlefieldTriggeredAbility(
new ConditionalOneShotEffect(new DestroyAllEffect(opponentsCreatures, false), new CastFromHandCondition(),
" DESTROY STUFF"));
this.addAbility(destroyAllOpponentsCreatures, new CastFromHandWatcher());
this.addAbility(tapAllOtherCreaturesYouControl, new CastFromHandWatcher());
Version 2: 1 ETB Effect, Destroy then add effect for Tap
- Code: Select all
Ability ability = new EntersBattlefieldTriggeredAbility(
new ConditionalOneShotEffect(new DestroyAllEffect(opponentsCreatures, false), new CastFromHandCondition(),
" TEST DESTROY TAP"));
ability.addEffect(new TapAllEffect(otherCreaturesYouControl));
this.addAbility(ability, new CastFromHandWatcher());
Version 3: 1 ETB Effect, Tap then add effect for Destroy
- Code: Select all
Ability ability = new EntersBattlefieldTriggeredAbility(
new ConditionalOneShotEffect(new TapAllEffect(otherCreaturesYouControl), new CastFromHandCondition(),
" TEST TAP DESTROY"));
ability.addEffect(new DestroyAllEffect(opponentsCreatures, false));
this.addAbility(ability, new CastFromHandWatcher());
Any thoughts on this? What is wrong with the code I'm doing?
I haven't tested with cards like Scion for instance to see if perhaps there is a bigger bug with cards like Scion which use the code formatting of version 2 and 3 - there may be a bug with the card when it is not cast from the hand. It will still do the addEffect portion when it is NOT cast from hand I suspect.
Version 1 is the closest, but I should not be able to order the triggers.
edit: For reference here is the Scion of Vitu-Ghazi code -
- Code: Select all
// When Scion of Vitu-Ghazi enters the battlefield, if you cast it from your hand, put a 1/1 white Bird creature token with flying onto the battlefield, then populate.
Ability ability = new EntersBattlefieldTriggeredAbility(
new ConditionalOneShotEffect(new CreateTokenEffect(new BirdToken()), new CastFromHandCondition(),
"if you cast it from your hand, put a 1/1 white Bird creature token with flying onto the battlefield,"));
ability.addEffect(new PopulateEffect("then"));
this.addAbility(ability, new CastFromHandWatcher());
Re: Help implementing a card
by escplan9 » 01 Mar 2016, 00:45
Confirmed the bug with Scion of Vitu-Ghazi - if it is NOT cast from the hand, it will still do the addEffect portion:
I submitted a bug report on Scion. I wonder how many other cards are affected by this... also makes me wonder what I'm supposed to do with Dread Cacodemon
- Code: Select all
Ability ability = new EntersBattlefieldTriggeredAbility(
new ConditionalOneShotEffect(new CreateTokenEffect(new BirdToken()), new CastFromHandCondition(),
"if you cast it from your hand, put a 1/1 white Bird creature token with flying onto the battlefield,"));
ability.addEffect(new PopulateEffect("then"));
this.addAbility(ability, new CastFromHandWatcher());
- Code: Select all
// VERSION 2: populate then add effect to create token
Ability ability = new EntersBattlefieldTriggeredAbility(
new ConditionalOneShotEffect(new PopulateEffect("then"), new CastFromHandCondition(),
"POPULATE FIRST"));
ability.addEffect(new CreateTokenEffect(new BirdToken()));
this.addAbility(ability, new CastFromHandWatcher());
I submitted a bug report on Scion. I wonder how many other cards are affected by this... also makes me wonder what I'm supposed to do with Dread Cacodemon
Last edited by escplan9 on 01 Mar 2016, 15:57, edited 1 time in total.
Re: Help implementing a card
by escplan9 » 01 Mar 2016, 01:37
Went back to the original version recommended by LevelX and it also behaves differently than the others:
If we do not want people to be able to respond to either of the effects - they go off immediately after the other without interruption, we need to fix the Cast from Hand portions. I'm not sure what else to do with the card at this time.
- Code: Select all
TriggeredAbility triggeredAbility = new EntersBattlefieldTriggeredAbility(new DestroyAllEffect(opponentsCreatures, false));
Effect effect = new TapAllEffect(otherCreaturesYouControl);
effect.setText("TAP TAP TAP");
triggeredAbility.addEffect(effect);
this.addAbility(new ConditionalTriggeredAbility(triggeredAbility, new CastFromHandCondition(),
"DESTROY FULL."));
this.addAbility(triggeredAbility, new CastFromHandWatcher());
If we do not want people to be able to respond to either of the effects - they go off immediately after the other without interruption, we need to fix the Cast from Hand portions. I'm not sure what else to do with the card at this time.
Re: Help implementing a card
by escplan9 » 01 Mar 2016, 07:27
Good news everyone - I may shut up soon enough!
In looking at other examples of cards where there were multiple effects to occur upon cast, I found some that created another class CardNameEffect() that added the handling in there. I decided to go that route after all the frustration yesterday. I based it off the structure in the card Breaching Leviathan.
Tested and works correctly both when cast from hand (applies effects in the correct order without allowing any response) and when not cast from hand (no effects apply).
edit: Created pull request (drmDev).
In looking at other examples of cards where there were multiple effects to occur upon cast, I found some that created another class CardNameEffect() that added the handling in there. I decided to go that route after all the frustration yesterday. I based it off the structure in the card Breaching Leviathan.
Tested and works correctly both when cast from hand (applies effects in the correct order without allowing any response) and when not cast from hand (no effects apply).
- Code: Select all
Ability ability = new EntersBattlefieldTriggeredAbility(
new ConditionalOneShotEffect(new DreadCacodemonEffect(), new CastFromHandCondition(),
" if you cast it from your hand, destroy all creatures your opponents control, then tap all other creatures you control."));
this.addAbility(ability, new CastFromHandWatcher());
...
public DreadCacodemonEffect() {
super(Outcome.DestroyPermanent);
this.staticText = "destroy all creatures your opponents control, then tap all other creatures you control";
}
...
@Override
public boolean apply(Game game, Ability source) {
for (Permanent creature: game.getBattlefield().getActivePermanents(opponentsCreatures, source.getControllerId(), source.getSourceId(), game)) {
creature.destroy(source.getSourceId(), game, false);
}
for (Permanent creature: game.getBattlefield().getActivePermanents(otherCreaturesYouControl, source.getControllerId(), source.getSourceId(), game)) {
creature.tap(game);
}
return true;
}
edit: Created pull request (drmDev).
Who is online
Users browsing this forum: No registered users and 7 guests