It is currently 07 Jul 2021, 21:40
   
Text Size

Adding new cards with Groovy

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

Re: Adding new cards with Groovy

Postby ember hauler » 23 Sep 2013, 16:52

And another one, but I guess Magarena should be updated to deal with minotaurs (v1.41 crashes with "unknown target filter "minotaur creatures you control""):

Image

Code: Select all
name=Rageblood Shaman
url=http://magiccards.info/ths/en/138.html
image=http://magiccards.info/scans/en/ths/138.jpg
value=4.464
rarity=R
type=Creature
subtype=Minotaur,Shaman
cost={1}{R}{R}
pt=2/3
ability=trample;\
        lord other minotaur creatures you control get +1/+1;\
        lord other minotaur creatures you control have trample
static=player
timing=main
ember hauler
 
Posts: 79
Joined: 14 Aug 2013, 08:13
Has thanked: 27 times
Been thanked: 14 times

Re: Adding new cards with Groovy

Postby ember hauler » 23 Sep 2013, 17:13

One more card, also from Theros, seems to be working:

Image

Code: Select all
name=Mistcutter Hydra
url=http://magiccards.info/ths/en/162.html
image=http://magiccards.info/scans/en/ths/162.jpg
value=4.281
rarity=R
type=Creature
ability=can't be countered;haste;protection from blue
subtype=Hydra
cost={X}{G}
timing=main
requires_groovy_code
Code: Select all
[
    new MagicWhenComesIntoPlayTrigger() {
        @Override
        public MagicEvent executeTrigger(
            final MagicGame game,
            final MagicPermanent permanent,
            final MagicPayedCost payedCost) {
            game.doAction(new MagicChangeCountersAction(
                permanent,
                MagicCounterType.PlusOne,
                payedCost.getX(),
                true
            ));
            return MagicEvent.NONE;
        }
    }
]
ember hauler
 
Posts: 79
Joined: 14 Aug 2013, 08:13
Has thanked: 27 times
Been thanked: 14 times

Re: Adding new cards with Groovy

Postby ember hauler » 23 Sep 2013, 17:20

And another one from Theros:

Image

Code: Select all
name=Sylvan Caryatid
url=http://magiccards.info/ths/en/180.html
image=http://magiccards.info/scans/en/ths/180.jpg
value=4.657
rarity=R
type=Creature
subtype=Plant
cost={1}{G}
pt=0/3
ability=defender;hexproof;tap add mana any
timing=main
ember hauler
 
Posts: 79
Joined: 14 Aug 2013, 08:13
Has thanked: 27 times
Been thanked: 14 times

Re: Adding new cards with Groovy

Postby ember hauler » 23 Sep 2013, 17:33

More Theros.

Image

Code: Select all
name=Opaline Unicorn
url=http://magiccards.info/ths/en/218.html
image=http://magiccards.info/scans/en/ths/218.jpg
value=3.714
rarity=C
type=Creature,Artifact
subtype=Unicorn
cost={3}
pt=1/2
ability=tap add mana any
timing=main
ember hauler
 
Posts: 79
Joined: 14 Aug 2013, 08:13
Has thanked: 27 times
Been thanked: 14 times

Re: Adding new cards with Groovy

Postby melvin » 24 Sep 2013, 06:05

Thanks, ember hauler, for the first batch of Theros cards :) Your Rageblook Shaman scripts works perfectly in 1.42 using the new generic support for creature type filters. Previously we would have to define custom filters, now the engine is able to generate filters on the fly for simple creature restrictions.
User avatar
melvin
AI Programmer
 
Posts: 1062
Joined: 21 Mar 2010, 12:26
Location: Singapore
Has thanked: 36 times
Been thanked: 458 times

Re: Adding new cards with Groovy

Postby jerichopumpkin » 24 Sep 2013, 07:58

Here I am again with other (broken) Slivers, asking for guidance and help.
I've included the crash report for each card:

