It is currently 16 Apr 2024, 16:19
   
Text Size

Help implementing a card

Moderators: North, BetaSteward, noxx, jeffwadsworth, JayDi, TheElk801, LevelX, CCGHQ Admins

Help implementing a card

Postby Rafbill » 29 Sep 2011, 16:46

I started trying to implement some cards for Mage, which is the more advanced project i have seen so far.
But i couldn't manage to implement the "attacking" part of the rules in this card :
http://magiccards.info/mt/en/20.html

Here is the class (without imports and license):
Code: Select all
public class PreeminentCaptain extends CardImpl<PreeminentCaptain> {

   final PreeminentCaptainEffect effect = new PreeminentCaptainEffect();

   public PreeminentCaptain(UUID ownerId) {
      super(ownerId, 20, "Preeminent Captain", Rarity.RARE,
            new CardType[] { CardType.CREATURE }, "{2}{W}");
      this.expansionSetCode = "MOR";
      this.subtype.add("Kithkin");
      this.subtype.add("Soldier");

      this.color.setWhite(true);
      this.power = new MageInt(2);
      this.toughness = new MageInt(2);

      this.addAbility(FirstStrikeAbility.getInstance());
      // Whenever Preeminent Captain attacks, you may put a Soldier creature
      // card from your hand onto the battlefield tapped and attacking.
      this.addAbility(new AttacksTriggeredAbility(effect, true));
   }

   public PreeminentCaptain(final PreeminentCaptain card) {
      super(card);
   }

   @Override
   public PreeminentCaptain copy() {
      return new PreeminentCaptain(this);
   }
}

class PreeminentCaptainEffect extends OneShotEffect<PreeminentCaptainEffect> {

   protected TargetCardInHand target;

   public PreeminentCaptainEffect() {
      super(Outcome.PutCreatureInPlay);
      target = new TargetCardInHand(new FilterSoldierCard());
   }

   public PreeminentCaptainEffect(final PreeminentCaptainEffect effect) {
      super(effect);
      target = effect.target;
   }

   @Override
   public boolean apply(Game game, Ability source) {
      Player player = game.getPlayer(source.getControllerId());
      if (target.choose(getOutcome(), player.getId(), game)) {
         if (target.getTargets().size() > 0) {
            UUID cardId = (UUID) target.getTargets().toArray()[0];
            Card card = player.getHand().get(cardId, game);
            if (card != null) {
               if (card.putOntoBattlefield(game, Zone.HAND,
                     source.getId(), source.getControllerId())) {
                  Permanent permanent = game.getPermanent(card.getId());
                  permanent.setTapped(true);
                  // ?  ?  ?
               }
            }
            return true;
         }
      }
      return false;
   }

   @Override
   public PreeminentCaptainEffect copy() {
      return new PreeminentCaptainEffect(this);
   }

}

class FilterSoldierCard extends FilterCard<FilterSoldierCard> {

   public FilterSoldierCard() {
      this("a soldier creature card.");
   }

   public FilterSoldierCard(String name) {
      super(name);
      cardType.add(CardType.CREATURE);
      subtype.add("Soldier");
   }

   public FilterSoldierCard(final FilterSoldierCard filter) {
      super(filter);
   }

   @Override
   public FilterSoldierCard copy() {
      return new FilterSoldierCard(this);
   }

}
I'm not a competent Java programmer, i usually work with C++.


No method in class Combat seems to be relevant, I'll try adding one (this card is the only card with an effect of that kind)

EDIT : Implemented it, added a method, "If you use the ability, you choose which player or planeswalker the Soldier creature is attacking. It doesn't have to attack the same player or planeswalker as Preeminent Captain." is still not implemented.
Rafbill
 
Posts: 1
Joined: 28 Sep 2011, 17:51
Has thanked: 0 time
Been thanked: 0 time

Re: Help implementing a card

Postby nantuko84 » 29 Sep 2011, 19:53

Hi, just add this line to you effect:

Code: Select all
game.getCombat().declareAttacker(permanent.getId(), game.getCombat().getDefendingPlayer(source.getSourceId()), game);
Mage\MagicWars blog: http://mwars.blogspot.com/
nantuko84
DEVELOPER
 
Posts: 266
Joined: 08 Feb 2009, 21:14
Has thanked: 2 times
Been thanked: 9 times

Re: Help implementing a card

