It is currently 19 Apr 2024, 02:24
   
Text Size

Card Contributions

Moderators: ubeefx, beholder, melvin, ShawnieBoy, Lodici, CCGHQ Admins

Re: Card Contributions

Postby melvin » 15 Mar 2015, 02:21

Wrong usage of executeModalEvent, it was created to replace the isMode checks.
Code: Select all
public void executeEvent(final MagicGame game, final MagicEvent event) {
    if (event.isKicked()) {
        game.addEvent(EFFECT1.getEvent(event.getSource()));
        game.addEvent(EFFECT2.getEvent(event.getSource()));
    } else {
        event.executeModalEvent(game, EFFECT1, EFFECT2);
    }
}
User avatar
melvin
AI Programmer
 
Posts: 1062
Joined: 21 Mar 2010, 12:26
Location: Singapore
Has thanked: 36 times
Been thanked: 459 times

Re: Card Contributions

Postby melvin » 15 Mar 2015, 02:31

PalladiaMors wrote:The other issue is that this way of doing entwine can only be used for untargeted cards; cards that require a target won't be viable because if the kicker mode is chosen it won't be able to get a target.
Not exactly, with ShawnieBoy's suggestion of creating different choices for entwine and not entwine case, in the entwine case the choice can be MagicTargetChoice if only one of the options has a target.
User avatar
melvin
AI Programmer
 
Posts: 1062
Joined: 21 Mar 2010, 12:26
Location: Singapore
Has thanked: 36 times
Been thanked: 459 times

Re: Card Contributions

Postby ShawnieBoy » 15 Mar 2015, 04:51

melvin wrote:Wrong usage of executeModalEvent, it was created to replace the isMode checks.
Code: Select all
public void executeEvent(final MagicGame game, final MagicEvent event) {
    if (event.isKicked()) {
        game.addEvent(EFFECT1.getEvent(event.getSource()));
        game.addEvent(EFFECT2.getEvent(event.getSource()));
    } else {
        event.executeModalEvent(game, EFFECT1, EFFECT2);
    }
}
Ahh yes, of course - thanks for that.
User avatar
ShawnieBoy
Programmer
 
Posts: 601
Joined: 02 Apr 2012, 22:42
Location: UK
Has thanked: 80 times
Been thanked: 50 times

Re: Card Contributions

Postby ShawnieBoy » 15 Mar 2015, 05:10

Back to basics works best :)

Here's the whole thing.

Code: Select all
def EFFECT1 = MagicRuleEventAction.create("Creatures you control get +1/+1 until end of turn.");

def EFFECT2 = MagicRuleEventAction.create("Untap all creatures you control.");

def CARDTEXT = "Choose one\$ — • Creatures you control get +1/+1 until end of turn." +
               " • Untap all creatures you control. " +
               "Choose both if you paid the entwine cost.";

[
    new MagicSpellCardEvent() {
        @Override
        public MagicEvent getEvent(final MagicCardOnStack cardOnStack, final MagicPayedCost payedCost) {
            return payedCost.isKicked() ?
                new MagicEvent(
                    cardOnStack,
                    this,
                    CARDTEXT
                ):
                new MagicEvent(
                    cardOnStack,
                    new MagicOrChoice(
                        MagicChoice.NONE,
                        MagicChoice.NONE
                    ),
                    this,
                    CARDTEXT
                );
        }
        @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            if (event.isKicked()) {
                game.addEvent((EFFECT1).getEvent(event.getSource()));
                game.addEvent((EFFECT2).getEvent(event.getSource()));
            } else if (event.isMode(1)) {
                game.addEvent((EFFECT1).getEvent(event.getSource()));
            } else if (event.isMode(2)) {
                game.addEvent((EFFECT2).getEvent(event.getSource()));
            }
        }
    }
]
With a format that does lend itself well to scripting.
User avatar
ShawnieBoy
Programmer
 
Posts: 601
Joined: 02 Apr 2012, 22:42
Location: UK
Has thanked: 80 times
Been thanked: 50 times

Re: Card Contributions

Postby melvin » 15 Mar 2015, 06:05

