It is currently 20 Apr 2024, 01:59
   
Text Size

Card Contributions

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

Re: Card Contributions

Postby PalladiaMors » 10 Mar 2015, 19:06

Yeah, playtested and it works perfectly. Do I get the green light to send the 20 cards? Or would you like to do it?
PalladiaMors
 
Posts: 343
Joined: 12 Jul 2014, 17:40
Has thanked: 36 times
Been thanked: 22 times

Re: Card Contributions

Postby ShawnieBoy » 10 Mar 2015, 19:14

Go for it :D - You poked my brain.

I'll have a look at the possibility of getting it scripted, but having the cards there to test now is better.
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 » 11 Mar 2015, 01:44

This kind of spontaneous discovery of ways to implement "new" mechanics within the limited system of Magarena really excites me.

Credits to @PalliaMors for suggesting using a custom card activation and @ShawnieBoy for suggesting to generate the cost dynamically.

"affinity for [text]" is card scriptable in latest development version on github, i.e.
Code: Select all
ability=Affinity for Plains
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 » 11 Mar 2015, 02:20

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 » 11 Mar 2015, 02:57

I was also thinking about delve. This is an attempt at Tombstalker:

Code: Select all
def choice = new MagicTargetChoice("a card from your graveyard");

[
     new MagicCardActivation(
        [MagicConditionFactory.GraveyardAtLeast(6), MagicCondition.CARD_CONDITION],
        new MagicActivationHints(MagicTiming.Main, true),
        "BB"
    ) {

        @Override
        public Iterable<MagicEvent> getCostEvent(final MagicCard source) {
            return [
                new MagicPayManaCostEvent(source,"{B}{B}"),
                new MagicExileCardEvent(source, choice),
                new MagicExileCardEvent(source, choice),
                new MagicExileCardEvent(source, choice),
                new MagicExileCardEvent(source, choice),
                new MagicExileCardEvent(source, choice),
                new MagicExileCardEvent(source, choice)
            ];
        }
    },
     new MagicCardActivation(
        [MagicConditionFactory.GraveyardAtLeast(5), MagicCondition.CARD_CONDITION],
        new MagicActivationHints(MagicTiming.Main, true),
        "1BB"
    ) {

        @Override
        public Iterable<MagicEvent> getCostEvent(final MagicCard source) {
            return [
                new MagicPayManaCostEvent(source,"{1}{B}{B}"),
                new MagicExileCardEvent(source, choice),
                new MagicExileCardEvent(source, choice),
                new MagicExileCardEvent(source, choice),
                new MagicExileCardEvent(source, choice),
                new MagicExileCardEvent(source, choice)
            ];
        }
    },
     new MagicCardActivation(
        [MagicConditionFactory.GraveyardAtLeast(4), MagicCondition.CARD_CONDITION],
        new MagicActivationHints(MagicTiming.Main, true),
        "2BB"
    ) {

        @Override
        public Iterable<MagicEvent> getCostEvent(final MagicCard source) {
            return [
                new MagicPayManaCostEvent(source,"{2}{B}{B}"),
                new MagicExileCardEvent(source, choice),
                new MagicExileCardEvent(source, choice),
                new MagicExileCardEvent(source, choice),
                new MagicExileCardEvent(source, choice)
            ];
        }
    },
     new MagicCardActivation(
        [MagicConditionFactory.GraveyardAtLeast(3), MagicCondition.CARD_CONDITION],
        new MagicActivationHints(MagicTiming.Main, true),
        "3BB"
    ) {

        @Override
        public Iterable<MagicEvent> getCostEvent(final MagicCard source) {
            return [
                new MagicPayManaCostEvent(source,"{3}{B}{B}"),
                new MagicExileCardEvent(source, choice),
                new MagicExileCardEvent(source, choice),
                new MagicExileCardEvent(source, choice)
            ];
        }
    },
     new MagicCardActivation(
        [MagicConditionFactory.GraveyardAtLeast(2), MagicCondition.CARD_CONDITION],
        new MagicActivationHints(MagicTiming.Main, true),
        "4BB"
    ) {

        @Override
        public Iterable<MagicEvent> getCostEvent(final MagicCard source) {
            return [
                new MagicPayManaCostEvent(source,"{4}{B}{B}"),
                new MagicExileCardEvent(source, choice),
                new MagicExileCardEvent(source, choice)
            ];
        }
    },
     new MagicCardActivation(
        [MagicConditionFactory.GraveyardAtLeast(1), MagicCondition.CARD_CONDITION],
        new MagicActivationHints(MagicTiming.Main, true),
        "5BB"
    ) {

        @Override
        public Iterable<MagicEvent> getCostEvent(final MagicCard source) {
            return [
                new MagicPayManaCostEvent(source,"{5}{B}{B}"),
                new MagicExileCardEvent(source, choice)
            ];
        }
    }
]
Unlike affinity, delve is optional, the player can exile as many cards as he wishes, so every option that the player can pay for should be available to him. However, the way I coded the card above, only the lowest cost and the standard cost (in case the player has enough mana to pay for the later) will be available. However, I know that cards with more than two alternate costs are possible, because the cards with phyrexian mana are available. Unfortunately, none of those are available in groovy form, so I can't figure out how that's done. Is it possible to improve the script above? The way I did it there isn't good enough to implement.

