Page 4 of 13

Re: Help implementing a card

PostPosted: 31 Aug 2013, 19:41
by cbt33
I had read much of that before but from another post I had gotten the impression you only needed to build once and could edit that.

The reason the build was taking so long was strictly because of the tests but when I removed the Mage.Tests module it only takes 6 minutes or so and was still successful. There's no downside to doing this is there?

Re: Help implementing a card

PostPosted: 01 Sep 2013, 06:19
by LevelX
cbt33 wrote:I had read much of that before but from another post I had gotten the impression you only needed to build once and could edit that.
The changed projects have to be rebuild. But normally that's very fast, needing only some seconds. There also exist an "compile on save" option in Netbeans, but that leads to errors under some circumstances and it's better to deactivate it.

cbt33 wrote:The reason the build was taking so long was strictly because of the tests but when I removed the Mage.Tests module it only takes 6 minutes or so and was still successful. There's no downside to doing this is there?
Yes, you don't have to rebuild the tests after every change. It's good practice to build them before you commit changes to the remote repository, to check if your changes broke some exiting tests.

Re: Help implementing a card

PostPosted: 16 Sep 2013, 19:37
by cbt33
Here are ten or so for Odyssey. I didn't test the threshold code on Divine Sacrament but it came from an existing card. Each one is from Odyssey except for BlessedOrator.java for which gen-card.pl placed the main card in Ninth extended in Odyssey.

A last problem I have is that the cards that are in init.txt don't appear when I press the cheat button. Are they also supposed to have the set prefix that are in .dck files?

Re: Help implementing a card

PostPosted: 16 Sep 2013, 22:35
by LevelX
cbt33 wrote:A last problem I have is that the cards that are in init.txt don't appear when I press the cheat button. Are they also supposed to have the set prefix that are in .dck files?
NO, the may not have a set prefix.
Did you use the correct name of the player in init.txt?
What does the server log output show about the init.txt parse, if you push the cheat button?

Re: Help implementing a card

PostPosted: 16 Sep 2013, 22:43
by LevelX
cbt33 wrote:Here are ten or so for Odyssey. I didn't test the threshold code on Divine Sacrament but it came from an existing card. Each one is from Odyssey except for BlessedOrator.java for which gen-card.pl placed the main card in Ninth extended in Odyssey.
I merged the cards to the repository using the pull request.
I will take a look tomorrow on the cards, if I see something to improve or change I will comment it in the pull request issue.

Thanks a lot for your efforts.
I hope to see some more cards implemented by you.
:-)

Re: Help implementing a card

PostPosted: 17 Sep 2013, 02:14
by cbt33
This is what is in the server output from when it parses init.txt on (I sign into the server as cbt)

INFO [2013-09-10 02:52 [40:708]] SystemUtil[pool-2-thread-2]: Parsing init.txt...
WARN [2013-09-10 02:52 [40:720]] SystemUtil[pool-2-thread-2]: Was skipped: battlefield:cbt:Mountain:3
WARN [2013-09-10 02:52 [40:721]] SystemUtil[pool-2-thread-2]: Was skipped: graveyard:cbt:Plains:1
WARN [2013-09-10 02:52 [40:721]] SystemUtil[pool-2-thread-2]: Was skipped: battlefield:cbt:Cephalid Broker:1
WARN [2013-09-10 02:52 [40:721]] SystemUtil[pool-2-thread-2]: Was skipped: battlefield:cbt:Megrim:1
WARN [2013-09-10 02:52 [40:722]] SystemUtil[pool-2-thread-2]: Was skipped: battlefield:cbt:Island:2
WARN [2013-09-10 02:52 [40:722]] SystemUtil[pool-2-thread-2]: Was skipped: battlefield:cbt:Plains:3
WARN [2013-09-10 02:52 [40:722]] SystemUtil[pool-2-thread-2]: Was skipped: hand:cbt:Whispersilk Cloak:1
WARN [2013-09-10 02:52 [40:723]] SystemUtil[pool-2-thread-2]: Was skipped: hand:cbt:Lightning Bolt:1
WARN [2013-09-10 02:52 [40:723]] SystemUtil[pool-2-thread-2]: Was skipped: library:cbt:Shock:2

I also get a long list of errors like these for what comes out of cheat.dck but those enter the battlefield just fine.