There is a bug in my earlier example, addEvent should not be used, especially if we want to support effects with target as it requires the choice to be made again. It should be executeEvent, as seen from executeModalEvent the correct way to call it should be:
Code: Select all
sourceEvents[i].getEvent(getSource()).executeEvent(game, getChosen());
which is rather clunky, hence executeModalEvent does it for you.

For the entwine, case I created executeAllEvent.

The combined logic should be:
Code: Select all
if (event.isKicked()) {
    event.executeAllEvents(game, EFFECT1, EFFECT2);
} else {
    event.executeModalEvent(game, EFFECT1, EFFECT2);
}
See viewtopic.php?f=82&t=10323&p=175090#p175090 for the full card script + groovy script. Note the use of Entwine instead of Kicker (so the correct name shows up in the UI).
User avatar
melvin
AI Programmer
 
Posts: 1062
Joined: 21 Mar 2010, 12:26
Location: Singapore
Has thanked: 36 times
Been thanked: 459 times

Re: Card Contributions

Postby melvin » 15 Mar 2015, 06:38

Example with one option having a target: see viewtopic.php?f=82&t=10323&p=175091#p175091
User avatar
melvin
AI Programmer
 
Posts: 1062
Joined: 21 Mar 2010, 12:26
Location: Singapore
Has thanked: 36 times
Been thanked: 459 times

Re: Card Contributions

Postby melvin » 15 Mar 2015, 09:29

Found a way to do it as card script. Updated examples on "Adding new cards with Groovy" script.

Groovy script archived at https://github.com/magarena/magarena/bl ... ant.groovy and https://github.com/magarena/magarena/bl ... Kha.groovy
User avatar
melvin
AI Programmer
 
Posts: 1062
Joined: 21 Mar 2010, 12:26
Location: Singapore
Has thanked: 36 times
Been thanked: 459 times

Re: Card Contributions

Postby PalladiaMors » 15 Mar 2015, 15:51

I'll give the remaining ones a try as soon as I can, but I have a doubt: can the cards that can't use RuleEventAction be done with the isMode checks? Or does that no longer work correctly? I'm pretty sure I'm capable of doing those with the mode checks, but I've no idea how to do them with executeModalEvent if they can't use RuleEventAction.

The last ~30 days have been great concerning implementation of new mechanics. Modal spells, Affinity, Entwine, non-mana cumulative upkeeps (that was already possible, but none of them had been previously done). That's well over 100 cards that I previously thought not possible yet. Way to go! Also, a huge amount of the recently implemented cards are instants, so they've caught up a bit with creatures, which hopefully should help balance the Firemind metagame a bit. It was also a very "Mirrodin" month, with affinity and entwine. With the rest of the Entwine cards and particularly Tooth and Nail, pretty much every competitive deck from Mirrodin Block Constructed will have >90% of its cards available.

