Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[YMID] Implement Arms Scavenger and 3 other cards, rework Seek effect #12802

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
71 changes: 71 additions & 0 deletions Mage.Sets/src/mage/cards/a/ArmsScavenger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package mage.cards.a;

import mage.MageInt;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.DraftFromSpellbookThenExilePlayThisTurnEffect;
import mage.abilities.effects.common.cost.AbilitiesCostReductionControllerEffect;
import mage.abilities.keyword.EquipAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.TargetController;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;

/**
* @author Sidorovich77
*/
public final class ArmsScavenger extends CardImpl {

private static final List<String> spellbook = Collections.unmodifiableList(Arrays.asList(
"Boots of Speed",
"Ceremonial Knife",
"Cliffhaven Kitesail",
"Colossus Hammer",
"Dueling Rapier",
"Goldvein Pick",
"Jousting Lance",
"Mask of Immolation",
"Mirror Shield",
"Relic Axe",
"Rogue's Gloves",
"Scavenged Blade",
"Shield of the Realm",
"Spare Dagger",
"Tormentor's Helm"
));

public ArmsScavenger(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");

this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.WARRIOR);
this.power = new MageInt(2);
this.toughness = new MageInt(2);


// At the beginning of your upkeep, draft a card from Arms Scavenger’s spellbook, then exile it. Until end of turn, you may play that card.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DraftFromSpellbookThenExilePlayThisTurnEffect(spellbook), TargetController.YOU, false));


// Equip abilities you activate cost {1} less to activate.
this.addAbility(new SimpleStaticAbility(new AbilitiesCostReductionControllerEffect(
EquipAbility.class, "Equip", 1
).setText("equip abilities you activate cost {1} less to activate")));

}

private ArmsScavenger(final ArmsScavenger card) {
super(card);
}

@Override
public ArmsScavenger copy() {
return new ArmsScavenger(this);
}
}
82 changes: 82 additions & 0 deletions Mage.Sets/src/mage/cards/g/GeistpackAlpha.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package mage.cards.g;

import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.StaticFilters;
import mage.filter.common.FilterPermanentCard;
import mage.filter.predicate.mageobject.ManaValuePredicate;
import mage.game.Game;
import mage.players.Player;

import java.util.UUID;

/**
* @author Sidorovich77
*/
public final class GeistpackAlpha extends CardImpl {


public GeistpackAlpha(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}");

this.subtype.add(SubType.WOLF);
this.power = new MageInt(5);
this.toughness = new MageInt(4);

// Trample
this.addAbility(TrampleAbility.getInstance());


// When Geistpack Alpha dies, seek a permanent card with mana value equal to the number of lands you control.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

miss card hint with lands amount info

this.addAbility(new DiesSourceTriggeredAbility(new GeistpackAlphaDiesEffect()));

}

private GeistpackAlpha(final GeistpackAlpha card) {
super(card);
}

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

class GeistpackAlphaDiesEffect extends OneShotEffect {

GeistpackAlphaDiesEffect() {
super(Outcome.Benefit);
staticText = " seek a permanent card with mana value equal to the number of lands you control.";
}

private GeistpackAlphaDiesEffect(final GeistpackAlphaDiesEffect effect) {
super(effect);
}

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

@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
int lands = game.getBattlefield().countAll(StaticFilters.FILTER_LAND, game.getControllerId(source.getSourceId()), game);
FilterPermanentCard filter = new FilterPermanentCard();
filter.add(new ManaValuePredicate(ComparisonType.EQUAL_TO, lands));
player.seekCard(filter, source, game);
return true;
}
}
75 changes: 75 additions & 0 deletions Mage.Sets/src/mage/cards/s/SettleTheWilds.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@

package mage.cards.s;

import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.SeekCardEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.filter.common.FilterPermanentCard;
import mage.filter.predicate.mageobject.ManaValuePredicate;
import mage.game.Game;
import mage.players.Player;

import java.util.UUID;

/**
* @author Sidorovich77
*/
public final class SettleTheWilds extends CardImpl {

public SettleTheWilds(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}");

// Seek a basic land card and put it onto the battlefield tapped.
// Then seek a permanent card with mana value equal to the number of lands you control.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Must use one line per ability for rules text as comment for better text and regexp searching by IDE

this.getSpellAbility().addEffect(new SeekCardEffect(StaticFilters.FILTER_CARD_BASIC_LAND, Zone.BATTLEFIELD, true).setText("Seek a basic land card and put it onto the battlefield tapped. "));
this.getSpellAbility().addEffect(new SettleTheWildsSeekEffect());

}

private SettleTheWilds(final SettleTheWilds card) {
super(card);
}

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

class SettleTheWildsSeekEffect extends OneShotEffect {

SettleTheWildsSeekEffect() {
super(Outcome.Benefit);
staticText = "Then seek a permanent card with mana value equal to the number of lands you control.";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why it's a custom effect instead of standard SeekCardEffect?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, the custom filter isn't actually necessary. You can make a predicate like ManaValueLessThanControlledLandCountPredicate but with equal to instead

}

private SettleTheWildsSeekEffect(final SettleTheWildsSeekEffect effect) {
super(effect);
}

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

@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
int lands = game.getBattlefield().countAll(StaticFilters.FILTER_LAND, game.getControllerId(source.getSourceId()), game);
FilterPermanentCard filter = new FilterPermanentCard();
filter.add(new ManaValuePredicate(ComparisonType.EQUAL_TO, lands));
player.seekCard(filter, source, game);
return true;
}
}

123 changes: 123 additions & 0 deletions Mage.Sets/src/mage/cards/t/TibaltWickedTormentor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package mage.cards.t;