WARN [2013-09-10 02:52 [40:644]] CardImpl[pool-2-thread-2]: putOntoBattlefield, not fully implemented: fromZone=OUTSIDE
WARN [2013-09-10 02:52 [40:644]] CardImpl[pool-2-thread-2]: Couldn't find card in fromZone, card=Forest, fromZone=OUTSIDE
WARN [2013-09-10 02:52 [40:646]] CardImpl[pool-2-thread-2]: putOntoBattlefield, not fully implemented: fromZone=OUTSIDE
WARN [2013-09-10 02:52 [40:646]] CardImpl[pool-2-thread-2]: Couldn't find card in fromZone, card=Forest, fromZone=OUTSIDE

Re: Help implementing a card

PostPosted: 17 Sep 2013, 06:28
by LevelX
cbt33 wrote:This is what is in the server output from when it parses init.txt on (I sign into the server as cbt)

INFO [2013-09-10 02:52 [40:708]] SystemUtil[pool-2-thread-2]: Parsing init.txt...
WARN [2013-09-10 02:52 [40:720]] SystemUtil[pool-2-thread-2]: Was skipped: battlefield:cbt:Mountain:3
WARN [2013-09-10 02:52 [40:721]] SystemUtil[pool-2-thread-2]: Was skipped: graveyard:cbt:Plains:1
WARN [2013-09-10 02:52 [40:721]] SystemUtil[pool-2-thread-2]: Was skipped: battlefield:cbt:Cephalid Broker:1
WARN [2013-09-10 02:52 [40:721]] SystemUtil[pool-2-thread-2]: Was skipped: battlefield:cbt:Megrim:1
WARN [2013-09-10 02:52 [40:722]] SystemUtil[pool-2-thread-2]: Was skipped: battlefield:cbt:Island:2
WARN [2013-09-10 02:52 [40:722]] SystemUtil[pool-2-thread-2]: Was skipped: battlefield:cbt:Plains:3
WARN [2013-09-10 02:52 [40:722]] SystemUtil[pool-2-thread-2]: Was skipped: hand:cbt:Whispersilk Cloak:1
WARN [2013-09-10 02:52 [40:723]] SystemUtil[pool-2-thread-2]: Was skipped: hand:cbt:Lightning Bolt:1
WARN [2013-09-10 02:52 [40:723]] SystemUtil[pool-2-thread-2]: Was skipped: library:cbt:Shock:2

I also get a long list of errors like these for what comes out of cheat.dck but those enter the battlefield just fine.

WARN [2013-09-10 02:52 [40:644]] CardImpl[pool-2-thread-2]: putOntoBattlefield, not fully implemented: fromZone=OUTSIDE
WARN [2013-09-10 02:52 [40:644]] CardImpl[pool-2-thread-2]: Couldn't find card in fromZone, card=Forest, fromZone=OUTSIDE
WARN [2013-09-10 02:52 [40:646]] CardImpl[pool-2-thread-2]: putOntoBattlefield, not fully implemented: fromZone=OUTSIDE
WARN [2013-09-10 02:52 [40:646]] CardImpl[pool-2-thread-2]: Couldn't find card in fromZone, card=Forest, fromZone=OUTSIDE
If you use the fast match button, your player name is always "Human".
So I guess if you change "cbt" to "Human" it will work.

Re: Help implementing a card

PostPosted: 23 Sep 2013, 19:11
by Backfir3
I need help with Lotus Vale. I've done the card and the part that's bugged is that when the player doesn't sacrifice the lands Lotus Vale should go to the graveyard, instead nothing happens. In server console I have no error. Help :?

Here's the code

Code: Select all
package mage.sets.weatherlight;

import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.AddManaOfAnyColorEffect;
import mage.abilities.mana.SimpleManaAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.choices.ChoiceColor;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.common.FilterLandPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.permanent.TappedPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetControlledPermanent;

/**
 *
 * @author Backfir3
 */
public class LotusVale extends CardImpl<LotusVale> {

    public LotusVale(UUID ownerId) {
        super(ownerId, 165, "Lotus Vale", Rarity.RARE, new CardType[]{CardType.LAND}, "");
        this.expansionSetCode = "WTH";

      // If Lotus Vale would enter the battlefield, sacrifice two untapped lands instead.
      // If you do, put Lotus Vale onto the battlefield. If you don't, put it into its owner's graveyard.
        this.addAbility(new SimpleStaticAbility(Zone.ALL, new LotusValeReplacementEffect()));
      
      // {T}: Add three mana of any one color to your mana pool.
        Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, new AddManaOfAnyColorEffect(3), new TapSourceCost());
        ability.addChoice(new ChoiceColor());
        this.addAbility(ability);
    }

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

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