Edit: did Promise of Power with isMode, tested each of the 3 modes and it looks like it works alright (besides the fact that you can't choose the order of effects in the entwined version, so I chose to draw first in order to get the Demon bigger). Looks like it works ok this way, so I'll try to do the ones I can like that.

Edit2: Firemind down today, so posting the cards here.

Code: Select all
name=black Demon creature token with flying
token=Demon
image=http://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=197936&type=card
value=2
type=Creature
subtype=Demon
color=b
ability=flying
Code: Select all
name=Promise of Power
image=http://mtgimage.com/card/promise%20of%20power.jpg
value=2.500
rarity=R
type=Sorcery
cost={2}{B}{B}{B}
ability=Entwine {4}
timing=main
requires_groovy_code
oracle=Choose one — • You draw five cards and you lose 5 life. • Put an X/X black Demon creature token with flying onto the battlefield, where X is the number of cards in your hand as the token enters the battlefield. Entwine {4}
Code: Select all
def TEXT1 = "You draw five cards and you lose 5 life."

def TEXT2 = "Put an X/X black Demon creature token with flying onto the battlefield, "+
            "where X is the number of cards in your hand as the token enters the battlefield."

[
    new MagicSpellCardEvent() {
        @Override
        public MagicEvent getEvent(final MagicCardOnStack cardOnStack, final MagicPayedCost payedCost) {
            return new MagicEvent(
                cardOnStack,
                payedCost.isKicked() ?
                    MagicChoice.NONE :
                    new MagicOrChoice(
                        MagicChoice.NONE,
                        MagicChoice.NONE
                    ),
                this,
                payedCost.isKicked() ?
                    "You draw five cards and you lose 5 life. "+
                    "Put an X/X black Demon creature token with flying onto the battlefield, "+
                    "where X is the number of cards in your hand as the token enters the battlefield." :
                    "Choose one\$ — • " + TEXT1 + " • " + TEXT2 + "\$"
            );
        }
        @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            if (event.isKicked()) {
                game.doAction(new MagicDrawAction(event.getPlayer(),5));
                game.doAction(new MagicChangeLifeAction(event.getPlayer(), -5));
                final int x = event.getPlayer().getHandSize();
                game.doAction(new MagicPlayTokenAction(event.getPlayer(), MagicCardDefinition.create({
                    it.setName("Demon");
                    it.setFullName("black Demon creature token with flying");
                    it.setPowerToughness(x, x);
                    it.setColors("b");
                    it.addSubType(MagicSubType.Demon);
                    it.addType(MagicType.Creature);
                    it.setToken();
                    it.setValue(x);
                })));   
            } else if (event.isMode(1)) {
                game.addEvent(MagicRuleEventAction.create("You draw five cards and you lose 5 life.").getEvent(event.getSource()));
            } else if (event.isMode(2)) {
                final int x = event.getPlayer().getHandSize();
                game.doAction(new MagicPlayTokenAction(event.getPlayer(), MagicCardDefinition.create({
                    it.setName("Demon");
                    it.setFullName("black Demon creature token with flying");
                    it.setPowerToughness(x, x);
                    it.setColors("b");
                    it.addSubType(MagicSubType.Demon);
                    it.addType(MagicType.Creature);
                    it.setToken();
                    it.setValue(x);
                })));   
            }
        }
    }
]
Code: Select all
name=Rude Awakening
image=http://mtgimage.com/card/rude%20awakening.jpg
value=2.500
rarity=R
type=Sorcery
cost={4}{G}
ability=Entwine {2}{G}
timing=main
requires_groovy_code
oracle=Choose one — • Untap all lands you control. • Until end of turn, lands you control become 2/2 creatures that are still lands. Entwine {2}{G}
Code: Select all
def PT = new MagicStatic(MagicLayer.SetPT, MagicStatic.UntilEOT) {
    @Override
    public void modPowerToughness(final MagicPermanent source,final MagicPermanent permanent,final MagicPowerToughness pt) {
        pt.set(2,2);
    }
};

def ST = new MagicStatic(MagicLayer.Type, MagicStatic.UntilEOT) {
    @Override
    public int getTypeFlags(final MagicPermanent permanent,final int flags) {
        return flags|MagicType.Creature.getMask();
    }
};

def TEXT1 = "Untap all lands you control."

def TEXT2 = "Until end of turn, lands you control become 2/2 creatures that are still lands."

