Page 17 of 28

Re: Adding new cards with Groovy

PostPosted: 08 Feb 2014, 08:00
by melvin
ShawnieBoy wrote:Hmm, I've tried that, but the computer has a habit of selecting 'Yes' but then not paying the mana.
Your right, I'd forgotten that the auto payment only occurs during MagicStackGetChoicesEvent.java, which occurs for events that go on the stack. In this case, as the event doesn't go on the stack, the payment has to be made manually by evoking event.payManaCost(game) in the isYes() case. See MagicCounterUnlessEvent.java for an example.

Re: Adding new cards with Groovy

PostPosted: 08 Feb 2014, 14:14
by ShawnieBoy
Thanks so much, been trying to get this to work for ages - Did look in the MagicCounterUnlessEvent, but didn't quite see what event.payManaCost(game) was doing. One thing I have noticed though, is that the mana enforcement has kinda gone the other way.

The computer was trying to bounce one of its own creatures (A good thing), but ended up paying the mana instead :(

Re: Adding new cards with Groovy

PostPosted: 10 Feb 2014, 22:04
by jerichopumpkin
I've been trying to add Deus of Calamity, but something is not right. The strange thing is that magarena does not crash, but the game does not start if the card is in one of the decks...
Deus_of_Calamity.txt
Code: Select all
name=Deus of Calamity
url=http://magiccards.info/shm/en/204.html
image=http://magiccards.info/scans/en/shm/204.jpg
value=4.214
rarity=R
type=Creature
subtype=Avatar,Spirit
cost={R/G}{R/G}{R/G}{R/G}{R/G}
pt=6/6
ability=trample
timing=main
requires_groovy_code
Deus_of_Calamity.groovy
Code: Select all
def LAND_YOUR_OPPONENT_CONTROLS = new MagicPermanentFilterImpl() {
    public boolean accept(final MagicGame game,final MagicPlayer player,final MagicPermanent target) {
      return target.isLand() && target.isOpponent(player);
   }
};

def TARGET_LAND_YOUR_OPPONENT_CONTROLS = new MagicTargetChoice(
    LAND_YOUR_OPPONENT_CONTROLS,
    "a land opponent controls"
);

[
    new MagicWhenDamageIsDealtTrigger() {
        @Override
        public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent,final MagicDamage damage) {
            return (damage.getSource() == permanent &&
                    permanent.isOpponent(damage.getTarget()) &&
               damage.getAmount() >= 6) ?
            return new MagicEvent(
               source,
               TARGET_LAND_YOUR_OPPONENT_CONTROLS,
               MagicDestroyTargetPicker.Destroy,
               this,
               "Destroy target land\$."
            ):
                MagicEvent.NONE;
        }
        @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            game.doAction(new MagicDestroyAction(event.getPermanent()));
        }
    }
]
Any hint?

Re: Adding new cards with Groovy

PostPosted: 11 Feb 2014, 02:05
by melvin
jerichopumpkin wrote:I've been trying to add Deus of Calamity, but something is not right.
1)
Code: Select all
return (damage.getSource() == permanent &&
                    permanent.isOpponent(damage.getTarget()) &&
               damage.getAmount() >= 6) ?
            return new MagicEvent(
Extra return. Remove "return" before "new"

2)
Code: Select all
new MagicEvent(
    source,
    TARGET_LAND_YOUR_OPPONENT_CONTROLS,
    MagicDestroyTargetPicker.Destroy,
    this,
    "Destroy target land\$."
):
The "source" variable used as the first argument doesn't exist, you probably mean "permanent"

Re: Adding new cards with Groovy

PostPosted: 11 Feb 2014, 07:39
by jerichopumpkin
:oops: silly me, I should do the scripting before dinner, instead of before bedtime!

Re: Adding new cards with Groovy

PostPosted: 11 Feb 2014, 12:31
by melvin
jerichopumpkin wrote:The strange thing is that magarena does not crash, but the game does not start if the card is in one of the decks
I'd like to get addition info on the above which seems odd. Magarena should crash when it tried to load the card in a deck. If it doesn't not crash, what happens when the card is in one of the decks? Does some kind of dialog pop up? Would be great if you could attach a screenshot of the state the game is in when it gets stuck.

Re: Adding new cards with Groovy