Pulmonic_Sliver.txt
Code: Select all
name=Pulmonic Sliver
url=http://magiccards.info/ts/en/36.html
image=http://magiccards.info/scans/en/ts/36.jpg
value=4.170
rarity=R
type=Creature
subtype=Sliver
cost={3}{W}{W}
pt=3/3
ability=lord all sliver creatures have flying
timing=main
static=all
requires_groovy_code
Pulmonic_Sliver.groovy
Code: Select all
[
    new MagicWhenDiesTrigger() {
        @Override
        public MagicEvent getEvent(final MagicPermanent permanent) {
           
            return (permanent.hasSubType(MagicSubType.Sliver)) ?
                new MagicEvent(
                    permanent,
                    new MagicSimpleMayChoice(
                        MagicSimpleMayChoice.PLAY_TOKEN,
                        1,
                        MagicSimpleMayChoice.DEFAULT_NONE
                    ),
                    this,
                    "you may put SN on top of its owner's library."
                ):
                MagicEvent.NONE;
        }
        @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            if (event.isYes()) {
                game.doAction(new MagicRemoveFromPlayAction(event.getSource(),MagicLocationType.TopOfOwnersLibrary));
            }
        }
    }
]
Pulmonic Sliver crash report:
CRASH REPORT FOR MAGARENA THREAD Thread[AWT-EventQueue-0,6,main]
CREATED ON 2013/09/23 19:35:55
MAGARENA VERSION 1.41, JRE 1.7.0_25, OS Windows 7_6.1 x86

Turn : 1 Phase : Mulligan Step : Begin Player : Jericho Score : 0
0] Player : Jericho Life : 20 Delayed : Total=0
1] Player : Computer Life : 20 Delayed : Total=0
Stack : 0
Score = 0

Exception from controller.runGame: startup failed:
C:\Users\Torre\Desktop\Magarena-1.41\Magarena\scripts\Pulmonic_Sliver.groovy: 22: [Static type checking] - Cannot find matching method magic.model.action.MagicRemoveFromPlayAction#<init>(magic.model.MagicSource, magic.model.MagicLocationType). Please check if the declared type is right and if the method exists.@ line 22, column 31.
game.doAction(new MagicRemoveFromPlayAction(event.getSource(), MagicLocationType.TopOfOwnersLibrary));

1 error

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
C:\Users\Torre\Desktop\Magarena-1.41\Magarena\scripts\Pulmonic_Sliver.groovy: 22: [Static type checking] - Cannot find matching method magic.model.action.MagicRemoveFromPlayAction#<init>(magic.model.MagicSource, magic.model.MagicLocationType). Please check if the declared type is right and if the method exists.@ line 22, column 31.
game.doAction(new MagicRemoveFromPlayAction( event.getSource(), MagicLocationType.TopOfOwnersLibrary));


Psionic_Sliver.txt
Code: Select all
name=Psionic Sliver
url=http://magiccards.info/ts/en/72.html
image=http://magiccards.info/scans/en/ts/72.jpg
value=3.667
rarity=C
type=Creature
subtype=Sliver
cost={4}{U}
pt=2/2
static=all
timing=main
requires_groovy_code
Psionic_Sliver.groovy
Code: Select all
def PsionicDamage = new MagicPermanentActivation(
        new MagicActivationHints(MagicTiming.Pump),
        "Psionic"
    ) {

         @Override
        public Iterable<MagicEvent> getCostEvent(final MagicPermanent source) {
            return [ new MagicTapEvent(source)];
        }

        @Override
        public MagicEvent getPermanentEvent(final MagicPermanent source, final MagicPayedCost payedCost) {
            return new MagicEvent(
                source,
                MagicTargetChoice.NEG_TARGET_CREATURE_OR_PLAYER,
                new MagicDamageTargetPicker(2),
                this,
                "SN deals 2 damage to target creature or player\$ and 3 damage to itself."
            );
        }

        @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            final MagicSource source=event.getSource();
            event.processTarget(game,new MagicTargetAction() {
                public void doAction(final MagicTarget target) {
                    final MagicDamage damage1=new MagicDamage(source,target,2);
                    game.doAction(new MagicDealDamageAction(damage1));
                    final MagicDamage damage2=new MagicDamage(source,source,3);
                    game.doAction(new MagicDealDamageAction(damage2));
                }
            });
        }
    };

[
    new MagicStatic(
        MagicLayer.Ability,
        MagicTargetFilter.TARGET_SLIVER
    ) {
        @Override
        public void modAbilityFlags(final MagicPermanent source,final MagicPermanent permanent,final Set<MagicAbility> flags) {
            permanent.addAbility(PsionicDamage);
        }
    }
]
Psionic Sliver crash report:
CRASH REPORT FOR MAGARENA THREAD Thread[AWT-EventQueue-0,6,main]
CREATED ON 2013/09/23 19:28:22
MAGARENA VERSION 1.41, JRE 1.7.0_25, OS Windows 7_6.1 x86

Turn : 1 Phase : Mulligan Step : Begin Player : Jericho Score : 0
0] Player : Jericho Life : 20 Delayed : Total=0
1] Player : Computer Life : 20 Delayed : Total=0
Stack : 0
Score = 0