[
    new MagicSpellCardEvent() {
        @Override
        public MagicEvent getEvent(final MagicCardOnStack cardOnStack, final MagicPayedCost payedCost) {
            return new MagicEvent(
                cardOnStack,
                payedCost.isKicked() ?
                    MagicChoice.NONE :
                    new MagicOrChoice(
                        MagicChoice.NONE,
                        MagicChoice.NONE
                    ),
                this,
                payedCost.isKicked() ?
                    "Untap all lands you control. "+
                    "Until end of turn, lands you control become 2/2 creatures that are still lands." :
                    "Choose one\$ — • " + TEXT1 + " • " + TEXT2 + "\$"
            );
        }
        @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            if (event.isKicked()) {
                final Collection<MagicPermanent> targets = event.getPlayer().filterPermanents(MagicTargetFilterFactory.LAND_YOU_CONTROL);
                for (final MagicPermanent target : targets) {
                    game.doAction(new MagicUntapAction(target));
                    game.doAction(new MagicBecomesCreatureAction(target,PT,ST));
                }         
            } else if (event.isMode(1)) {
                final Collection<MagicPermanent> targets = event.getPlayer().filterPermanents(MagicTargetFilterFactory.LAND_YOU_CONTROL);
                for (final MagicPermanent target : targets) {
                    game.doAction(new MagicUntapAction(target));
                }         
            } else if (event.isMode(2)) {
                final Collection<MagicPermanent> targets = event.getPlayer().filterPermanents(MagicTargetFilterFactory.LAND_YOU_CONTROL);
                for (final MagicPermanent target : targets) {
                    game.doAction(new MagicBecomesCreatureAction(target,PT,ST));
                }         
            }
        }
    }
]
Code: Select all
name=Pilgrim of the Fires
image=http://mtgimage.com/card/pilgrim%20of%20the%20fires.jpg
value=2.500
rarity=U
type=Artifact,Creature
subtype=Golem
cost={7}
pt=6/4
ability=First strike; trample
timing=main
oracle=First strike, trample
Code: Select all
name=Temporal Cascade
image=http://mtgimage.com/card/temporal%20cascade.jpg
value=2.500
rarity=R
type=Sorcery
cost={5}{U}{U}
ability=Entwine {2}
timing=main
requires_groovy_code
oracle=Choose one — • Each player shuffles his or her hand and graveyard into his or her library. • Each player draws seven cards. Entwine {2}
Code: Select all
def TEXT1 = "Each player shuffles his or her hand and graveyard into his or her library."

def TEXT2 = "Each player draws seven cards."

[
    new MagicSpellCardEvent() {
        @Override
        public MagicEvent getEvent(final MagicCardOnStack cardOnStack, final MagicPayedCost payedCost) {
            return new MagicEvent(
                cardOnStack,
                payedCost.isKicked() ?
                    MagicChoice.NONE :
                    new MagicOrChoice(
                        MagicChoice.NONE,
                        MagicChoice.NONE
                    ),
                this,
                payedCost.isKicked() ?
                    "Each player shuffles his or her hand and graveyard into his or her library. "+
                    "Each player draws seven cards." :
                    "Choose one\$ — • " + TEXT1 + " • " + TEXT2 + "\$"
            );
        }
        @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            if (event.isKicked()) {
                for (final MagicPlayer player : game.getAPNAP()) {
                    final MagicCardList graveyard = new MagicCardList(player.getGraveyard());
                    final MagicCardList hand = new MagicCardList(player.getHand());
                for (final MagicCard card : graveyard) {
                    game.doAction(new MagicRemoveCardAction(card,MagicLocationType.Graveyard));
                    game.doAction(new MagicMoveCardAction(card,MagicLocationType.Graveyard,MagicLocationType.OwnersLibrary));
                }
                for (final MagicCard card : hand) {
                    game.doAction(new MagicRemoveCardAction(card,MagicLocationType.OwnersHand));
                    game.doAction(new MagicMoveCardAction(card,MagicLocationType.OwnersHand,MagicLocationType.OwnersLibrary));
                }
                    game.doAction(new MagicDrawAction(player,7));
                };
            } else if (event.isMode(1)) {
                for (final MagicPlayer player : game.getAPNAP()) {
                    final MagicCardList graveyard = new MagicCardList(player.getGraveyard());
                    final MagicCardList hand = new MagicCardList(player.getHand());
                for (final MagicCard card : graveyard) {
                    game.doAction(new MagicRemoveCardAction(card,MagicLocationType.Graveyard));
                    game.doAction(new MagicMoveCardAction(card,MagicLocationType.Graveyard,MagicLocationType.OwnersLibrary));
                }
                for (final MagicCard card : hand) {
                    game.doAction(new MagicRemoveCardAction(card,MagicLocationType.OwnersHand));
                    game.doAction(new MagicMoveCardAction(card,MagicLocationType.OwnersHand,MagicLocationType.OwnersLibrary));
                }
            }
            } else if (event.isMode(2)) {
                for (final MagicPlayer player : game.getAPNAP()) {
                    game.doAction(new MagicDrawAction(player,7));
                }
            }
        }
    }
]
Code: Select all
name=Tooth and Nail
image=http://mtgimage.com/card/tooth%20and%20nail.jpg
value=2.500
rarity=R
type=Sorcery
cost={5}{G}{G}
ability=Entwine {2}
timing=main
requires_groovy_code
oracle=Choose one — • Search your library for up to two creature cards, reveal them, put them into your hand, then shuffle your library. • Put up to two creature cards from your hand onto the battlefield. Entwine {2}
Code: Select all
def TEXT1 = "Search your library for up to two creature cards, reveal them, put them into your hand, then shuffle your library."