Postby jeffwadsworth » 20 Jun 2012, 02:59

Working on Living Destiny. I can not select a card from my hand with this code. Yes, it supposed to be a creature card, but it is just a test.

Code: Select all
/*
 *  Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without modification, are
 *  permitted provided that the following conditions are met:
 *
 *     1. Redistributions of source code must retain the above copyright notice, this list of
 *        conditions and the following disclaimer.
 *
 *     2. Redistributions in binary form must reproduce the above copyright notice, this list
 *        of conditions and the following disclaimer in the documentation and/or other materials
 *        provided with the distribution.
 *
 *  THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
 *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 *  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
 *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 *  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 *  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 *  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *  The views and conclusions contained in the software and documentation are those of the
 *  authors and should not be interpreted as representing official policies, either expressed
 *  or implied, of BetaSteward_at_googlemail.com.
 */
package mage.sets.riseoftheeldrazi;

import java.util.UUID;
import mage.Constants;
import mage.Constants.CardType;
import mage.Constants.Rarity;
import mage.abilities.Ability;
import mage.abilities.costs.CostImpl;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.filter.FilterCard;
import mage.filter.common.FilterCreatureCard;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInHand;

/**
 *
 * @author jeffwadsworth
 */
public class LivingDestiny extends CardImpl<LivingDestiny> {

    public LivingDestiny(UUID ownerId) {
        super(ownerId, 195, "Living Destiny", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{3}{G}");
        this.expansionSetCode = "ROE";

        this.color.setGreen(true);

        // As an additional cost to cast Living Destiny, reveal a creature card from your hand.
        TargetCardInHand targetCard = new TargetCardInHand(new FilterCard("a card"));
        this.getSpellAbility().addCost(new RevealTargetCost(targetCard));
       
        // You gain life equal to the revealed card's converted mana cost.
        this.getSpellAbility().addEffect(new LivingDestinyEffect());
    }

    public LivingDestiny(final LivingDestiny card) {
        super(card);
    }

    @Override
    public LivingDestiny copy() {
        return new LivingDestiny(this);
    }
}

class RevealTargetCost extends CostImpl<RevealTargetCost> {
   
    protected int convertedManaCosts = 0;
   
    public RevealTargetCost(TargetCardInHand target) {
        this.addTarget(target);
        this.text = "Reveal " + target.getTargetName();
    }
   
    public RevealTargetCost(RevealTargetCost cost) {
        super(cost);
    }
   
    @Override
    public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) {
        if (targets.choose(Constants.Outcome.Benefit, controllerId, sourceId, game)) {
            Player player = game.getPlayer(controllerId);
            Cards cards = new CardsImpl();
            for (UUID targetId: targets.get(0).getTargets()) {
                Card card = player.getHand().get(targetId, game);
                if (card == null)
                    return false;
                convertedManaCosts = card.getManaCost().convertedManaCost();
                cards.add(card);
                player.revealCards("Revealed card", cards, game);
                return true;
            }
        }
        return false;
    }
   
    public int getConvertedCosts() {
            return convertedManaCosts;
        }

    @Override
    public boolean canPay(UUID sourceId, UUID controllerId, Game game) {
        return targets.canChoose(controllerId, game);
    }

    @Override
    public RevealTargetCost copy() {
        return new RevealTargetCost(this);
    }
}

class LivingDestinyEffect extends OneShotEffect<LivingDestinyEffect> {

                public LivingDestinyEffect() {
                        super(Constants.Outcome.GainLife);
                        staticText = "You gain life equal to its converted mana cost";
                }

                public LivingDestinyEffect(LivingDestinyEffect effect) {
                        super(effect);
                }

                @Override
                public boolean apply(Game game, Ability source) {
                        RevealTargetCost cost = (RevealTargetCost) source.getCosts().get(0);
                        if (cost != null) {
                                Player player = game.getPlayer(source.getControllerId());
                                int CMC = cost.convertedManaCosts;
                                if (player != null) {
                                        player.gainLife(CMC, game);
                                }
                        }
                        return true;
                }

                @Override
                public LivingDestinyEffect copy() {
                        return new LivingDestinyEffect(this);
                }

}
jeffwadsworth
Super Tester Elite
 
Posts: 1171
Joined: 20 Oct 2010, 04:47
Location: USA
Has thanked: 287 times
Been thanked: 69 times

Re: Help implementing a card