import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.costs.common.DiscardCardCost;
import mage.abilities.dynamicvalue.common.GetXValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.DraftFromSpellbookThenExileCastThisTurnEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.mana.BasicManaEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.DevilToken;
import mage.players.Player;
import mage.target.common.TargetCreatureOrPlaneswalker;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;

/**
* @author Sidorovich77
*/
public final class TibaltWickedTormentor extends CardImpl {

private static final List<String> spellbook = Collections.unmodifiableList(Arrays.asList(
"Brimstone Vandal",
"Chained Brute",
"Charmbreaker Devils",
"Devil's Play",
"Festival Crasher",
"Forge Devil",
"Frenzied Devils",
"Havoc Jester",
"Hellrider",
"Hobblefiend",
"Pitchburn Devils",
"Sin Prodder",
"Spiteful Prankster",
"Tibalt's Rager",
"Torch Fiend"
));

public TibaltWickedTormentor(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{3}{R}{R}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.TIBALT);

this.setStartingLoyalty(3);

// +1: Add {R}{R}. Draft a card from Tibalt, Wicked Tormentor’s spellbook, then exile it. Until end of turn, you may cast that card.
Ability ability = new LoyaltyAbility(new BasicManaEffect(Mana.RedMana(2)), 1);
ability.addEffect(new DraftFromSpellbookThenExileCastThisTurnEffect(spellbook));
this.addAbility(ability);

// +1: Tibalt, Wicked Tormentor deals 4 damage to target creature or planeswalker unless its controller has Tibalt deal 4 damage to them.
// If they do, you may discard a card. If you do, draw a card.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

must use one line comment in card

Ability ability1 = new LoyaltyAbility(new TibaltDamageEffect(), 1);
ability1.addTarget(new TargetCreatureOrPlaneswalker());
this.addAbility(ability1);

// -X: Create X 1/1 red Devil creature tokens with “When this creature dies, it deals 1 damage to any target.”
this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new DevilToken(), GetXValue.instance)));
}

private TibaltWickedTormentor(final TibaltWickedTormentor card) {
super(card);
}

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

class TibaltDamageEffect extends OneShotEffect {

TibaltDamageEffect() {
super(Outcome.Neutral);
this.staticText = " {this} deals 4 damage to target creature or planeswalker unless its controller has Tibalt deal 4 damage to them." +
" If they do, you may discard a card. If you do, draw a card.";
}

private TibaltDamageEffect(final TibaltDamageEffect effect) {
super(effect);
}

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

@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getFirstTarget());
Player player = game.getPlayer(source.getControllerId());
Player controller = game.getPlayer(permanent.getControllerId());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Miss permanent null check
  2. Looks like you wrongly use player and controller (must invert). Also check who does damage and make an answer.

if (player == null || controller == null) {
String message = "Have Tibalt, Wicked Tormentor do 4 damage to you?";
if (controller.chooseUse(Outcome.Damage, message, source, game)) {
controller.damage(4, source.getSourceId(), source, game);
Effect effect = new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new DiscardCardCost());
effect.apply(game, source);
} else {
permanent.damage(4, source, game);
}
return true;
}
return false;
}
}

5 changes: 4 additions & 1 deletion Mage.Sets/src/mage/sets/AlchemyInnistrad.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,20 @@ private AlchemyInnistrad() {
this.hasBoosters = false;
this.hasBasicLands = false;

cards.add(new SetCardInfo("Arms Scavenger", 35, Rarity.RARE, mage.cards.a.ArmsScavenger.class));
cards.add(new SetCardInfo("Citystalker Connoisseur", 27, Rarity.RARE, mage.cards.c.CitystalkerConnoisseur.class));
cards.add(new SetCardInfo("Cursebound Witch", 24, Rarity.UNCOMMON, mage.cards.c.CurseboundWitch.class));
cards.add(new SetCardInfo("Expedition Supplier", 6, Rarity.RARE, mage.cards.e.ExpeditionSupplier.class));
cards.add(new SetCardInfo("Faithful Disciple", 7, Rarity.UNCOMMON, mage.cards.f.FaithfulDisciple.class));
cards.add(new SetCardInfo("Geistpack Alpha", 48, Rarity.RARE, mage.cards.g.GeistpackAlpha.class));
cards.add(new SetCardInfo("Ishkanah, Broodmother", 52, Rarity.MYTHIC, mage.cards.i.IshkanahBroodmother.class));
cards.add(new SetCardInfo("Key to the Archive", 59, Rarity.RARE, mage.cards.k.KeyToTheArchive.class));
cards.add(new SetCardInfo("Kindred Denial", 18, Rarity.UNCOMMON, mage.cards.k.KindredDenial.class));
cards.add(new SetCardInfo("Obsessive Collector", 19, Rarity.RARE, mage.cards.o.ObsessiveCollector.class));
cards.add(new SetCardInfo("Sanguine Brushstroke", 32, Rarity.RARE, mage.cards.s.SanguineBrushstroke.class));
cards.add(new SetCardInfo("Settle the Wilds", 55, Rarity.UNCOMMON, mage.cards.s.SettleTheWilds.class));
cards.add(new SetCardInfo("Soulstealer Axe", 60, Rarity.UNCOMMON, mage.cards.s.SoulstealerAxe.class));
cards.add(new SetCardInfo("Suntail Squadron", 11, Rarity.RARE, mage.cards.s.SuntailSquadron.class));
cards.add(new SetCardInfo("Tibalt, Wicked Tormentor", 43, Rarity.MYTHIC, mage.cards.t.TibaltWickedTormentor.class));
cards.add(new SetCardInfo("Tireless Angler", 23, Rarity.RARE, mage.cards.t.TirelessAngler.class));
cards.add(new SetCardInfo("Toralf's Disciple", 44, Rarity.RARE, mage.cards.t.ToralfsDisciple.class));
}
Expand Down
Loading
Loading