Adding new cards with Groovy
by ubeefx
Moderators: melvin, beholder, ubeefx, ShawnieBoy, Lodici, CCGHQ Admins
Re: Adding new cards with Groovy
by 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""):


- 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
by ember hauler » 23 Sep 2013, 17:13
One more card, also from Theros, seems to be working:


- 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
by ember hauler » 23 Sep 2013, 17:20
And another one from Theros:


- 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
by ember hauler » 23 Sep 2013, 17:33
More Theros.


- 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
by 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.
-

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
by 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
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
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
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...
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
- 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));
}
}
}
]
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
- 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);
}
}
]
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
- 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")
));
}
});
}
}
]
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
by 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.

Sword_of_Kaldra.txt

Shield_of_Kaldra.txt

Helm_of_Kaldra.txt

Kaldra.txt

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
- 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()
));
}
}
]

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
- 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()
));
}
}
]

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
- 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()
));
}
}
]

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
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
by 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.
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.
Re: Adding new cards with Groovy
by 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.

Magarena/scripts/Pulmonic_Sliver.txt
@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.

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
- 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);
}
}
]
-

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
by jerichopumpkin » 02 Oct 2013, 12:06
And yet again, thank you Melvin, you are the best!
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
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?
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 inelegantmelvin 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 should have searched more carefully for a fitting example, Dryad Militant is even in one of my decks...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).
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.
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...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.
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
by melvin » 02 Oct 2013, 12:36
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.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?
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
-

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
by jerichopumpkin » 03 Oct 2013, 16:34

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
- 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
));
}
}
]
- jerichopumpkin
- Posts: 212
- Joined: 12 Sep 2013, 11:21
- Has thanked: 19 times
- Been thanked: 13 times
Re: Adding new cards with Groovy
by jerichopumpkin » 03 Oct 2013, 18:59
this couple is truly evil in magarena...

The_Tabernacle_at_Pendrell_Vale.txt

Pendrell_Mists.txt

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
- 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);
}
}
]

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
- 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
by 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
- 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
- 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
by melvin » 05 Oct 2013, 01:44
Both are solved with conditions, which is passed as an array before the activation hint. i.e.
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
new MagicCardActivation(
[TWO_OTHER_GREEN_CARDS_IN_HAND, MagicCondition.CARD_CONDITION]
new MagicActivationHints(MagicTiming.Main),
"Alt"
) {
...
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
}
};
-

melvin - AI Programmer
- Posts: 1062
- Joined: 21 Mar 2010, 12:26
- Location: Singapore
- Has thanked: 36 times
- Been thanked: 458 times
Who is online
Users browsing this forum: No registered users and 1 guest