Postby jmartus » 20 Jun 2012, 04:01

one of my favorite cards thank you :) hope you get it working.
jmartus
 
Posts: 207
Joined: 11 Oct 2010, 09:25
Has thanked: 0 time
Been thanked: 7 times

Re: Help implementing a card

Postby noxx » 20 Jun 2012, 07:30

jeffwadsworth wrote:Working on Living Destiny. I can not select a card from my hand with this code. Yes, it supposed to be a creature card, but it is just a test.
You forgot to set "paid = true;" in RevealTargetCost after card was revealed.

I've commited 3 tests for your card, so you can use them to make sure that your implementation works.

Best Regards,
Noxx
noxx
DEVELOPER
 
Posts: 110
Joined: 25 Mar 2012, 08:13
Has thanked: 3 times
Been thanked: 37 times

Re: Help implementing a card

Postby jeffwadsworth » 03 Jul 2012, 02:22

Looking at Stasis. Considering we do not want to over-tax the system, is there a way to efficiently handle this card?
jeffwadsworth
Super Tester Elite
 
Posts: 1171
Joined: 20 Oct 2010, 04:47
Location: USA
Has thanked: 287 times
Been thanked: 69 times

Re: Help implementing a card

Postby North » 03 Jul 2012, 12:09

Breeding Pit and Justice are for the first effect.

There is Yosei, the Morning Star who implements a similar behavior to the second effect.
North
DEVELOPER
 
Posts: 93
Joined: 15 May 2011, 08:20
Has thanked: 8 times
Been thanked: 15 times

Re: Help implementing a card

Postby jeffwadsworth » 03 Jul 2012, 21:39

North wrote:Breeding Pit and Justice are for the first effect.

There is Yosei, the Morning Star who implements a similar behavior to the second effect.
Yes, I noticed that and others, but that targets player and it is a one-time effect. I wish it was that simple. :)
jeffwadsworth
Super Tester Elite
 
Posts: 1171
Joined: 20 Oct 2010, 04:47
Location: USA
Has thanked: 287 times
Been thanked: 69 times

Re: Help implementing a card

Postby jeffwadsworth » 04 Jul 2012, 15:56

Working on Pithing Needle. Does anyone know how to reference an AbilityType of an (GameEvent.EventType.Activate_Ability) event?
For this card, the activated ability of the chosen card does not hit the stack, so something like:
stackAbility.getAbilityType() != Constants.AbilityType.MANA
will not work. It needs to be able to check the ability type of the activated ability before it hits the stack.
jeffwadsworth
Super Tester Elite
 
Posts: 1171
Joined: 20 Oct 2010, 04:47
Location: USA
Has thanked: 287 times
Been thanked: 69 times

Re: Help implementing a card

Postby North » 04 Jul 2012, 17:37

I could try implementing Stasis if you want.

Also, did you try writing a replacement effect for Pithing Needle? Stony Silence abd Phyrexian Revoker have something similar for example. I don't know if I've hit the right spot.
North
DEVELOPER
 
Posts: 93
Joined: 15 May 2011, 08:20
Has thanked: 8 times
Been thanked: 15 times

Re: Help implementing a card

Postby jeffwadsworth » 04 Jul 2012, 19:59

North wrote:I could try implementing Stasis if you want.

Also, did you try writing a replacement effect for Pithing Needle? Stony Silence abd Phyrexian Revoker have something similar for example. I don't know if I've hit the right spot.
Please go ahead with the Stasis if you have it figured out. The code for Pithing Needle is a replacement effect, but that isn't the problem. It needs to check the "activate_ability" to see if it is a mana ability. Everything else is done and works fine.

Essentially, I am looking for something like:
Ability activatedAbility = game.getActivatedAbility(event.getSourceId());

That way we could check to see if it is a mana ability, etc.

activatedAbility.getAbilityType() != Constants.AbilityType.MANA
jeffwadsworth
Super Tester Elite
 
Posts: 1171
Joined: 20 Oct 2010, 04:47
Location: USA
Has thanked: 287 times
Been thanked: 69 times

Re: Help implementing a card

Postby jeffwadsworth » 05 Jul 2012, 23:12

Nevermind about Pithing Needle. I found a solution.
jeffwadsworth
Super Tester Elite
 
Posts: 1171
Joined: 20 Oct 2010, 04:47
Location: USA
Has thanked: 287 times
Been thanked: 69 times