def TEXT2 = "Put up to two creature cards from your hand onto the battlefield."

def choice = new MagicTargetChoice("a creature card from your hand");

[
    new MagicSpellCardEvent() {
        @Override
        public MagicEvent getEvent(final MagicCardOnStack cardOnStack, final MagicPayedCost payedCost) {
            return new MagicEvent(
                cardOnStack,
                payedCost.isKicked() ?
                    MagicChoice.NONE :
                    new MagicOrChoice(
                        MagicChoice.NONE,
                        MagicChoice.NONE
                    ),
                this,
                payedCost.isKicked() ?
                    "Search your library for up to two creature cards, reveal them, put them into your hand, then shuffle your library."+
                    " Put up to two creature cards from your hand onto the battlefield." :
                    "Choose one\$ — • " + TEXT1 + " • " + TEXT2 + "\$"
            );
        }
        @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            if (event.isKicked()) {
            final List<MagicCard> choiceList = event.getPlayer().filterCards(MagicTargetFilterFactory.CREATURE_CARD_FROM_LIBRARY);
                game.addEvent(new MagicSearchToLocationEvent(
                    event,
                    new MagicFromCardListChoice(choiceList, 2, true),
                    MagicLocationType.OwnersHand
                ));
                game.addEvent(new MagicPutOntoBattlefieldEvent(
                    event,
                    new MagicMayChoice(choice)
                )); 
                game.addEvent(new MagicPutOntoBattlefieldEvent(
                    event,
                    new MagicMayChoice(choice)
                ));
            } else if (event.isMode(1)) {
            final List<MagicCard> choiceList = event.getPlayer().filterCards(MagicTargetFilterFactory.CREATURE_CARD_FROM_LIBRARY);
                game.addEvent(new MagicSearchToLocationEvent(
                    event,
                    new MagicFromCardListChoice(choiceList, 2, true),
                    MagicLocationType.OwnersHand
                ));
            } else if (event.isMode(2)) {
                game.addEvent(new MagicPutOntoBattlefieldEvent(
                    event,
                    new MagicMayChoice(choice)
                ));
                game.addEvent(new MagicPutOntoBattlefieldEvent(
                    event,
                    new MagicMayChoice(choice)
                ));
            }
        }
    }
]
Did the put onto battlefield above as MayChoices, because it's an "up to 2" event, so you can choose 0, 1 or 2 creatures, thus I think doing them as choices is the way to go.

Code: Select all
name=Oblivion Stone
image=http://mtgimage.com/card/oblivion%20stone.jpg
value=2.500
rarity=R
type=Artifact
cost={3}
ability={4}, {T}: Put a fate counter on target permanent.
timing=artifact
requires_groovy_code
oracle={4}, {T}: Put a fate counter on target permanent. {5}, {T}, Sacrifice Oblivion Stone: Destroy each nonland permanent without a fate counter on it, then remove all fate counters from all permanents.
Code: Select all
def NONLAND_PERMANENT_WITHOUT_FATE_COUNTER = new MagicPermanentFilterImpl() {
    public boolean accept(final MagicGame game,final MagicPlayer player,final MagicPermanent target) {
        return !target.isLand() && target.getCounters(MagicCounterType.Fade) == 0;
    }
};