Exception from controller.runGame: startup failed:
C:\Users\Torre\Desktop\Magarena-1.41\Magarena\scripts\Psionic_Sliver.groovy: 30: [Static type checking] - Cannot find matching method magic.model.MagicDamage#<init>(magic.model.MagicSource, magic.model.MagicSource, int). Please check if the declared type is right and if the method exists.
@ line 30, column 49.
final MagicDamage damage2 = new MagicD
^

1 error

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
C:\Users\Torre\Desktop\Magarena-1.41\Magarena\scripts\Psionic_Sliver.groovy: 30: [Static type checking] - Cannot find matching method magic.model.MagicDamage#<init>(magic.model.MagicSource, magic.model.MagicSource, int). Please check if the declared type is right and if the method exists.
@ line 30, column 49.
final MagicDamage damage2 = new MagicD


Forbidden_Orchard.txt
Code: Select all
name=Forbidden Orchard
url=http://magiccards.info/v12/en/6.html
image=http://magiccards.info/scans/en/v12/6.jpg
value=4.375
rarity=M
type=Land
mana=b1g1r1u1w1
timing=land
requires_groovy_code
Forbidden_Orchard.groovy
Code: Select all
[
    new MagicManaActivation(
        MagicManaType.ALL_TYPES,
        2
    ) {
        @Override
        public Iterable<MagicEvent> getCostEvent(final MagicPermanent permanent) {
            return [
                    new MagicTapEvent(permanent)
                ];   
        }
      @Override
        public MagicEvent getPermanentEvent(final MagicPermanent source, final MagicPayedCost payedCost) {
           return  new MagicEvent(
            permanent,
            MagicTargetChoice.TARGET_OPPONENT,
            this,
            "Target opponent\$ puts a 1/1 colorless Spirit creature token onto the battlefield."
         );
        }   
      @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            event.processTargetPlayer(game,new MagicPlayerAction() {
                public void doAction(final MagicPlayer player) {
                    game.doAction(new MagicPlayTokenAction(
                  player,
                  TokenCardDefinitions.get("Spirit1")
               ));
                }
            });
         
        }
    }
]
Forbidden Orchard crash report:
CRASH REPORT FOR MAGARENA THREAD Thread[AWT-EventQueue-0,6,main]
CREATED ON 2013/09/23 19:41:06
MAGARENA VERSION 1.41, JRE 1.7.0_25, OS Windows 7_6.1 x86

Turn : 1 Phase : Mulligan Step : Begin Player : Jericho Score : 0
0] Player : Jericho Life : 20 Delayed : Total=0
1] Player : Computer Life : 20 Delayed : Total=0
Stack : 0
Score = 0

Exception from controller.runGame: startup failed:
C:\Users\Torre\Desktop\Magarena-1.41\Magarena\scripts\Forbidden_Orchard.groovy: 15: [Static type checking] - The variable [permanent] is undeclared.
@ line 15, column 5.
permanent,
^