Edit: submitted a fix to Dark Deal, which was working completely wrong.
PalladiaMors
 
Posts: 343
Joined: 12 Jul 2014, 17:40
Has thanked: 36 times
Been thanked: 22 times

Re: Card Contributions

Postby jerichopumpkin » 11 Mar 2015, 08:48

Woah! Yuo managed to add affinity (and similar effects) to the scriptable cards, that's amazing!!! Thank you guys!!!
Back on topic, I don't know if this implementation of delve is the best way to do it, but it seems that it could work, and I think it's also applicable for Convoke.
Since I do not have the time and the skill needed, I'l just leave the idea here for an alternate way to do delve/convoke: what about giving the ability to produce mana to relevant cards only during the "pay to cast" step?
jerichopumpkin
 
Posts: 212
Joined: 12 Sep 2013, 11:21
Has thanked: 19 times
Been thanked: 13 times

Re: Card Contributions

Postby ShawnieBoy » 11 Mar 2015, 15:35

melvin wrote:This kind of spontaneous discovery of ways to implement "new" mechanics within the limited system of Magarena really excites me.

Credits to @PalliaMors for suggesting using a custom card activation and @ShawnieBoy for suggesting to generate the cost dynamically.

"affinity for [text]" is card scriptable in latest development version on github, i.e.
Code: Select all
ability=Affinity for Plains
Good to be back! I love this part too :D

Delve would be a multi-pronged approach. There would have to be a casting 'option' (with or without delve), which would also then involve choosing from a card-list of the graveyard, the chosen ones would be used to then reduce the casting cost by that amount.

The problem I see, is that to be able to cast the card - it would have to have it's potential casting cost dynamically created as an assumption that the player will delve for max. Otherwise you wouldn't even be able to select it at all. It would then be changed again after the graveyard cards are then chosen.

This same process would apply to delve and convoke.
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 PalladiaMors » 11 Mar 2015, 16:21

Now that melvin has enabled exiling multiple cards from graveyard in script form, this is what I had in mind, following the phyrexian mana cards:

Code: Select all
name=Tombstalker
image=http://mtgimage.com/card/tombstalker.jpg
value=2.500
rarity=R
type=Creature
subtype=Demon
cost={6}{B}{B}
ability=alt cost {5}{B}{B}, Exile one card from your graveyard named Exile1;\
        alt cost {4}{B}{B}, Exile two cards from your graveyard named Exile2;\
        alt cost {3}{B}{B}, Exile three cards from your graveyard named Exile3;\
        alt cost {2}{B}{B}, Exile four cards from your graveyard named Exile4;\
        alt cost {1}{B}{B}, Exile five cards from your graveyard named Exile5;\
        alt cost {B}{B}, Exile six cards from your graveyard named Exile6
pt=5/5
ability=Flying
timing=main
oracle=Flying. Delve
I've tested it and it doesn't work, the alt costs aren't enabled, I don't really understand why. If it did, I see two problems with this implementation. One is aesthetical, since it's not pretty to have that many options popup in the options zone, but I don't see that as a problem. The other one is a rules concern, because this way of doing the card can't account for a possible cost increase. However, in this case we're lucky that those cards aren't available for Magarena, and I don't see that changing very soon. When we get cost increasers, Magarena will probably have gotten the mana pool, and then I think Delve will probably be implementable without any tricks. I think it's unlikely that happens in 2015, so Magarena/Firemind users could enjoy these cards like this for the time being. There's a third concern, which is that this way doesn't have the delve keyword attached to the card, so it won't interact with whatever interacts with Delve, but I don't know if there's anything like that?