[
    new MagicPermanentActivation(
        new MagicActivationHints(MagicTiming.Removal),
        "Destroy"
    ) {
        @Override
        public Iterable<MagicEvent> getCostEvent(final MagicPermanent source) {
            return [
                new MagicPayManaCostEvent(source,"{5}"),
                new MagicTapEvent(source),
                new MagicSacrificeEvent(source)
            ];
        }

        @Override
        public MagicEvent getPermanentEvent(final MagicPermanent source, final MagicPayedCost payedCost) {
            return new MagicEvent(
                source,
                this,
                "Destroy each nonland permanent without a fate counter on it, "+
                "then remove all fate counters from all permanents."
            );
        }

        @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            final Collection<MagicPermanent> targets =
            game.filterPermanents(NONLAND_PERMANENT_WITHOUT_FATE_COUNTER);
                game.doAction(new MagicDestroyAction(targets));
                final List<MagicPermanent> permanents = game.filterPermanents(MagicTargetFilterFactory.PERMANENT);
                for (final MagicPermanent permanent : permanents) {   
                    game.doAction(new MagicChangeCountersAction(
                        permanent,
                        MagicCounterType.Fate,
                        permanent.getCounters(MagicCounterType.Fate)
                    ));
            }   
        }
    }
]
PalladiaMors
 
Posts: 343
Joined: 12 Jul 2014, 17:40
Has thanked: 36 times
Been thanked: 22 times

Re: Card Contributions

Postby melvin » 16 Mar 2015, 00:25

PalladiaMors wrote:besides the fact that you can't choose the order of effects in the entwined version
You can't choose the order according to 702.41b
702.41b wrote:If the entwine cost was paid, follow the text of each of the
modes in the order written on the card when the spell resolves.
Draw before Demon is correct as Draw is mode 1 and Demon is mode 2.

PalladiaMors wrote:Firemind down today, so posting the cards here.
Cards on the forum is rather error prone to integrate, please submit to firemind.ch when it is back up. Thanks.
User avatar
melvin
AI Programmer
 
Posts: 1062
Joined: 21 Mar 2010, 12:26
Location: Singapore
Has thanked: 36 times
Been thanked: 459 times

Re: Card Contributions

Postby PalladiaMors » 19 Mar 2015, 02:24

Gave my first try to a planeswalker, Garruk Relentless / Garruk, the Veil-Cursed. Unfortunately, I'm having problems with the transformation. Normally I'd drop it, but this one was a lot of work, so I though I'd better ask for help.