C:\Users\Torre\Desktop\Magarena-1.41\Magarena\scripts\Forbidden_Orchard.groovy: 14: [Static type checking] - Cannot find matching method magic.model.event.MagicEvent#<init>(java.lang.Object, magic.model.choice.MagicTargetChoice, Forbidden_Orchard$1, java.lang.String). Please check if the declared type is right and if the method exists.
@ line 14, column 20.
return new MagicEvent(
^

2 errors

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
C:\Users\Torre\Desktop\Magarena-1.41\Magarena\scripts\Forbidden_Orchard.groovy: 15: [Static type checking] - The variable [permanent] is undeclared.
@ line 15, column 5.
permanent,
^

C:\Users\Torre\Desktop\Magarena-1.41\Magarena\scripts\Forbidden_Orchard.groovy: 14: [Static type checking] - Cannot find matching method magic.model.event.MagicEvent#<init>(java.lang.Object, magic.model.choice.MagicTargetChoice, Forbidden_Orchard$1, java.lang.String). Please check if the declared type is right and if the method exists.
@ line 14, column 20.
return new MagicEvent(
^

The one that really puzzles me is Psionic, it shold work, after all it's nearly identical to Goblin Artillery, it only changes the target of the 2nd damage...
jerichopumpkin
 
Posts: 212
Joined: 12 Sep 2013, 11:21
Has thanked: 19 times
Been thanked: 13 times

Re: Adding new cards with Groovy

Postby jerichopumpkin » 25 Sep 2013, 21:16

I'm posting here the Kaldra Set, because on projectfiremind I could not submit the script for the token. By the way, I've used a fanmade token, and I would like to thank the anonymous guy who made it for everyone to use.

Image
Sword_of_Kaldra.txt
Code: Select all
name=Sword of Kaldra
url=http://magiccards.info/mi/en/251.html
image=http://magiccards.info/scans/en/mi/251.jpg
value=4.344
rarity=R
type=Legendary,Artifact
subtype=Equipment
cost={4}
equip={4}
given_pt=5/5
timing=equipment
requires_groovy_code
Sword_of_Kaldra.groovy
Code: Select all
[   
   new MagicStatic(
        MagicLayer.Ability,
        MagicTargetFilter.TARGET_EQUIPMENT
    ) {
        @Override
        public void modAbilityFlags(final MagicPermanent source,final MagicPermanent permanent,final Set<MagicAbility> flags) {
            flags.add(MagicAbility.Indestructible);
        }
      @Override
        public boolean condition(
                final MagicGame game,
                final MagicPermanent source,
                final MagicPermanent target) {
            return (target.getName() == "Sword of Kaldra" || target.getName() == "Shield of Kaldra" || target.getName() == "Helm of Kaldra");
        }
    },
   new MagicWhenOtherComesIntoPlayTrigger() {
        @Override
        public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent,final MagicPermanent otherPermanent) {
            return (otherPermanent.isCreature() &&
               otherPermanent.getName() == "Kaldra" &&
                    otherPermanent.isFriend(permanent)) ?
                new MagicEvent(
                    permanent,
                    otherPermanent,
                    this,
                    "Attach SN to RN."
                ) :
                MagicEvent.NONE;
        }

        @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            game.doAction(new MagicAttachAction(
                event.getPermanent(),
                event.getRefPermanent()
            ));
        }
    }
]
Image
Shield_of_Kaldra.txt
Code: Select all
name=Shield of Kaldra
url=http://magiccards.info/ds/en/139.html
image=http://magiccards.info/scans/en/ds/139.jpg
value=3.924
rarity=R
type=Legendary,Artifact
subtype=Equipment
cost={4}
equip={4}
given_ability=indestructible
timing=equipment
requires_groovy_code
Shield_of_Kaldra.groovy
Code: Select all
[   
   new MagicStatic(
        MagicLayer.Ability,
        MagicTargetFilter.TARGET_EQUIPMENT
    ) {
        @Override
        public void modAbilityFlags(final MagicPermanent source,final MagicPermanent permanent,final Set<MagicAbility> flags) {
            flags.add(MagicAbility.Indestructible);
        }
      @Override
        public boolean condition(
                final MagicGame game,
                final MagicPermanent source,
                final MagicPermanent target) {
            return (target.getName() == "Sword of Kaldra" || target.getName() == "Shield of Kaldra" || target.getName() == "Helm of Kaldra");
        }
    },
   new MagicWhenOtherComesIntoPlayTrigger() {
        @Override
        public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent,final MagicPermanent otherPermanent) {
            return (otherPermanent.isCreature() &&
               otherPermanent.getName() == "Kaldra" &&
                    otherPermanent.isFriend(permanent)) ?
                new MagicEvent(
                    permanent,
                    otherPermanent,
                    this,
                    "Attach SN to RN."
                ) :
                MagicEvent.NONE;
        }

        @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            game.doAction(new MagicAttachAction(
                event.getPermanent(),
                event.getRefPermanent()
            ));
        }
    }
]
Image
Helm_of_Kaldra.txt
Code: Select all
name=Helm of Kaldra
url=http://magiccards.info/5dn/en/131.html
image=http://magiccards.info/scans/en/5dn/131.jpg
value=4.019
rarity=R
type=Legendary,Artifact
subtype=Equipment
cost={3}
equip={2}
given_ability=first strike;trample;haste
timing=equipment
requires_groovy_code
Helm_of_Kaldra.groovy
Code: Select all
[   
   new MagicPermanentActivation(
        new MagicActivationHints(MagicTiming.Token),                                                                                                                                       
        "Kaldra"                                                                                                                                                                               
    ) {
      @Override
        public Iterable<MagicEvent> getCostEvent(final MagicPermanent source) {
            return [new MagicPayManaCostEvent(source,"{1}")];
        }
      @Override
        public MagicEvent getPermanentEvent(final MagicPermanent source,final MagicPayedCost payedCost) {
            final MagicPlayer player = source.getController();
         final Collection<MagicPermanent> targets =
                    player.getGame().filterPermanents(player,MagicTargetFilter.TARGET_EQUIPMENT);
         boolean sword = false;
         boolean shield = false;
         boolean helm = false;
         for (final MagicPermanent equip : targets) {
            if (equip.getName() == "Sword of Kaldra"){ sword = true;}
            if (equip.getName() == "Shield of Kaldra"){ shield = true;}
            if (equip.getName() == "Helm of Kaldra"){ helm = true;}
            }
         
         return (sword && shield && helm)?
            new MagicEvent(
               source,
               this,
               "PN puts a legendary 4/4 colorless Avatar creature token named Kaldra onto the battlefield."
                ) :
            MagicEvent.NONE;
        }
      @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            game.doAction(new MagicPlayTokenAction(event.getPlayer(), TokenCardDefinitions.get("Kaldra")));
        }
   },
   new MagicWhenOtherComesIntoPlayTrigger() {
        @Override
        public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent,final MagicPermanent otherPermanent) {
            return (otherPermanent.isCreature() &&
               otherPermanent.getName() == "Kaldra" &&
                    otherPermanent.isFriend(permanent)) ?
                new MagicEvent(
                    permanent,
                    otherPermanent,
                    this,
                    "Attach SN to RN."
                ) :
                MagicEvent.NONE;
        }

        @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            game.doAction(new MagicAttachAction(
                event.getPermanent(),
                event.getRefPermanent()
            ));
        }
    }
]
Image
Kaldra.txt
Code: Select all
name=Kaldra
token=Kaldra
image=http://mtgcardsmith.com/view/cards/1376735874.png
value=4
type=Legendary,Creature
subtype=Avatar
color=
cost={0}
pt=4/4
edit: I've made a mistake, the token isn't an artifact creature, now the script is correct
Last edited by jerichopumpkin on 28 Sep 2013, 15:46, edited 3 times in total.
jerichopumpkin
 