class LotusValeReplacementEffect extends ReplacementEffectImpl<LotusValeReplacementEffect> {

    private static final FilterLandPermanent filter = new FilterLandPermanent("two untapped lands");

    static {
        filter.add(Predicates.not(new TappedPredicate()));
    }

    public LotusValeReplacementEffect() {
        super(Duration.WhileOnBattlefield, Outcome.Exile);
        staticText = "If Lotus Vale would enter the battlefield, sacrifice two untapped lands instead. If you do, put Lotus Vale onto the battlefield. If you don't, put it into its owner's graveyard.";
    }

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

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

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

    @Override
    public boolean replaceEvent(GameEvent event, Ability source, Game game) {
        Player player = game.getPlayer(source.getControllerId());
      TargetControlledPermanent target = new TargetControlledPermanent(2, 2, filter, false);
        if (player != null){
            if (player.chooseUse(Outcome.Sacrifice, "Sacrifice two untapped lands or Lotus Vale goes to the owner's graveyard?", game)) {
                if (target.canChoose(player.getId(), game)) {
                    while (!target.isChosen()) {
                        player.choose(Outcome.Sacrifice, target, source.getSourceId(), game);
                    }
                    List<UUID> chosenTargets = target.getTargets();
               for (UUID permID : chosenTargets) {
                  Permanent permanent = game.getPermanent(permID);
                  if (permanent != null) {
                     if (!permanent.sacrifice(source.getSourceId(), game)) {
                                return true;
                            }
                  }
               }
               return false;
                }
            }
            else{
                Card card = game.getCard(event.getTargetId());
                if (card != null) {
                    return card.moveToZone(Zone.GRAVEYARD, source.getId(), game, true);
                }
                return true;
            }
           
        }
        return false;
    }

    @Override
    public boolean applies(GameEvent event, Ability source, Game game) {
        if (event.getType() == GameEvent.EventType.ZONE_CHANGE && ((ZoneChangeEvent)event).getToZone() == Zone.BATTLEFIELD) {
            UUID sourceID = source.getSourceId();
            if(source.getSourceId().equals(event.getTargetId())){
                return true;
            }
        }
        return false;
    }

}
Btw, when I was looking for a similar card, I discovered Mox Diamond and it's bugged too. When the player chose not to discard a land, Mox Diamond clones itself, one copy in the graveyard and another on the battlefield. In console there's this "FATAL [2013-09-23 20:54 [01:692]] CardImpl[pool-3-thread-1]: invalid zone for card - BATTLEFIELD".

Re: Help implementing a card

PostPosted: 23 Sep 2013, 22:13
by LevelX
Backfir3 wrote:I need help with Lotus Vale. I've done the card and the part that's bugged is that when the player doesn't sacrifice the lands Lotus Vale should go to the graveyard, instead nothing happens. In server console I have no error. Help :?
Btw, when I was looking for a similar card, I discovered Mox Diamond and it's bugged too. When the player chose not to discard a land, Mox Diamond clones itself, one copy in the graveyard and another on the battlefield. In console there's this "FATAL [2013-09-23 20:54 [01:692]] CardImpl[pool-3-thread-1]: invalid zone for card - BATTLEFIELD".
Hello Backfir3,
I fixed Mox Diamon (used the wrong event), I guess you can change Lotus Vale in the same way.
Regards
LevelX2

Re: Help implementing a card

PostPosted: 10 Oct 2013, 19:08
by cbt33
Trying to implement Cabal Patriarch I receive a null pointer exception with this:

Code: Select all
public class CabalPatriarch extends CardImpl<CabalPatriarch> {