Anyway, if this way of doing delve worked, I'd be supporting it. Could someone please explain why it's not working?

Oh yeah, Convoke is very similar and I was thinking about using the same idea for that.

Edit: A Convoke version:

Code: Select all
name=Stoke the Flames
image=http://mtgimage.com/card/stoke%20the%20flames.jpg
value=2.500
rarity=U
type=Instant
cost={2}{R}{R}
ability=alt cost {1}{R}{R}, tap an untapped creature you control named 1RR;\
        alt cost {R}{R}, tap two untapped creatures you control named RR;\
        alt cost {2}{R}, tap an untapped red creature you control named 2R;\
        alt cost {1}{R}, tap an untapped creature you control, tap an untapped red creature you control named 1R;\
        alt cost {2}, tap two untapped red creatures you control named 2;\
        alt cost {R}, tap two untapped creatures you control, tap an untapped red creature you control named R;\
        alt cost tap two untapped creatures you control, tap two untapped red creatures you control named 0
effect=SN deals 4 damage to target creature or player.
timing=removal
oracle=Convoke. Stoke the Flames deals 4 damage to target creature or player.
This one is working, the alternate costs are showing up, but I have to test it a bit more because it looks like when the tapped creature is red, it's getting counted twice. Of course, doing high cost cards in this manner will be a lot of trouble.
PalladiaMors
 
Posts: 343
Joined: 12 Jul 2014, 17:40
Has thanked: 36 times
Been thanked: 22 times

Re: Card Contributions

Postby PalladiaMors » 12 Mar 2015, 01:45

Hey, I think I messed up on both Land Equilibrium and Land Tax. If those submissions are too low quality, please just refuse them. I'll try to get them right later. Thanks.
PalladiaMors
 
Posts: 343
Joined: 12 Jul 2014, 17:40
Has thanked: 36 times
Been thanked: 22 times

Re: Card Contributions

Postby melvin » 12 Mar 2015, 02:07

PalladiaMors wrote:this is what I had in mind, following the phyrexian mana
I think doing it as alt costs is too clunky. I think we can do it with something similar to Devour[1] which also has a variable component. Instead of generating all the cost events upfront, each event can generate the next one dynamically.

The idea is to return a MagicDelveCostEvent(manaCost) as the only cost event. This event is "You may exile a card from your graveyard rather than pay {1}". When it resolves, if the player said yes, we exile the card and add MagicDelveCostEvent(manaCost - {1}) to the event queue with addFirstEvent so it will continue to ask until all the colorless cost is paid. When the player answer no or all the colorless cost is paid, it adds the remaining mana cost as a regular pay mana cost event.

I think the same can be applied to convoke and phyrexian mana.

The tricky bit is writing the getConditions() method for these chained cost events to determine if you are able to satisfy them without actually going through the motion.

[1] https://github.com/magarena/magarena/bl ... igger.java
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 » 12 Mar 2015, 03:02

melvin, I can't figure out how to do a "pull request", can you please delete the two cards mentioned above? I got confused Land Equilibrium's oracle text, but it's a "would enter the battlefield" effect that's not supported by Magarena. I forgot to reveal the cards in Land Tax and I actually don't know how to reveal in a search onto location event. The card is too strong and in my opinion should be perfect in order to be implemented. Thank you.
PalladiaMors
 
Posts: 343
Joined: 12 Jul 2014, 17:40
Has thanked: 36 times
Been thanked: 22 times

Re: Card Contributions

Postby melvin » 12 Mar 2015, 06:44

@PalladiaMors these cards can be fixed, will get them fixed and include them in the next release.
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 » 13 Mar 2015, 16:12

I couldn't resist another smartass attempt at implementing a new mechanic. Tried to do entwine as a kicker, pretty happy with the result.

Code: Select all
name=Roar of the Kha
image=http://mtgimage.com/card/roar%20of%20the%20kha.jpg
value=2.500
rarity=U
type=Instant
cost={1}{W}
ability=Kicker {1}{W}
timing=pump
requires_groovy_code
oracle=Choose one — • Creatures you control get +1/+1 until end of turn. • Untap all creatures you control. Entwine {1}{W}
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.");