Posts: 212
Joined: 12 Sep 2013, 11:21
Has thanked: 19 times
Been thanked: 13 times

Re: Adding new cards with Groovy

Postby mike » 26 Sep 2013, 22:06

Finally got around to adding Theros on Project Firemind. Card submissions for Theros cards should work now.

The thing with the tokens is unfortunately a known restriction due to my approach to link all scripts to actual cards. I see now that this might be a bit too limiting. I'll see if I can add the option to mark a script submission as token to override this requirement.
User avatar
mike
Programmer
 
Posts: 128
Joined: 05 Jul 2013, 17:00
Has thanked: 0 time
Been thanked: 29 times

Re: Adding new cards with Groovy

Postby melvin » 29 Sep 2013, 14:16

@mike: Thanks for the improvements!

@jerichopumpkin: Love the Kaldra set, it is very flavorful. I've merged in a simplified version as it was not necessary for each artifact to have the MagicWhenOtherComesIntoPlayTrigger trigger. See https://code.google.com/p/magarena/sour ... dra.groovy

Fixed Pulmonic Sliver, see below The tricky bit is that it should be the rarely used MagicWouldBeMovedTrigger (other cards are Rest in Peace and Dryad Militant) as the card never actually hits the graveyard (important for things that trigger of other things entering the graveyard).

For Psionic Sliver, your script is essentially correct except for a technicality, a MagicSource variable cannot be used in place of a MagicTarget, however a MagicPermanent is both a MagicSource and a MagicTarget. So the trick is to retrieve the permanent with event.getPermanent() then it can be used as both the source and target of damage.

Forbidden Orchard cannot be scripted now as we do not track the reason why a permanent is tapped, so we can't tell when it is tapped for mana or for other reasons.

Image

Magarena/scripts/Pulmonic_Sliver.txt
Code: Select all
name=Pulmonic Sliver
url=http://magiccards.info/ts/en/36.html
image=http://magiccards.info/scans/en/ts/36.jpg
value=4.170
rarity=R
type=Creature
subtype=Sliver
cost={3}{W}{W}
pt=3/3
ability=lord all sliver creatures have flying
timing=main
static=all
requires_groovy_code
Magarena/scripts/Pulmonic_Sliver.groovy
Code: Select all
def PulmonicTrigger = new MagicWouldBeMovedTrigger() {
    @Override
    public MagicEvent executeTrigger(final MagicGame game, final MagicPermanent permanent, final MagicMoveCardAction act) {
        if (permanent == act.permanent && act.getToLocation() == MagicLocationType.Graveyard) {
            //disable the current move action
            act.setToLocation(MagicLocationType.Play);

            game.addEvent(new MagicEvent(
                permanent,
                new MagicMayChoice("Put ${permanent} on top of its owner's library?"),
                act.card,
                {
                    final MagicGame G, final MagicEvent E ->
                    if (E.isYes()) {
                        G.doAction(new MagicMoveCardAction(E.getRefCard(), act.fromLocation, MagicLocationType.TopOfOwnersLibrary));
                    } else {
                        //needs to be delayed so it occurs after trigger is remove
                        G.addDelayedAction(new MagicMoveCardAction(E.getRefCard(), act.fromLocation, MagicLocationType.Graveyard));
                    }
                } as MagicEventAction,
                "PN may\$ put SN on top of its owner's library."
            ));
        }
        return MagicEvent.NONE;
    }
};