Re: Help implementing a card

Postby jeffwadsworth » 07 Jul 2012, 19:40

Does anyone see the issue with this code for "Rhox Faithmender"? M13. The amount is changed in the event, but not applied during resolution. Weird.

http://gatherer.wizards.com/Pages/Card/ ... eid=279987


Code: Select all
/*
 *  Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without modification, are
 *  permitted provided that the following conditions are met:
 *
 *     1. Redistributions of source code must retain the above copyright notice, this list of
 *        conditions and the following disclaimer.
 *
 *     2. Redistributions in binary form must reproduce the above copyright notice, this list
 *        of conditions and the following disclaimer in the documentation and/or other materials
 *        provided with the distribution.
 *
 *  THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
 *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 *  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
 *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 *  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 *  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 *  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *  The views and conclusions contained in the software and documentation are those of the
 *  authors and should not be interpreted as representing official policies, either expressed
 *  or implied, of BetaSteward_at_googlemail.com.
 */
package mage.sets.magic2013;

import java.util.UUID;
import mage.Constants;
import mage.Constants.CardType;
import mage.Constants.Rarity;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.keyword.LifelinkAbility;
import mage.cards.CardImpl;
import mage.game.Game;
import mage.game.events.GameEvent;

/**
 *
 * @author jeffwadsworth
 */
public class RhoxFaithmender extends CardImpl<RhoxFaithmender> {

    public RhoxFaithmender(UUID ownerId) {
        super(ownerId, 29, "Rhox Faithmender", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{W}");
        this.expansionSetCode = "M13";
        this.subtype.add("Rhino");
        this.subtype.add("Monk");

        this.color.setWhite(true);
        this.power = new MageInt(1);
        this.toughness = new MageInt(5);

        // Lifelink
        this.addAbility(LifelinkAbility.getInstance());
       
        // If you would gain life, you gain twice that much life instead.
        this.addAbility(new SimpleStaticAbility(Constants.Zone.BATTLEFIELD, new RhoxFaithmenderEffect()));
    }

    public RhoxFaithmender(final RhoxFaithmender card) {
        super(card);
    }

    @Override
    public RhoxFaithmender copy() {
        return new RhoxFaithmender(this);
    }
}

class RhoxFaithmenderEffect extends ReplacementEffectImpl<RhoxFaithmenderEffect> {

    public RhoxFaithmenderEffect() {
        super(Constants.Duration.WhileOnBattlefield, Constants.Outcome.Benefit);
        staticText = "If you would gain life, you gain twice that much life instead.";
    }

    public RhoxFaithmenderEffect(final RhoxFaithmenderEffect effect) {
        super(effect);
    }

    @Override
    public RhoxFaithmenderEffect copy() {
        return new RhoxFaithmenderEffect(this);
    }

    @Override
    public boolean apply(Game game, Ability source) {
        return true;
    }

    @Override
    public boolean replaceEvent(GameEvent event, Ability source, Game game) {
        return apply(game, source);
    }

    @Override
    public boolean applies(GameEvent event, Ability source, Game game) {
        switch (event.getType()) {
            case GAIN_LIFE:
                if (event.getPlayerId().equals(source.getControllerId())) {
                    event.setAmount(event.getAmount() * 2);
                }
        }
        return false;
    }
}

jeffwadsworth
Super Tester Elite
 
Posts: 1171
Joined: 20 Oct 2010, 04:47
Location: USA
Has thanked: 287 times
Been thanked: 69 times

Re: Help implementing a card

Postby noxx » 08 Jul 2012, 06:26

I'll take a look at it.

Btw, how is it going with Pithing Needle?
noxx
DEVELOPER
 
Posts: 110
Joined: 25 Mar 2012, 08:13
Has thanked: 3 times
Been thanked: 37 times

Re: Help implementing a card

Postby jeffwadsworth » 08 Jul 2012, 06:40

noxx wrote:I'll take a look at it.

Btw, how is it going with Pithing Needle?
Well, I thought I had a way to access the activated ability, but no dice. I will get back to it in time.
jeffwadsworth
Super Tester Elite
 
Posts: 1171
Joined: 20 Oct 2010, 04:47
Location: USA
Has thanked: 287 times
Been thanked: 69 times

Next

Return to Developers Talk

Who is online

Users browsing this forum: No registered users and 10 guests


Who is online

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

Login Form