diff --git a/Mage.Sets/src/mage/cards/b/BlasterCombatDJ.java b/Mage.Sets/src/mage/cards/b/BlasterCombatDJ.java new file mode 100644 index 000000000000..a75d0bae3fad --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BlasterCombatDJ.java @@ -0,0 +1,153 @@ +package mage.cards.b; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.ModularAbility; +import mage.constants.*; +import mage.abilities.keyword.MoreThanMeetsTheEyeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.Game; +import mage.game.events.EntersTheBattlefieldEvent; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.permanent.PermanentToken; +import mage.players.Player; + +/** + * + * @author anonymous + */ +public final class BlasterCombatDJ extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("Other nontoken artifact creatures and Vehicles you control"); + + static { + filter.add(TargetController.YOU.getControllerPredicate()); + filter.add(AnotherPredicate.instance); + filter.add(Predicates.or( + Predicates.and(TokenPredicate.FALSE, CardType.ARTIFACT.getPredicate(), CardType.CREATURE.getPredicate()), + SubType.VEHICLE.getPredicate()) + ); + } + + public BlasterCombatDJ(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}{R}{G}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.ROBOT); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + this.secondSideCardClazz = mage.cards.b.BlasterMoraleBooster.class; + + // More Than Meets the Eye {1}{R}{G} + this.addAbility(new MoreThanMeetsTheEyeAbility(this, "{1}{R}{G}")); + + // Other nontoken artifact creatures and Vehicles you control have modular 1. + Ability ability = new SimpleStaticAbility(new BlasterCombatDJReplacementEffect()); + ability.addEffect(new GainAbilityControlledEffect( + new ModularAbility(1), Duration.WhileOnBattlefield, filter + ).setText("")); + this.addAbility(ability); + + // Whenever you put one or more +1/+1 counters on Blaster, convert it. + this.addAbility(new BlasterCombatDJTriggeredAbility()); + } + + private BlasterCombatDJ(final BlasterCombatDJ card) { + super(card); + } + + @Override + public BlasterCombatDJ copy() { + return new BlasterCombatDJ(this); + } +} + +class BlasterCombatDJReplacementEffect extends ReplacementEffectImpl { + + BlasterCombatDJReplacementEffect() { + super(Duration.WhileOnBattlefield, Outcome.BoostCreature); + staticText = "Other nontoken artifact creatures and Vehicles you control have modular 1. " + + "(They enter with an additional +1/+1 counter on them. When they die, you may put " + + "their +1/+1 counters on target artifact creature.)"; + } + + private BlasterCombatDJReplacementEffect(BlasterCombatDJReplacementEffect effect) { + super(effect); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + Permanent creatureOrVehicle = ((EntersTheBattlefieldEvent) event).getTarget(); + return creatureOrVehicle != null + && creatureOrVehicle.getId() != source.getSourceId() + && creatureOrVehicle.isControlledBy(source.getControllerId()) + && ((creatureOrVehicle.isCreature(game) + && creatureOrVehicle.isArtifact(game) + && !(creatureOrVehicle instanceof PermanentToken)) + || creatureOrVehicle.hasSubtype(SubType.VEHICLE, game)); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget(); + Player player = game.getPlayer(source.getControllerId()); + if (creature == null || player == null) { + return false; + } + creature.addCounters(CounterType.P1P1.createInstance(), source.getControllerId(), source, game, event.getAppliedEffects()); + return false; + } + + @Override + public BlasterCombatDJReplacementEffect copy() { + return new BlasterCombatDJReplacementEffect(this); + } +} + +class BlasterCombatDJTriggeredAbility extends TriggeredAbilityImpl { + + BlasterCombatDJTriggeredAbility() { + super(Zone.BATTLEFIELD, new TransformSourceEffect().setText("convert {this}")); + this.setTriggerPhrase("Whenever you put one or more +1/+1 counters on {this}, "); + } + + private BlasterCombatDJTriggeredAbility(final BlasterCombatDJTriggeredAbility ability) { + super(ability); + } + + @Override + public BlasterCombatDJTriggeredAbility copy() { + return new BlasterCombatDJTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.COUNTERS_ADDED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return event.getData().equals(CounterType.P1P1.getName()) + && isControlledBy(event.getPlayerId()) + && event.getTargetId().equals(getSourceId()); + } + +} diff --git a/Mage.Sets/src/mage/cards/b/BlasterMoraleBooster.java b/Mage.Sets/src/mage/cards/b/BlasterMoraleBooster.java new file mode 100644 index 000000000000..942f988b2750 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BlasterMoraleBooster.java @@ -0,0 +1,114 @@ +package mage.cards.b; + +import java.util.UUID; + +import mage.abilities.Ability; +import mage.abilities.common.ActivateAsSorceryActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.HasteAbility; +import mage.constants.Outcome; +import mage.constants.SuperType; +import mage.abilities.keyword.ModularAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterArtifactPermanent; +import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; +import mage.util.CardUtil; + +/** + * + * @author anonymous + */ +public final class BlasterMoraleBooster extends CardImpl { + + private static final FilterPermanent filter = new FilterArtifactPermanent("another target artifact"); + + static { + filter.add(AnotherPredicate.instance); + } + + public BlasterMoraleBooster(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, ""); + + this.supertype.add(SuperType.LEGENDARY); + this.color.setRed(true); + this.color.setGreen(true); + this.nightCard = true; + + // Modular 3 + this.addAbility(new ModularAbility(this, 3)); + + // {X}, {T}: Move X +1/+1 counters from Blaster onto another target artifact. That artifact gains haste until end of turn. If Blaster has no +1/+1 counters on it, convert it. Activate only as a sorcery. + Ability ability = new ActivateAsSorceryActivatedAbility(new BlasterMoraleBoosterEffect(), new ManaCostsImpl<>("{X}")); + ability.addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance()) + .setText("")); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + } + + private BlasterMoraleBooster(final BlasterMoraleBooster card) { + super(card); + } + + @Override + public BlasterMoraleBooster copy() { + return new BlasterMoraleBooster(this); + } +} + +class BlasterMoraleBoosterEffect extends OneShotEffect { + + BlasterMoraleBoosterEffect() { + super(Outcome.Benefit); + staticText = "Move X +1/+1 counters from {this} onto another target artifact. " + + "That artifact gains haste until end of turn. " + + "If Blaster has no +1/+1 counters on it, convert it."; + } + + private BlasterMoraleBoosterEffect(final BlasterMoraleBoosterEffect effect) { + super(effect); + } + + @Override + public BlasterMoraleBoosterEffect copy() { + return new BlasterMoraleBoosterEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent toPermanent = game.getPermanent(source.getFirstTarget()); + Permanent fromPermanent = game.getPermanent(source.getSourceId()); + if (fromPermanent == null + || toPermanent == null + || controller == null + || !fromPermanent.getCounters(game).containsKey(CounterType.P1P1)) { + return false; + } + + // Remove X +1/+1 counters, or all of them. + int countersToMove = Math.min( + CardUtil.getSourceCostsTag(game, source, "X", 0), + fromPermanent.getCounters(game).getCount(CounterType.P1P1.getName()) + ); + fromPermanent.removeCounters(CounterType.P1P1.getName(), countersToMove, source, game); + //put the same number of counters on the other artifact. + toPermanent.addCounters(CounterType.P1P1.createInstance(countersToMove), source.getControllerId(), source, game); + if (fromPermanent.getCounters(game).getCount(CounterType.P1P1.getName()) == 0) { + return fromPermanent.transform(source, game); + } + return true; + } + +} diff --git a/Mage.Sets/src/mage/sets/Transformers.java b/Mage.Sets/src/mage/sets/Transformers.java index 1a228b0b29bd..db95589d6eb5 100644 --- a/Mage.Sets/src/mage/sets/Transformers.java +++ b/Mage.Sets/src/mage/sets/Transformers.java @@ -21,6 +21,8 @@ private Transformers() { cards.add(new SetCardInfo("Arcee, Acrobatic Coupe", 7, Rarity.MYTHIC, mage.cards.a.ArceeAcrobaticCoupe.class)); cards.add(new SetCardInfo("Arcee, Sharpshooter", 7, Rarity.MYTHIC, mage.cards.a.ArceeSharpshooter.class)); + cards.add(new SetCardInfo("Blaster, Combat DJ", 8, Rarity.MYTHIC, mage.cards.b.BlasterCombatDJ.class)); + cards.add(new SetCardInfo("Blaster, Morale Booster", 8, Rarity.MYTHIC, mage.cards.b.BlasterMoraleBooster.class)); cards.add(new SetCardInfo("Blitzwing, Adaptive Assailant", 4, Rarity.MYTHIC, mage.cards.b.BlitzwingAdaptiveAssailant.class)); cards.add(new SetCardInfo("Blitzwing, Cruel Tormentor", 4, Rarity.MYTHIC, mage.cards.b.BlitzwingCruelTormentor.class)); cards.add(new SetCardInfo("Flamewar, Brash Veteran", 10, Rarity.MYTHIC, mage.cards.f.FlamewarBrashVeteran.class)); diff --git a/Mage/src/main/java/mage/abilities/keyword/ModularAbility.java b/Mage/src/main/java/mage/abilities/keyword/ModularAbility.java index f11bb84d88c4..83fbecbb9fd3 100644 --- a/Mage/src/main/java/mage/abilities/keyword/ModularAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/ModularAbility.java @@ -47,6 +47,10 @@ public class ModularAbility extends DiesSourceTriggeredAbility { private final int amount; private final boolean sunburst; + public ModularAbility(int amount) { + this(null, amount); + } + public ModularAbility(Card card, int amount) { this(card, amount, false); }