[
    new MagicStatic(
        MagicLayer.Ability,
        MagicTargetFilter.TARGET_SLIVER
    ) {
        @Override
        public void modAbilityFlags(final MagicPermanent source,final MagicPermanent permanent,final Set<MagicAbility> flags) {
            permanent.addAbility(PulmonicTrigger);
        }
    }
]
User avatar
melvin
AI Programmer
 
Posts: 1062
Joined: 21 Mar 2010, 12:26
Location: Singapore
Has thanked: 36 times
Been thanked: 458 times

Re: Adding new cards with Groovy

Postby jerichopumpkin » 02 Oct 2013, 12:06

And yet again, thank you Melvin, you are the best!
melvin wrote:@jerichopumpkin: Love the Kaldra set, it is very flavorful. I've merged in a simplified version as it was not necessary for each artifact to have the MagicWhenOtherComesIntoPlayTrigger trigger. See https://code.google.com/p/magarena/sour ... dra.groovy
I knew there was a cleaner method to do that, but I had an error I could not get rid of, so I surrendered to a simpler solution, even though much more inelegant :)

melvin wrote:Fixed Pulmonic Sliver, see below The tricky bit is that it should be the rarely used MagicWouldBeMovedTrigger (other cards are Rest in Peace and Dryad Militant) as the card never actually hits the graveyard (important for things that trigger of other things entering the graveyard).
I should have searched more carefully for a fitting example, Dryad Militant is even in one of my decks... :oops:

melvin wrote:For Psionic Sliver, your script is essentially correct except for a technicality, a MagicSource variable cannot be used in place of a MagicTarget, however a MagicPermanent is both a MagicSource and a MagicTarget. So the trick is to retrieve the permanent with event.getPermanent() then it can be used as both the source and target of damage.
:oops: :oops: :oops: It didn't even crossed my mind that this could be the problem. This will avoid me a lot of trouble with the next cards :wink:

melvin wrote:Forbidden Orchard cannot be scripted now as we do not track the reason why a permanent is tapped, so we can't tell when it is tapped for mana or for other reasons.
Oh well, I had a couple decks in mind with it, but one of them required Donate (which is unimplementable for now), so it's no big deal...

edit: I almost forgot! I want to add Ensnaring Bridge, but I don't know where to find the definition of abilities, so I can figure out the "can't attack" part of "can't attack or block". Can someone point me out where to find them in the project?
jerichopumpkin
 
Posts: 212
Joined: 12 Sep 2013, 11:21
Has thanked: 19 times
Been thanked: 13 times

Re: Adding new cards with Groovy

Postby melvin » 02 Oct 2013, 12:36

jerichopumpkin wrote:I almost forgot! I want to add Ensnaring Bridge, but I don't know where to find the definition of abilities, so I can figure out the "can't attack" part of "can't attack or block". Can someone point me out where to find them in the project?
Hmm, now that you mention it, we don't have a "can't attack" ability, but we do have "can't block" (MagicAbility.CannotBlock) and "can't attack or block" (MagicAbility.CannotAttackOrBlock). Technically these are not really abilities, I've been thinking of cleaning up this part, they should be under the "state" of the permanent. Oh, wait we actually have a MagicPermanentState.CannotAttack, unfortunately MagicPermanentState shouldn't be modified by continuous effects. At some future point, we'll shift all these to MagicPermanentState and integrate it into the continuous effect system.

For now I'll add in a MagicAbility.CannotAttack for the next release. You could test with MagicAbility.CannotAttackOrBlock first and change it when submitting to MagicAbility.CannotAttack.

The full list of abilities should be listed at https://code.google.com/p/magarena/wiki ... ntingCards but I've been lazy, for the nitty gritty you can always refer to the actual implementation in https://code.google.com/p/magarena/sour ... ility.java
User avatar
melvin
AI Programmer
 