    public CabalPatriarch(UUID ownerId) {
        super(ownerId, 120, "Cabal Patriarch", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{B}{B}{B}");
        this.expansionSetCode = "ODY";
        this.supertype.add("Legendary");
        this.subtype.add("Human");
        this.subtype.add("Wizard");

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

       // {2}{B}, Sacrifice a creature: Target creature gets -2/-2 until end of turn.
      Ability ability1 = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(-2, -2, Duration.EndOfTurn), new ManaCostsImpl("{2}{B}"));
      ability1.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(true), true));
      ability1.addTarget(new TargetCreaturePermanent(true));
      this.addAbility(ability1);
       
        // {2}{B}, Exile a creature card from your graveyard: Target creature gets -2/-2 until end of turn.
      Ability ability2 = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(-2, -2, Duration.EndOfTurn), new ManaCostsImpl("{2}{B}"));
      ability2.addCost(new ExileFromGraveCost(new TargetCardInYourGraveyard(new FilterCreatureCard())));
      ability2.addTarget(new TargetCreaturePermanent(true));
      this.addAbility(ability2);
    }

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

    @Override
    public CabalPatriarch copy() {
        return new CabalPatriarch(this);
    }
}
Also, if I was given access to edit the main on the GitHub repo, should I still do a pull request for what I add just to make sure someone looks at it before it goes through?

Re: Help implementing a card

PostPosted: 10 Oct 2013, 20:59
by LevelX
cbt33 wrote:Trying to implement Cabal Patriarch I receive a null pointer exception with this:

Code: Select all
 new SacrificeTargetCost(new TargetControlledCreaturePermanent(true), true);
The problem was the second parameter of the SacrificeTargetCost.


Here's the working code:
Code: Select all
public class CabalPatriarch extends CardImpl<CabalPatriarch> {

    public CabalPatriarch(UUID ownerId) {
        super(ownerId, 120, "Cabal Patriarch", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{B}{B}{B}");
        this.expansionSetCode = "ODY";
        this.supertype.add("Legendary");
        this.subtype.add("Human");
        this.subtype.add("Wizard");

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

       // {2}{B}, Sacrifice a creature: Target creature gets -2/-2 until end of turn.
      Ability ability1 = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(-2, -2, Duration.EndOfTurn), new ManaCostsImpl("{2}{B}"));
      TargetControlledPermanent target = new TargetControlledPermanent(new FilterControlledCreaturePermanent(""));
      target.setRequired(true);
      ability1.addCost(new SacrificeTargetCost(target));
      ability1.addTarget(new TargetCreaturePermanent(true));
      this.addAbility(ability1);

        // {2}{B}, Exile a creature card from your graveyard: Target creature gets -2/-2 until end of turn.
      Ability ability2 = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(-2, -2, Duration.EndOfTurn), new ManaCostsImpl("{2}{B}"));
      ability2.addCost(new ExileFromGraveCost(new TargetCardInYourGraveyard(new FilterCreatureCard("a creature card"))));
      ability2.addTarget(new TargetCreaturePermanent(true));
      this.addAbility(ability2);
    }

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

    @Override
    public CabalPatriarch copy() {
        return new CabalPatriarch(this);
    }
}
cbt33 wrote:Also, if I was given access to edit the main on the GitHub repo, should I still do a pull request for what I add just to make sure someone looks at it before it goes through?
If you like or not sure if your code is ok, you can do a pull request.

Re: Help implementing a card

PostPosted: 21 Dec 2013, 04:07
by cbt33
If I commit files using NetBeans>Team>Commit... do they show up in or around the main repo if I have a cloned repo or are there more steps?

Re: Help implementing a card

PostPosted: 21 Dec 2013, 14:34
by LevelX
cbt33 wrote:If I commit files using NetBeans>Team>Commit... do they show up in or around the main repo if I have a cloned repo or are there more steps?
You have also to do [Project]->Git->Remote->Push... after committing to your local repository.

Re: Help implementing a card

PostPosted: 03 Jan 2014, 01:45
by cbt33
Can anyone tell why the tool tip for Zombie Cannibal doesn't show and the tooltip for Savage Firecat doesn't show completely?

Zombie Cannibal:
Code: Select all
      this.power = new MageInt(1);
        this.toughness = new MageInt(1);

        // Whenever Zombie Cannibal deals combat damage to a player, you may exile target card from that player's graveyard.
    this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new ZombieCannibalEffect(), true, true));
   
    }

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

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

class ZombieCannibalEffect extends OneShotEffect<ZombieCannibalEffect> {
   
    public ZombieCannibalEffect() {
        super(Outcome.Exile);
        staticText = "you may exile target card from that player's graveyard.";
    }
   