[
    new MagicSpellCardEvent() {
        @Override
        public MagicEvent getEvent(final MagicCardOnStack cardOnStack, final MagicPayedCost payedCost) {
            return new MagicEvent(
                cardOnStack,
                new MagicOrChoice(
                    MagicChoice.NONE,
                    MagicChoice.NONE
                ),
                this,
                "Choose one\$ - creatures you control get +1/+1 until end of turn; " +
                "or untap all creatures you control. " +
                "Choose both if you paid the extra cost."
            );
        }
        @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            if (event.isKicked()) {
                game.addEvent(MagicRuleEventAction.create("Creatures you control get +1/+1 until end of turn.").getEvent(event.getSource()));
                game.addEvent(MagicRuleEventAction.create("Untap all creatures you control.").getEvent(event.getSource()));
            } else if (event.isMode(1)) {
                event.executeModalEvent(game, EFFECT1);
            } else if (event.isMode(2)) {
                event.executeModalEvent(game, EFFECT2);
            }
        }
    }
]
This has one obvious problem: if the kicker is selected, the player still is forced to make a redundant choice, but besides being useless this has no impact on the card's effect. 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. A good amount of the entwine cards are untargeted, though.

What do you think? Acceptable, or not good enough?

Edit: Oops, the entwine cost is 1W instead of 2.
Last edited by PalladiaMors on 14 Mar 2015, 03:07, 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 ShawnieBoy » 13 Mar 2015, 17:00

PalladiaMors wrote:I couldn't resist another smartass attempt at implementing a new mechanic. Tried to do entwine as a kicker, pretty happy with the result.

Code: Select all
name=Roar of the Kha
image=http://mtgimage.com/card/roar%20of%20the%20kha.jpg
value=2.500
rarity=U
type=Instant
cost={1}{W}
ability=Kicker {2}
timing=pump
requires_groovy_code
oracle=Choose one — • Creatures you control get +1/+1 until end of turn. • Untap all creatures you control. Entwine {1}{W}
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.");

[
    new MagicSpellCardEvent() {
        @Override
        public MagicEvent getEvent(final MagicCardOnStack cardOnStack, final MagicPayedCost payedCost) {
            return new MagicEvent(
                cardOnStack,
                new MagicOrChoice(
                    MagicChoice.NONE,
                    MagicChoice.NONE
                ),
                this,
                "Choose one\$ - creatures you control get +1/+1 until end of turn; " +
                "or untap all creatures you control. " +
                "Choose both if you paid the extra cost."
            );
        }
        @Override
        public void executeEvent(final MagicGame game, final MagicEvent event) {
            if (event.isKicked()) {
                game.addEvent(MagicRuleEventAction.create("Creatures you control get +1/+1 until end of turn.").getEvent(event.getSource()));
                game.addEvent(MagicRuleEventAction.create("Untap all creatures you control.").getEvent(event.getSource()));
            } else if (event.isMode(1)) {
                event.executeModalEvent(game, EFFECT1);
            } else if (event.isMode(2)) {
                event.executeModalEvent(game, EFFECT2);
            }
        }
    }
]
This has one obvious problem: if the kicker is selected, the player still is forced to make a redundant choice, but besides being useless this has no impact on the card's effect. 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. A good amount of the entwine cards are untargeted, though.

What do you think? Acceptable, or not good enough?
It's certainly along the right lines, it would need an .isKicked() check before giving the choice options for the modal part. It's the only part that Entwine is concerned with. I'll have a look over this too, there must be a way.
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 » 13 Mar 2015, 18:01

Well, I've got this far:

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(MagicRuleEventAction.create("Creatures you control get +1/+1 until end of turn.").getEvent(event.getSource()));
                game.addEvent(MagicRuleEventAction.create("Untap all creatures you control.").getEvent(event.getSource()));
            } else if (event.isMode(1)) {
                event.executeModalEvent(game, EFFECT1);
            } else if (event.isMode(2)) {
                event.executeModalEvent(game, EFFECT2);
            }
        }
    }
]
However, although the options are performing in the correct way, (Modal choice dependant on whether kicker chosen). The modal effects aren't working (Well, sometimes the pump option works, but I'm wondering if that's to do with the undo). Another pair of eyes may help here.
User avatar
ShawnieBoy
Programmer
 
Posts: 601
Joined: 02 Apr 2012, 22:42
Location: UK
Has thanked: 80 times
Been thanked: 50 times

PreviousNext

Return to Magarena

Who is online

Users browsing this forum: No registered users and 66 guests


Who is online

In total there are 66 users online :: 0 registered, 0 hidden and 66 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 66 guests

Login Form