Posts: 1062
Joined: 21 Mar 2010, 12:26
Location: Singapore
Has thanked: 36 times
Been thanked: 458 times

Re: Adding new cards with Groovy

Postby jerichopumpkin » 03 Oct 2013, 16:34

Image
Blaze_Commando.txt
Code: Select all
name=Blaze Commando
url=http://magiccards.info/dgm/en/56.html
image=http://magiccards.info/scans/en/dgm/56.jpg
value=4.087
rarity=U
type=Creature
subtype=Minotaur,Soldier
cost={3}{R}{W}
pt=5/3
timing=main
requires_groovy_code
Blaze_Commando.groovy
Code: Select all
def LAST_SOURCE = null;
[
    new MagicWhenDamageIsDealtTrigger() {
        @Override
        public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent,final MagicDamage damage) {
            final MagicSource source=damage.getSource();
         
         if( permanent.isFriend(source) && source.isSpell() &&
                source.getCardDefinition().isSpell() && (!LAST_SOURCE || LAST_SOURCE != source)){
               LAST_SOURCE = source;
               return new MagicEvent(
                  permanent,
                  this,
                  "PN puts two 1/1 red and white Soldier creature token with haste onto the battlefield."
               );
            }else{
                 return MagicEvent.NONE;
            }
        }
        @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            game.doAction(new MagicPlayTokensAction(
                event.getPlayer(),
                TokenCardDefinitions.get("RW Soldier"),
                2
            ));
        }
    }
]
I've added this, but the oracle text says that the ability triggers for each occurence of "deals" in the instant or sorcery you cast, so in the future, my script for Blaze Commando may result broken
jerichopumpkin
 
Posts: 212
Joined: 12 Sep 2013, 11:21
Has thanked: 19 times
Been thanked: 13 times

Re: Adding new cards with Groovy

Postby jerichopumpkin » 03 Oct 2013, 18:59

this couple is truly evil in magarena...
Image
The_Tabernacle_at_Pendrell_Vale.txt
Code: Select all
name=The Tabernacle at Pendrell Vale
url=http://magiccards.info/lg/en/252.html
image=http://magiccards.info/scans/en/lg/252.jpg
value=4.610
rarity=R
type=Legendary,Land
timing=land
requires_groovy_code
The_Tabernacle_at_Pendrell_Vale.groovy
Code: Select all

def TabernacleUpkeep = new MagicAtUpkeepTrigger() {
        @Override
        public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent,final MagicPlayer upkeepPlayer) {
            return permanent.isController(upkeepPlayer) ?
                new MagicEvent(
                    permanent,
                    new MagicMayChoice(
                        new MagicPayManaCostChoice(MagicManaCost.create("{1}"))
                    ),
                    this,
                    "You may\$ pay {1}\$. If you don't, destroy SN."
                ) :
                MagicEvent.NONE;
        }
        @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            if (event.isNo()) {
                game.doAction(new MagicDestroyAction(event.getPermanent()));
            }
        }
    };

[
    new MagicStatic(
        MagicLayer.Ability,
        MagicTargetFilter.TARGET_CREATURE
    ) {
        @Override
        public void modAbilityFlags(final MagicPermanent source,final MagicPermanent permanent,final Set<MagicAbility> flags) {
            permanent.addAbility(TabernacleUpkeep);
        }
    }
]
Image
Pendrell_Mists.txt
Code: Select all
name=Pendrell Mists
url=http://magiccards.info/wl/en/47.html
image=http://magiccards.info/scans/en/wl/47.jpg
value=4.172
rarity=R
type=Enchantment
cost={3}{U}
timing=enchantment
requires_groovy_code
Pendrell_Mists.groovy
Code: Select all
def MistsUpkeep = new MagicAtUpkeepTrigger() {
        @Override
        public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent,final MagicPlayer upkeepPlayer) {
            return permanent.isController(upkeepPlayer) ?
                new MagicEvent(
                    permanent,
                    new MagicMayChoice(
                        new MagicPayManaCostChoice(MagicManaCost.create("{1}"))
                    ),
                    this,
                    "You may\$ pay {1}\$. If you don't, destroy SN."
                ) :
                MagicEvent.NONE;
        }
        @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            if (event.isNo()) {
                game.doAction(new MagicSacrificeAction(event.getPermanent()));
            }
        }
    };