    public ZombieCannibalEffect(final ZombieCannibalEffect effect) {
        super(effect);
    }
   
    @Override
    public ZombieCannibalEffect copy() {
        return new ZombieCannibalEffect(this);
    }
   
    @Override
    public boolean apply(Game game, Ability source) {
        FilterCard filter = new FilterCard();
        Player player = game.getPlayer(source.getTargets().getFirstTarget());
        if (player != null) {
            filter.add(new OwnerIdPredicate(player.getId()));
            Target target = new TargetCardInGraveyard(filter);
            game.getPermanent(target.getFirstTarget()).moveToExile(null, null, source.getSourceId(), game);
        }
        return false;
    }
   
}
Savage Firecat:
Code: Select all
this.addAbility(new SavageFirecatTriggeredAbility(new RemoveCounterSourceEffect(new PlusOneCounter(1))));

    }

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

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

class SavageFirecatTriggeredAbility extends TriggeredAbilityImpl<SavageFirecatTriggeredAbility> {

    public SavageFirecatTriggeredAbility(Effect effect) {
        super(Zone.BATTLEFIELD, effect, false);
    }

    public SavageFirecatTriggeredAbility(final SavageFirecatTriggeredAbility ability) {
        super(ability);
    }

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

    @Override
    public boolean checkTrigger(GameEvent event, Game game) {
        if (event.getType() == EventType.TAPPED_FOR_MANA &&
                game.getCard(event.getSourceId()).getCardType().contains(CardType.LAND) &&
                event.getPlayerId().equals(this.controllerId)){
            return true;
        }
    return false;
}
   
    @Override
    public String getRule() {
        return "Whenever you tap a land for mana,";
}

}

Re: Help implementing a card

PostPosted: 03 Jan 2014, 06:47
by LevelX
cbt33 wrote:Can anyone tell why the tool tip for Zombie Cannibal doesn't show and the tooltip for Savage Firecat doesn't show completely?

Zombie Cannibal:
Code: Select all
      this.power = new MageInt(1);
        this.toughness = new MageInt(1);

        // Whenever Zombie Cannibal deals combat damage to a player, you may exile target card from that player's graveyard.
    this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new ZombieCannibalEffect(), true, true));
   
    }

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

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

class ZombieCannibalEffect extends OneShotEffect<ZombieCannibalEffect> {
   
    public ZombieCannibalEffect() {
        super(Outcome.Exile);
        staticText = "you may exile target card from that player's graveyard.";
    }
   
    public ZombieCannibalEffect(final ZombieCannibalEffect effect) {
        super(effect);
    }
   
    @Override
    public ZombieCannibalEffect copy() {
        return new ZombieCannibalEffect(this);
    }
   
    @Override
    public boolean apply(Game game, Ability source) {
        FilterCard filter = new FilterCard();
        Player player = game.getPlayer(source.getTargets().getFirstTarget());
        if (player != null) {
            filter.add(new OwnerIdPredicate(player.getId()));
            Target target = new TargetCardInGraveyard(filter);
            game.getPermanent(target.getFirstTarget()).moveToExile(null, null, source.getSourceId(), game);
        }
        return false;
    }
   
}
Savage Firecat:
Code: Select all
this.addAbility(new SavageFirecatTriggeredAbility(new RemoveCounterSourceEffect(new PlusOneCounter(1))));

    }

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

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

class SavageFirecatTriggeredAbility extends TriggeredAbilityImpl<SavageFirecatTriggeredAbility> {

    public SavageFirecatTriggeredAbility(Effect effect) {
        super(Zone.BATTLEFIELD, effect, false);
    }

    public SavageFirecatTriggeredAbility(final SavageFirecatTriggeredAbility ability) {
        super(ability);
    }

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

    @Override
    public boolean checkTrigger(GameEvent event, Game game) {
        if (event.getType() == EventType.TAPPED_FOR_MANA &&
                game.getCard(event.getSourceId()).getCardType().contains(CardType.LAND) &&
                event.getPlayerId().equals(this.controllerId)){
            return true;
        }
    return false;
}
   
    @Override
    public String getRule() {
        return "Whenever you tap a land for mana,";
}

}
Did you delete the cards.db files of the server and client project after making changes to the cards?
Because the texts are taken from there won't be updated automatically! Only if you delete the files, then they are recreated with the updated texts from the changed java sources.