Code: Select all
name=Garruk Relentless
image=http://mtgimage.com/card/garruk%20relentless.jpg
value=2.500
rarity=M
type=Planeswalker
subtype=Garruk
cost={3}{G}
ability=loyalty 3
transform=Garruk, the Veil-Cursed
timing=main
requires_groovy_code
oracle=When Garruk Relentless has two or fewer loyalty counters on him, transform him. 0: Garruk Relentless deals 3 damage to target creature. That creature deals damage equal to its power to him. 0: Put a 2/2 green Wolf creature token onto the battlefield.
Code: Select all
[
    new MagicStatic(MagicLayer.Game) {
        @Override
        public boolean condition(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
            return source.getCounters(MagicCounterType.Loyalty) <= 2;
        }
        @Override
        public void modGame(final MagicPermanent source, final MagicGame game) {
            game.doAction(new MagicTransformAction(source));
        }
    },
    new MagicPlaneswalkerActivation(0) {
        @Override
        public MagicEvent getPermanentEvent(final MagicPermanent source,final MagicPayedCost payedCost) {
            return new MagicEvent(
                source,
                MagicTargetChoice.NEG_TARGET_CREATURE,
                this,
                "SN deals 3 damage to target creature. That creature deals damage equal to its power to him."
            );
        }
        @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            event.processTargetPermanent(game, {
                game.doAction(new MagicDealDamageAction(event.getSource(),it,3));
                game.doAction(new MagicDealDamageAction(it,event.getPermanent(),it.getPower()));
            });
        }
    },
    new MagicPlaneswalkerActivation(0) {
        @Override
        public MagicEvent getPermanentEvent(final MagicPermanent source,final MagicPayedCost payedCost) {
             return new MagicEvent(
                source,
                this,
                "Put a 2/2 green Wolf creature token onto the battlefield."
            );
       }
        @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            game.doAction(new MagicPlayTokenAction(event.getPlayer(),TokenCardDefinitions.get("2/2 green Wolf creature token")));
        }
    }
]
Code: Select all
name=Garruk, the Veil-Cursed
image=http://mtgimage.com/card/garruk%2C%20the%20veil-cursed.jpg
value=2.500
rarity=M
type=Planeswalker
subtype=Garruk
color=bg
transform=Garruk Relentless
timing=main
requires_groovy_code
oracle=+1: Put a 1/1 black Wolf creature token with deathtouch onto the battlefield. −1: Sacrifice a creature. If you do, search your library for a creature card, reveal it, put it into your hand, then shuffle your library. −3: Creatures you control gain trample and get +X/+X until end of turn, where X is the number of creature cards in your graveyard.
Code: Select all
[
    new MagicPlaneswalkerActivation(1) {
        @Override
        public MagicEvent getPermanentEvent(final MagicPermanent source,final MagicPayedCost payedCost) {
            return new MagicEvent(
                source,
                this,
                "Put a 1/1 black Wolf creature token with deathtouch onto the battlefield."
            );
        }
        @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            game.doAction(new MagicPlayTokenAction(event.getPlayer(),TokenCardDefinitions.get("1/1 black Wolf creature token with deathtouch")));
        }
    },
    new MagicPlaneswalkerActivation(-1) {
        @Override
        public MagicEvent getPermanentEvent(final MagicPermanent source,final MagicPayedCost payedCost) {
             return new MagicEvent(
                source,
                this,
                "Sacrifice a creature. If you do, search your library for a creature card, reveal it, put it into your hand, then shuffle your library."
            );
       }
        @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            final MagicEvent sac = new MagicSacrificePermanentEvent(event.getSource(),event.getPlayer(),MagicTargetChoice.SACRIFICE_CREATURE);
            if (sac.isSatisfied()) {
                final List<MagicCard> choiceList = event.getPlayer().filterCards(MagicTargetFilterFactory.CREATURE_CARD_FROM_LIBRARY);
                game.addEvent(new MagicSearchToLocationEvent(
                    event,
                    new MagicFromCardListChoice(choiceList, 1, true),
                    MagicLocationType.OwnersHand
                ));           }   
       }
    },
    new MagicPlaneswalkerActivation(-3) {
        @Override
        public MagicEvent getPermanentEvent(final MagicPermanent source,final MagicPayedCost payedCost) {
            return new MagicEvent(
                source,
                this,
                "Creatures you control gain trample and get +X/+X until end of turn, where X is the number of creature cards in your graveyard."
            );
        }
        @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            final int X = game.filterCards(event.getPlayer(), MagicTargetFilterFactory.CREATURE_CARD_FROM_GRAVEYARD).size(); 
            final Collection<MagicPermanent> targets = game.filterPermanents(
                event.getPlayer(),
                MagicTargetFilterFactory.CREATURE_YOU_CONTROL
            );
            for (final MagicPermanent target : targets) {
                game.doAction(new MagicGainAbilityAction(target, MagicAbility.Trample));
                game.doAction(new MagicChangeTurnPTAction(target, X, X));            }     
        }
    }
]
I've done the 1/1 token also. It's crashing erratically during play, pointing at the transformation. I don't know how to get that part right, please help if possible!

Edit: Submitted fixes for Worldgorger Dragon, Wormfang Behemoth and Slithermuse. Sorry for not playtesting those better :oops:
Last edited by PalladiaMors on 19 Mar 2015, 03:16, edited 1 time in total.
PalladiaMors
 
Posts: 343
Joined: 12 Jul 2014, 17:40
Has thanked: 36 times
Been thanked: 22 times

Re: Card Contributions

Postby melvin » 19 Mar 2015, 03:00