[
    new MagicStatic(
        MagicLayer.Ability,
        MagicTargetFilter.TARGET_CREATURE
    ) {
        @Override
        public void modAbilityFlags(final MagicPermanent source,final MagicPermanent permanent,final Set<MagicAbility> flags) {
            permanent.addAbility(MistsUpkeep);
        }
    }
]
jerichopumpkin
 
Posts: 212
Joined: 12 Sep 2013, 11:21
Has thanked: 19 times
Been thanked: 13 times

Re: Adding new cards with Groovy

Postby jerichopumpkin » 04 Oct 2013, 16:57

Again I need advice with a script... I've made Allosaurus Rider, and I have 2 issues:
- you can cast it with a single green card instead of two
- you can cast it anytime with the alternate cost

here is the code:
Allosaurus_Rider.txt
Code: Select all
name=Allosaurus Rider
url=http://magiccards.info/ptc/en/30.html
image=http://magiccards.info/scans/en/ptc/30.jpg
value=4.051
rarity=R
type=Creature
subtype=Elf,Warrior
cost={5}{G}{G}
pt=1/1
timing=smain
requires_groovy_code
Allosaurus_Rider.groovy
Code: Select all
def TARGET_GREEN_CARD_FROM_HAND = new MagicCardFilterImpl() {
        public boolean accept(final MagicGame game,final MagicPlayer player,final MagicCard target) {
            return target.hasColor(MagicColor.Green);
        }
        public boolean acceptType(final MagicTargetType targetType) {
            return targetType == MagicTargetType.Hand;
        }
    };
   
[
    new MagicCardActivation(
        new MagicActivationHints(MagicTiming.Main),
        "Alt"
    ) {
        public Iterable<MagicEvent> getCostEvent(final MagicCard source) {
            final MagicTargetChoice targetChoice1 = new MagicTargetChoice(
                new MagicTargetFilter.MagicOtherCardTargetFilter(
                    TARGET_GREEN_CARD_FROM_HAND,
                    source
                ),
                MagicTargetHint.None,
                "a green card from your hand"
            );
         final MagicTargetChoice targetChoice2 = new MagicTargetChoice(
                new MagicTargetFilter.MagicOtherCardTargetFilter(
                    TARGET_GREEN_CARD_FROM_HAND,
                    source
                ),
                MagicTargetHint.None,
                "a green card from your hand"
            );
            return [
                new MagicExileCardEvent(source, targetChoice1),
                new MagicExileCardEvent(source, targetChoice2)
            ];
        }
    },
   new MagicCDA() {
        @Override
        public void modPowerToughness(final MagicGame game,final MagicPlayer player,final MagicPowerToughness pt) {
            final int size = player.getNrOfPermanents(MagicType.Land);
            pt.add(size, size);
        }
    }
]
jerichopumpkin
 
Posts: 212
Joined: 12 Sep 2013, 11:21
Has thanked: 19 times
Been thanked: 13 times

Re: Adding new cards with Groovy

Postby melvin » 05 Oct 2013, 01:44

Both are solved with conditions, which is passed as an array before the activation hint. i.e.

Code: Select all
 new MagicCardActivation(
        [TWO_OTHER_GREEN_CARDS_IN_HAND, MagicCondition.CARD_CONDITION]
        new MagicActivationHints(MagicTiming.Main),
        "Alt"
    ) {
...
To follow the card's regular casting restriction (sorcery during main), just use the built-in MagicCondition.CARD_CONDITION. Now that you mentioned it, all the alternate casting cost should include this, but so far we've only had instants so it didn't matter.

To prevent casting with a single green card, you need to define your own activation condition, define following at the start of the script
Code: Select all
    def TWO_OTHER_GREEN_CARDS_IN_HAND = new MagicCondition() {
        public boolean accept(final MagicSource source) {
           //source is the MagicCard
           //obtain MagicGame from source via source.getGame()
           //create a other card filter, same as one in the cost
           //use game.filterCards passing it the player and filter to get a list of other green cards
           //return true if player has at least two other green cards
        }
    };
User avatar
melvin
AI Programmer
 
Posts: 1062
Joined: 21 Mar 2010, 12:26
Location: Singapore
Has thanked: 36 times
Been thanked: 458 times

PreviousNext

Return to Magarena

Who is online

Users browsing this forum: No registered users and 1 guest


Who is online

In total there is 1 user online :: 0 registered, 0 hidden and 1 guest (based on users active over the past 10 minutes)
Most users ever online was 1922 on 07 Jun 2021, 06:01

Users browsing this forum: No registered users and 1 guest

Login Form