PostPosted: 11 Feb 2014, 17:02
by jerichopumpkin
It seems to enter an infinite loop. Magarena is just stuck here:
prnt-scrn-mag.jpg
starting a game with Deus of Calamity with wrong groovy

Then if you press Esc, you can access the running duel menu. Everything works, except for "Restart Duel" and "Concede Game". Clicking either of them leads to a crash:
crash.log
(2.81 KiB) Downloaded 82 times

And the screen capture:
crash.png

Re: Adding new cards with Groovy

PostPosted: 11 Feb 2014, 19:24
by ShawnieBoy
This has already been fixed for 1.47 - try using that one :)

Re: Adding new cards with Groovy

PostPosted: 13 Feb 2014, 18:06
by ShawnieBoy
While trundling through groovy codes, I've been beginning to wonder:

    Aren't groovy codes superior to scripted cards? (In regards to AI hinting for permanent activations)
    Is the aim to get all cards into scripts?
    Is it preferable to have all 'def = ' in groovy codes in the main program? (for example niche permanent filters), or is it better to keep them on the specific cards?

I'm always willing to get more stuff scriptable if it can stand up against a groovy version :)
Or incorporating the script card definitions into groovy, so only one file is needed.

Re: Adding new cards with Groovy

PostPosted: 15 Feb 2014, 13:59
by melvin
ShawnieBoy wrote:Aren't groovy codes superior to scripted cards? (In regards to AI hinting for permanent activations)
Groovy code is much more flexible compared to scripts, the downside is they are longer, harder to write and debug.

ShawnieBoy wrote:Is the aim to get all cards into scripts?
For me, the ideal is to just paste in the rules text directly in the card script. Scripts are an intermediate step, they help to reduce repetitions and lower the barrier of entry for adding cards.

ShawnieBoy wrote:Is it preferable to have all 'def = ' in groovy codes in the main program? (for example niche permanent filters), or is it better to keep them on the specific cards?
If it applies to only one card, better to keep in the card's groovy script.

Re: Adding new cards with Groovy

PostPosted: 15 Feb 2014, 15:28
by hong yie
Image

Trostani_s_Summoner.txt
Code: Select all
name=Trostani's Summoner
url=http://magiccards.info/dgm/en/110.html
image=http://magiccards.info/scans/en/dgm/110.jpg
value=3.773
rarity=U
type=Creature
subtype=Elf,Shaman
cost=5{G}{W}
pt=1/1
timing=main
requires_groovy_code
Trostani_s_Summoner.groovy
Code: Select all
[
    new MagicWhenComesIntoPlayTrigger() {
        @Override
        public MagicEvent executeTrigger(
                final MagicGame game,
                final MagicPermanent permanent,
                final MagicPayedCost payedCost) {
            return new MagicEvent(
            permanent,
            this,
            "PN puts a 2/2 white Knight creature token with vigilance, "+
            "a 3/3 green Centaur creature token, and "+
            "a 4/4 green Rhino creature token with trample onto the battlefield."
            )
        }
        @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            game.doAction(new MagicPlayTokenAction(
                event.getPlayer(),
                TokenCardDefinitions.get("2/2 white Knight creature token with vigilance")                              
            ));
            game.doAction(new MagicPlayTokenAction(
                event.getPlayer(),
                TokenCardDefinitions.get("3/3 green Centaur creature token")                              
            ));
            game.doAction(new MagicPlayTokenAction(
                event.getPlayer(),
                TokenCardDefinitions.get("4/4 green Rhino creature token with trample")                              
            ));
      }
    }
]

Re: Adding new cards with Groovy

PostPosted: 16 Feb 2014, 05:03
by ShawnieBoy
I have another couple of questions (Sorry!)

Is it possible to add MagicConditions to SpellCardEvents? (ie. cast this spell only if...)
Is it possible to determine the amount of life an opponent has lost 'this turn' - I can see a WasDealtDamage MagicPlayerState flag, but nothing more specific.

Thanks :D

Re: Adding new cards with Groovy

PostPosted: 16 Feb 2014, 05:30
by melvin
ShawnieBoy wrote:I have another couple of questions (Sorry!)
Questions are good, keep em coming.

ShawnieBoy wrote:Is it possible to add MagicConditions to SpellCardEvents? (ie. cast this spell only if...)
Not to SpellCardEvents, those are for representing the effect of a spell. There can be conditions to MagicCardActivation, which is the card counter part of MagicPermanentActivation. MagicCardActivation is the basis for the implementation of bloodrush, cycling, and normal casting of cards from hand (handled by MagicCardActivation itself).