The first ability is a state-triggered ability, so it should be
Code: Select all
def EFFECT = MagicRuleEventAction.create("Transform SN.");
[
    new MagicStatic(MagicLayer.Game) {
        @Override
        public boolean condition(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
            return source.getCounters(MagicCounterType.Loyalty) <= 2;
        }
        @Override
        public void modGame(final MagicPermanent source, final MagicGame game) {
            game.doAction(new MagicPutStateTriggerOnStackAction(
                 EFFECT.getEvent(source)
            ));               
        }
    },
    ...
]
User avatar
melvin
AI Programmer
 
Posts: 1062
Joined: 21 Mar 2010, 12:26
Location: Singapore
Has thanked: 36 times
Been thanked: 459 times

Re: Card Contributions

Postby PalladiaMors » 19 Mar 2015, 03:11

Now it transforms, but none of Veil-Cursed's abilities can be activated. I admit I currently don't have the pictures, so it's been kind of difficult to playtest properly. Oh and please notice the edit about the fixes above, those 3 cards are currently completely broken. I should really playtest more thoroughly, but sometimes I don't have enough time, I'm sorry about that.

Edit: I think I know what's going on with this: it doesn't have the ability=loyalty, so it's not able to work properly as a planeswalker. I don't think I'm capable of doing this one, after all - my bad for bringing this up, I should've realized it was a tough card, just forget it.
PalladiaMors
 
Posts: 343
Joined: 12 Jul 2014, 17:40
Has thanked: 36 times
Been thanked: 22 times

Re: Card Contributions

Postby melvin » 19 Mar 2015, 05:51

PalladiaMors wrote:Now it transforms, but none of Veil-Cursed's abilities can be activated.
It looks like you are missing the hidden property on the transformed face, see https://github.com/magarena/magarena/bl ... _Fiend.txt for an example. We should have this in the game, please email what you've got so far to magarena@googlegroups.com

PalladiaMors wrote:Oh and please notice the edit about the fixes above, those 3 cards are currently completely broken.
Fixes integrated, do take note of MagicWhenSelfLeavesPlayTrigger. Updated in https://github.com/magarena/magarena/co ... cd70da9625
User avatar
melvin
AI Programmer
 
Posts: 1062
Joined: 21 Mar 2010, 12:26
Location: Singapore
Has thanked: 36 times
Been thanked: 459 times

Re: Card Contributions

Postby muppet » 19 Mar 2015, 12:05

Ok I'll keep a look out for cards marked main that should be something else. Does it also stop the ai using any abilities outside of main too e.g. Sakura Tribal Elder is marked main but you might quite often want to sacrifice it at other times?
muppet
Tester
 
Posts: 590
Joined: 03 Aug 2011, 14:37
Has thanked: 33 times
Been thanked: 30 times

Re: Card Contributions

Postby PalladiaMors » 19 Mar 2015, 13:02

melvin wrote:We should have this in the game, please email what you've got so far to magarena@googlegroups.com
It does works after adding the "hidden" word, so I'm trying to submit through Firemind.

@muppet, permanents with activated abilities can have various different timing hints, one to guide the AI to cast the card, and others to guide it when activating its abilities. For instance, see Scavenging Ooze. The script file has timing=main, which is standard for creatures. That hint is related to when the card should be cast. If you have a look at the groovy file, where its ability is coded, you'll see on the third line "new MagicActivationHints(MagicTiming.Pump)". That hint guides it about when to activate this ability.

Sakura-Tribe Elder is done completely without groovy, so its ability is hard coded in the main code. If you can locate this ability in there, it should have a specific timing hint as well.

By the way, I didn't manage to get through that change to Snapcaster Mage's timing hint, it would probably be a good idea if you could post it as a bug report in the 1.59 bugs topic. That's a very played card and that timing hint could be improved.
PalladiaMors
 
Posts: 343
Joined: 12 Jul 2014, 17:40
Has thanked: 36 times
Been thanked: 22 times

PreviousNext

Return to Magarena

Who is online

Users browsing this forum: No registered users and 29 guests


Who is online

In total there are 29 users online :: 0 registered, 0 hidden and 29 guests (based on users active over the past 10 minutes)
Most users ever online was 4143 on 23 Jan 2024, 08:21

Users browsing this forum: No registered users and 29 guests

Login Form