Every card is automatically given a standard MagicCardActivation for casting it by paying the mana cost.

Cards that have additional MagicCardActivation include Force of Will and Lightning Reflexes.

ShawnieBoy wrote:Is it possible to determine the amount of life an opponent has lost 'this turn' - I can see a WasDealtDamage MagicPlayerState flag, but nothing more specific.
No.

Re: Adding new cards with Groovy

PostPosted: 16 Feb 2014, 05:45
by hong yie
tried to submit this script to firemind.ch, but somehow this card is not recognized. i think this would be in Mike's Authority, maybe.
Anyway here it is

Image
Karametra__God_of_Harvests.txt
Code: Select all
name=Karametra, God of Harvests
url=http://magiccards.info/bng/en/148.html
image=http://magiccards.info/scans/en/bng/148.jpg
value=3.331
rarity=M
type=Legendary,Enchantment,Creature
subtype=God
cost={3}{G}{W}
pt=6/7
ability=indestructible
timing=main
requires_groovy_code
Karametra__God_of_Harvests.groovy
Code: Select all
[
    new MagicStatic(MagicLayer.Type) {
        @Override
        public int getTypeFlags(final MagicPermanent permanent,final int flags) {
            return flags & ~MagicType.Creature.getMask();
        }
        @Override
        public void modSubTypeFlags(final MagicPermanent permanent,final Set<MagicSubType> flags) {
            flags.remove(MagicSubType.God);
        }
        @Override
        public boolean condition(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
            return source.getController().getDevotion(MagicColor.Green) + source.getController().getDevotion(MagicColor.White)< 7;
        }
    },
    new MagicWhenOtherSpellIsCastTrigger() {
        @Override
        public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent,final MagicCardOnStack spell) {
            return spell.isFriend(permanent) && spell.hasType(MagicType.Creature) ?
            new MagicEvent(
               cardOnStack,
               this,
               "PN searches his or her library for a Forest or Plains card and put that card onto the battlefield tapped. Then shuffle PN's library."
            ):
                MagicEvent.NONE;
        }
        @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            game.addEvent(new MagicSearchOntoBattlefieldEvent(
                event,
                MagicTargetChoice.FOREST_PLAINS_CARD_FROM_LIBRARY,
                MagicPlayMod.TAPPED
            ));
        }
    }
]

Re: Adding new cards with Groovy

PostPosted: 16 Feb 2014, 06:00
by melvin
Nice work! This is the first two color God to be added, https://code.google.com/p/magarena/sour ... bd4b134f1b

Fixed a couple of bugs in the groovy script, the corrected version is below.
Changes:
1) correct calculation of devotion, hybrid mana cost should be counted once only
2) first arg to MagicEvent should be spell instead of cardOnStack
3) should be MagicTargetChoice.FOREST_OR_PLAINS_CARD_FROM_LIBRARY instead of MagicTargetChoice.FOREST_PLAINS_CARD_FROM_LIBRARY
Code: Select all
[
    new MagicStatic(MagicLayer.Type) {
        @Override
        public int getTypeFlags(final MagicPermanent permanent,final int flags) {
            return flags & ~MagicType.Creature.getMask();
        }
        @Override
        public void modSubTypeFlags(final MagicPermanent permanent,final Set<MagicSubType> flags) {
            flags.remove(MagicSubType.God);
        }
        @Override
        public boolean condition(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
            return source.getController().getDevotion(MagicColor.Green, MagicColor.White) < 7;
        }
    },
    new MagicWhenOtherSpellIsCastTrigger() {
        @Override
        public MagicEvent executeTrigger(final MagicGame game,final MagicPermanent permanent,final MagicCardOnStack spell) {
            return spell.isFriend(permanent) && spell.hasType(MagicType.Creature) ?
                new MagicEvent(
                   spell,
                   this,
                   "PN searches his or her library for a Forest or Plains card and put that card onto the battlefield tapped. Then shuffle PN's library."
                ):
                MagicEvent.NONE;
        }
        @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            game.addEvent(new MagicSearchOntoBattlefieldEvent(
                event,
                MagicTargetChoice.FOREST_OR_PLAINS_CARD_FROM_LIBRARY,
                MagicPlayMod.TAPPED
            ));
        }
    }
]