From 02b97aa9b3d2b5892931651dcdde19e766d636c2 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 2 Nov 2017 13:43:49 +0100 Subject: [PATCH] Some fixes to: Merge pull request #4129 from jerekwilson/master - Implementing 5 cards --- .../src/mage/cards/d/DeadIronSledge.java | 60 ++---- .../src/mage/cards/d/DecreeOfJustice.java | 19 +- Mage.Sets/src/mage/cards/i/IceFloe.java | 8 +- Mage.Sets/src/mage/cards/j/JaggedPoppet.java | 49 ++--- Mage.Sets/src/mage/cards/r/RhysticCave.java | 191 ++++++++++-------- Mage.Sets/src/mage/cards/t/TalonOfPain.java | 104 ++++++++-- Mage.Sets/src/mage/cards/w/WitchEngine.java | 2 +- .../DoUnlessAnyPlayerPaysManaEffect.java | 94 +++++++++ 8 files changed, 336 insertions(+), 191 deletions(-) create mode 100644 Mage/src/main/java/mage/abilities/effects/common/DoUnlessAnyPlayerPaysManaEffect.java diff --git a/Mage.Sets/src/mage/cards/d/DeadIronSledge.java b/Mage.Sets/src/mage/cards/d/DeadIronSledge.java index 11b27920136..a93cad40ce2 100644 --- a/Mage.Sets/src/mage/cards/d/DeadIronSledge.java +++ b/Mage.Sets/src/mage/cards/d/DeadIronSledge.java @@ -35,42 +35,20 @@ import java.util.UUID; import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.common.BlocksAttachedTriggeredAbility; -import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility; -import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.DestroyAllEffect; -import mage.abilities.effects.common.DestroySourceEffect; -import mage.abilities.effects.common.DestroyTargetEffect; -import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; import mage.abilities.keyword.EquipAbility; -import mage.abilities.keyword.FirstStrikeAbility; -import mage.abilities.keyword.TrampleAbility; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AttachmentType; import mage.constants.CardType; -import mage.constants.Duration; import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.permanent.BlockedByIdPredicate; -import mage.filter.predicate.permanent.BlockingAttackerIdPredicate; -import mage.filter.predicate.permanent.PermanentIdPredicate; import mage.game.Game; import mage.game.combat.CombatGroup; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.target.common.TargetCreaturePermanent; -import mage.target.targetpointer.FirstTargetPointer; -import mage.target.targetpointer.FixedTarget; import mage.target.targetpointer.FixedTargets; -import mage.util.CardUtil; /** * @@ -80,13 +58,11 @@ public class DeadIronSledge extends CardImpl { public DeadIronSledge(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}"); - this.subtype.add(SubType.EQUIPMENT); // Whenever equipped creature blocks or becomes blocked by a creature, destroy both creatures. this.addAbility(new DeadIronSledgeTriggeredAbility()); - - + // Equip {2} this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2))); } @@ -99,12 +75,13 @@ public class DeadIronSledge extends CardImpl { public DeadIronSledge copy() { return new DeadIronSledge(this); } - + } + class DeadIronSledgeTriggeredAbility extends TriggeredAbilityImpl { private Set possibleTargets = new HashSet<>(); - + DeadIronSledgeTriggeredAbility() { super(Zone.BATTLEFIELD, new DeadIronSledgeDestroyEffect(), false); } @@ -112,7 +89,7 @@ class DeadIronSledgeTriggeredAbility extends TriggeredAbilityImpl { DeadIronSledgeTriggeredAbility(final DeadIronSledgeTriggeredAbility ability) { super(ability); } - + @Override public boolean checkEventType(GameEvent event, Game game) { return event.getType() == GameEvent.EventType.DECLARED_BLOCKERS; @@ -126,35 +103,32 @@ class DeadIronSledgeTriggeredAbility extends TriggeredAbilityImpl { Permanent equippedPermanent = game.getPermanentOrLKIBattlefield((equipment.getAttachedTo())); if (equippedPermanent != null) { possibleTargets.clear(); - if(equippedPermanent.isBlocked(game)){ + if (equippedPermanent.isBlocked(game)) { possibleTargets.add(equippedPermanent.getId()); //add equipped creature to target list } - String targetName = ""; if (equippedPermanent.isAttacking()) { for (CombatGroup group : game.getCombat().getGroups()) { if (group.getAttackers().contains(equippedPermanent.getId())) { possibleTargets.addAll(group.getBlockers()); } } - targetName = "a creature blocking attacker "; } else if (equippedPermanent.getBlocking() > 0) { for (CombatGroup group : game.getCombat().getGroups()) { if (group.getBlockers().contains(equippedPermanent.getId())) { possibleTargets.addAll(group.getAttackers()); } } - targetName = "a creature blocked by creature "; } if (!possibleTargets.isEmpty()) { this.getTargets().clear(); - + for (UUID creatureId : possibleTargets) { Permanent target = game.getPermanentOrLKIBattlefield(creatureId); targetPermanents.add(target); } - - this.getEffects().get(0).setTargetPointer(new FixedTargets(targetPermanents,game)); - + + this.getEffects().get(0).setTargetPointer(new FixedTargets(targetPermanents, game)); + return true; } } @@ -166,7 +140,7 @@ class DeadIronSledgeTriggeredAbility extends TriggeredAbilityImpl { public TriggeredAbility copy() { return new DeadIronSledgeTriggeredAbility(this); } - + @Override public String getRule() { return "Whenever equipped creature blocks or becomes blocked by a creature, destroy both creatures."; @@ -191,11 +165,11 @@ class DeadIronSledgeDestroyEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - - List targets = this.getTargetPointer().getTargets(game, source); - for(UUID target: targets){ - Permanent permanent = game.getPermanentOrLKIBattlefield(target); - permanent.destroy(target, game, false); + for (UUID targetId : this.getTargetPointer().getTargets(game, source)) { + Permanent permanent = game.getPermanent(targetId); + if (permanent != null) { + permanent.destroy(targetId, game, false); + } } return true; } diff --git a/Mage.Sets/src/mage/cards/d/DecreeOfJustice.java b/Mage.Sets/src/mage/cards/d/DecreeOfJustice.java index b033167814f..8b13bccdb7a 100644 --- a/Mage.Sets/src/mage/cards/d/DecreeOfJustice.java +++ b/Mage.Sets/src/mage/cards/d/DecreeOfJustice.java @@ -54,15 +54,14 @@ import mage.players.Player; public class DecreeOfJustice extends CardImpl { public DecreeOfJustice(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{X}{2}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{X}{2}{W}{W}"); - - // create X 4/4 white Angel creature tokens with flying. + // Create X 4/4 white Angel creature tokens with flying. this.getSpellAbility().addEffect(new CreateTokenEffect(new AngelToken(), new ManacostVariableValue())); - + // Cycling {2}{W} this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{2}{W}"))); - + // When you cycle Decree of Justice, you may pay {X}. If you do, create X 1/1 white Soldier creature tokens. Ability ability = new CycleTriggeredAbility(new DecreeOfJusticeCycleEffect(), true); this.addAbility(ability); @@ -79,28 +78,28 @@ public class DecreeOfJustice extends CardImpl { } class DecreeOfJusticeCycleEffect extends OneShotEffect { - + DecreeOfJusticeCycleEffect() { super(Outcome.Benefit); this.staticText = "you may pay {X}. If you do, create X 1/1 white Soldier creature tokens"; } - + DecreeOfJusticeCycleEffect(final DecreeOfJusticeCycleEffect effect) { super(effect); } - + @Override public DecreeOfJusticeCycleEffect copy() { return new DecreeOfJusticeCycleEffect(this); } - + @Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { int X = player.announceXMana(0, Integer.MAX_VALUE, "Announce the value for {X}", game, source); Cost cost = new GenericManaCost(X); - if(cost.pay(source, game, source.getSourceId(), source.getControllerId(), false)){ + if (cost.pay(source, game, source.getSourceId(), source.getControllerId(), false)) { Token token = new SoldierToken(); token.putOntoBattlefield(X, game, source.getSourceId(), source.getControllerId()); return true; diff --git a/Mage.Sets/src/mage/cards/i/IceFloe.java b/Mage.Sets/src/mage/cards/i/IceFloe.java index 5daccfa4d85..5dff9889085 100644 --- a/Mage.Sets/src/mage/cards/i/IceFloe.java +++ b/Mage.Sets/src/mage/cards/i/IceFloe.java @@ -32,7 +32,6 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SkipUntapOptionalAbility; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.DontUntapAsLongAsSourceTappedEffect; import mage.abilities.effects.common.TapTargetEffect; import mage.abilities.keyword.FlyingAbility; @@ -47,7 +46,7 @@ import mage.target.common.TargetCreaturePermanent; /** * - + * * @author TheElk801 */ public class IceFloe extends CardImpl { @@ -64,9 +63,8 @@ public class IceFloe extends CardImpl { // You may choose not to untap Ice Floe during your untap step. this.addAbility(new SkipUntapOptionalAbility()); - // {tap}: Tap target creature without flying that's attacking you. It doesn't untap during its controller's untap step for as long as Ice Floe remains tapped. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), new GenericManaCost(1)); - ability.addCost(new TapSourceCost()); + // {T}: Tap target creature without flying that's attacking you. It doesn't untap during its controller's untap step for as long as Ice Floe remains tapped. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), new TapSourceCost()); ability.addTarget(new TargetCreaturePermanent(filter)); ability.addEffect(new DontUntapAsLongAsSourceTappedEffect()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/j/JaggedPoppet.java b/Mage.Sets/src/mage/cards/j/JaggedPoppet.java index e8627cd335f..7062dbf0e7b 100644 --- a/Mage.Sets/src/mage/cards/j/JaggedPoppet.java +++ b/Mage.Sets/src/mage/cards/j/JaggedPoppet.java @@ -34,15 +34,13 @@ import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.common.DealtDamageToSourceTriggeredAbility; import mage.abilities.condition.common.HellbentCondition; import mage.abilities.decorator.ConditionalTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.discard.DiscardControllerEffect; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.Zone; import mage.game.Game; import mage.players.Player; @@ -55,28 +53,23 @@ public class JaggedPoppet extends CardImpl { public JaggedPoppet(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{R}"); - + this.subtype.add(SubType.OGRE); this.subtype.add(SubType.WARRIOR); this.power = new MageInt(3); this.toughness = new MageInt(4); // Whenever Jagged Poppet is dealt damage, discard that many cards. - Ability dealtDamageAbility = new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new JaggedPoppetDealtDamageEffect(), false, false, true); - this.addAbility(dealtDamageAbility); - + this.addAbility(new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new JaggedPoppetDealtDamageEffect(), false, false, true)); + // Hellbent - Whenever Jagged Poppet deals combat damage to a player, if you have no cards in hand, that player discards cards equal to the damage. Ability hellbentAbility = new ConditionalTriggeredAbility( - new DealsCombatDamageToAPlayerTriggeredAbility(new JaggedPoppetDealsDamageEffect(), false,true), - HellbentCondition.instance, + new DealsCombatDamageToAPlayerTriggeredAbility(new JaggedPoppetDealsDamageEffect(), false, true), + HellbentCondition.instance, "Hellbent - Whenever {this} deals combat damage to a player, if you have no cards in hand, that player discards cards equal to the damage."); - hellbentAbility.setAbilityWord(AbilityWord.HELLBENT); this.addAbility(hellbentAbility); - - - - + } public JaggedPoppet(final JaggedPoppet card) { @@ -89,14 +82,13 @@ public class JaggedPoppet extends CardImpl { } } - class JaggedPoppetDealsDamageEffect extends OneShotEffect { public JaggedPoppetDealsDamageEffect() { super(Outcome.Discard); //staticText = "it deals that much damage to each creature that player controls"; } - + public JaggedPoppetDealsDamageEffect(final JaggedPoppetDealsDamageEffect effect) { super(effect); } @@ -105,11 +97,11 @@ class JaggedPoppetDealsDamageEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { //According to the Balefire Dragon code, This statement gets the player that was dealt the combat damage Player player = game.getPlayer(targetPointer.getFirst(game, source)); - if (player != null) { + if (player != null) { //Call the getValue method of the Effect class to retrieve the amount of damage int amount = (Integer) getValue("damage"); - - if(amount > 0){ + + if (amount > 0) { //Call the player discard function discarding cards equal to damage player.discard(amount, false, source, game); } @@ -120,43 +112,42 @@ class JaggedPoppetDealsDamageEffect extends OneShotEffect { @Override public JaggedPoppetDealsDamageEffect copy() { - return new JaggedPoppetDealsDamageEffect(this); + return new JaggedPoppetDealsDamageEffect(this); } } - class JaggedPoppetDealtDamageEffect extends OneShotEffect { public JaggedPoppetDealtDamageEffect() { super(Outcome.Discard); staticText = "discard that many cards"; } - + public JaggedPoppetDealtDamageEffect(final JaggedPoppetDealtDamageEffect effect) { super(effect); } - + @Override public boolean apply(Game game, Ability source) { - + //According to the Firedrinker Satyr code, This statement gets the player that controls Jagged Poppet Player player = game.getPlayer(source.getControllerId()); - if (player != null) { + if (player != null) { //Call the getValue method of the Effect class to retrieve the amount of damage int amount = (Integer) getValue("damage"); - - if(amount > 0){ + + if (amount > 0) { //Call the player discard function discarding cards equal to damage player.discard(amount, false, source, game); } return true; } return false; - + } @Override public JaggedPoppetDealtDamageEffect copy() { return new JaggedPoppetDealtDamageEffect(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/r/RhysticCave.java b/Mage.Sets/src/mage/cards/r/RhysticCave.java index 88362d5905c..6ce08e56515 100644 --- a/Mage.Sets/src/mage/cards/r/RhysticCave.java +++ b/Mage.Sets/src/mage/cards/r/RhysticCave.java @@ -30,26 +30,21 @@ package mage.cards.r; import java.util.UUID; import mage.MageObject; import mage.Mana; -import mage.ObjectColor; import mage.abilities.Ability; -import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.Cost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.Effect; -import mage.abilities.effects.common.ChooseColorEffect; -import mage.abilities.effects.common.DoUnlessAnyPlayerPaysEffect; +import mage.abilities.effects.common.BasicManaEffect; +import mage.abilities.effects.common.DoUnlessAnyPlayerPaysManaEffect; import mage.abilities.effects.common.ManaEffect; -import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.mana.ActivatedManaAbilityImpl; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.choices.ChoiceColor; import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; import mage.constants.Zone; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.players.Player; /** @@ -61,16 +56,8 @@ public class RhysticCave extends CardImpl { public RhysticCave(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); - // {tap}: Choose a color. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, - new ChooseColorEffect(Outcome.PutManaInPool), - new TapSourceCost()); - - // Add one mana of that color to your mana pool unless any player pays {1}. Activate this ability only any time you could cast an instant. - ability.addEffect(new DoUnlessAnyPlayerPaysEffect(new RhysticCaveManaEffect(),new GenericManaCost(1))); - - this.addAbility(ability); - + // {T}: Choose a color. Add one mana of that color to your mana pool unless any player pays {1}. Activate this ability only any time you could cast an instant. + this.addAbility(new RhysticCaveManaAbility()); } public RhysticCave(final RhysticCave card) { @@ -81,69 +68,105 @@ public class RhysticCave extends CardImpl { public RhysticCave copy() { return new RhysticCave(this); } - - - class RhysticCaveManaEffect extends ManaEffect { - - private final Mana chosenMana; - - public RhysticCaveManaEffect() { - super(); - chosenMana = new Mana(); - this.staticText = "Add one mana of that color to your mana pool "; - } - - public RhysticCaveManaEffect(final RhysticCaveManaEffect effect) { - super(effect); - this.chosenMana = effect.chosenMana.copy(); - } - - @Override - public Mana getMana(Game game, Ability source) { - return null; - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - MageObject mageObject = game.getPermanentOrLKIBattlefield(source.getSourceId()); //get obj reference to Rhystic Cave - if (controller != null) { - if (mageObject != null) { - ObjectColor choice = (ObjectColor) game.getState().getValue(mageObject.getId()+"_color"); - if (choice!= null) { - String color = choice.toString(); - switch (color) { - case "R": - chosenMana.setRed(1); - break; - case "U": - chosenMana.setBlue(1); - break; - case "W": - chosenMana.setWhite(1); - break; - case "B": - chosenMana.setBlack(1); - break; - case "G": - chosenMana.setGreen(1); - break; - } - } - checkToFirePossibleEvents(chosenMana, game, source); - controller.getManaPool().addMana(chosenMana, game, source); - return true; - } - - } - - return false; - } - - @Override - public Effect copy() { - return new RhysticCaveManaEffect(this); - } - } - +} + +class RhysticCaveManaAbility extends ActivatedManaAbilityImpl { + + public RhysticCaveManaAbility() { + super(Zone.BATTLEFIELD, new DoUnlessAnyPlayerPaysManaEffect(new RhysticCaveManaEffect(), new GenericManaCost(1), "Pay {1} to prevent mana adding from {this}."), new TapSourceCost()); + this.netMana.add(new Mana(0, 0, 0, 0, 0, 0, 1, 0)); + this.setUndoPossible(false); + } + + public RhysticCaveManaAbility(Zone zone, Mana mana, Cost cost) { + super(zone, new BasicManaEffect(mana), cost); + + } + + public RhysticCaveManaAbility(final RhysticCaveManaAbility ability) { + super(ability); + } + + @Override + public boolean canActivate(UUID playerId, Game game) { + Player player = game.getPlayer(playerId); + if (player != null && !player.isInPayManaMode()) { + return super.canActivate(playerId, game); + } + return false; + } + + @Override + public RhysticCaveManaAbility copy() { + return new RhysticCaveManaAbility(this); + } + + @Override + public String getRule() { + return super.getRule() + " Activate this ability only any time you could cast an instant."; + } +} + +class RhysticCaveManaEffect extends ManaEffect { + + private final Mana chosenMana; + + public RhysticCaveManaEffect() { + super(); + chosenMana = new Mana(); + this.staticText = "Choose a color. Add one mana of that color to your mana pool "; + } + + public RhysticCaveManaEffect(final RhysticCaveManaEffect effect) { + super(effect); + this.chosenMana = effect.chosenMana.copy(); + } + + @Override + public Mana getMana(Game game, Ability source) { + return null; + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject mageObject = game.getPermanentOrLKIBattlefield(source.getSourceId()); //get obj reference to Rhystic Cave + if (controller != null) { + if (mageObject != null) { + ChoiceColor choice = new ChoiceColor(true); + controller.choose(outcome, choice, game); + if (choice.getColor() != null) { + String color = choice.getColor().toString(); + switch (color) { + case "R": + chosenMana.setRed(1); + break; + case "U": + chosenMana.setBlue(1); + break; + case "W": + chosenMana.setWhite(1); + break; + case "B": + chosenMana.setBlack(1); + break; + case "G": + chosenMana.setGreen(1); + break; + } + } + checkToFirePossibleEvents(chosenMana, game, source); + controller.getManaPool().addMana(chosenMana, game, source); + return true; + } + + } + + return false; + } + + @Override + public Effect copy() { + return new RhysticCaveManaEffect(this); + } } diff --git a/Mage.Sets/src/mage/cards/t/TalonOfPain.java b/Mage.Sets/src/mage/cards/t/TalonOfPain.java index 6cdcfb3dc63..f9ddad33770 100644 --- a/Mage.Sets/src/mage/cards/t/TalonOfPain.java +++ b/Mage.Sets/src/mage/cards/t/TalonOfPain.java @@ -27,23 +27,23 @@ */ package mage.cards.t; -import java.util.Objects; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.costs.common.RemoveVariableCountersSourceCost; +import mage.abilities.costs.Cost; +import mage.abilities.costs.VariableCostImpl; +import mage.abilities.costs.common.RemoveCountersSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.dynamicvalue.common.ManacostVariableValue; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.Zone; +import mage.counters.Counter; import mage.counters.CounterType; import mage.game.Game; import mage.game.events.GameEvent; @@ -59,23 +59,21 @@ public class TalonOfPain extends CardImpl { public TalonOfPain(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); - + /* - * Whenever a source you control other than Talon of Pain deals damage to an opponent, + * Whenever a source you control other than Talon of Pain deals damage to an opponent, * put a charge counter on Talon of Pain. */ this.addAbility(new TalonOfPainTriggeredAbility()); - - - // {X}, {tap}, Remove X charge counters from Talon of Pain: Talon of Pain deals X damage to target creature or player. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new ManacostVariableValue()) , new ManaCostsImpl("{X}")); + + // {X}, {T}, Remove X charge counters from Talon of Pain: Talon of Pain deals X damage to target creature or player. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new ManacostVariableValue()), new ManaCostsImpl("{X}")); ability.addCost(new TapSourceCost()); - ability.addCost(new RemoveVariableCountersSourceCost(CounterType.CHARGE.createInstance())); + ability.addCost(new TalonOfPainRemoveVariableCountersSourceCost(CounterType.CHARGE.createInstance())); ability.addTarget(new TargetCreatureOrPlayer()); this.addAbility(ability); - - + } public TalonOfPain(final TalonOfPain card) { @@ -86,7 +84,7 @@ public class TalonOfPain extends CardImpl { public TalonOfPain copy() { return new TalonOfPain(this); } - + private class TalonOfPainTriggeredAbility extends TriggeredAbilityImpl { public TalonOfPainTriggeredAbility() { @@ -111,13 +109,15 @@ public class TalonOfPain extends CardImpl { public boolean checkTrigger(GameEvent event, Game game) { // to another player Player controller = game.getPlayer(this.getControllerId()); - if(controller==null){return false;} - if(controller.hasOpponent(event.getTargetId(),game)){ + if (controller == null) { + return false; + } + if (controller.hasOpponent(event.getTargetId(), game)) { // a source you control other than Talon of Pain UUID sourceControllerId = game.getControllerId(event.getSourceId()); - if (sourceControllerId != null - && sourceControllerId.equals(this.getControllerId()) - && this.getSourceId() != event.getSourceId() ) { + if (sourceControllerId != null + && sourceControllerId.equals(this.getControllerId()) + && this.getSourceId() != event.getSourceId()) { // return true so the effect will fire and a charge counter will be added return true; } @@ -131,3 +131,69 @@ public class TalonOfPain extends CardImpl { } } } + +class TalonOfPainRemoveVariableCountersSourceCost extends VariableCostImpl { + + protected int minimalCountersToPay = 0; + private String counterName; + + public TalonOfPainRemoveVariableCountersSourceCost(Counter counter) { + this(counter, 0); + } + + public TalonOfPainRemoveVariableCountersSourceCost(Counter counter, String text) { + this(counter, 0, text); + } + + public TalonOfPainRemoveVariableCountersSourceCost(Counter counter, int minimalCountersToPay) { + this(counter, minimalCountersToPay, ""); + } + + public TalonOfPainRemoveVariableCountersSourceCost(Counter counter, int minimalCountersToPay, String text) { + super(counter.getName() + " counters to remove"); + this.minimalCountersToPay = minimalCountersToPay; + this.counterName = counter.getName(); + if (text == null || text.isEmpty()) { + this.text = "Remove X " + counterName + " counters from {this}"; + } else { + this.text = text; + } + } + + public TalonOfPainRemoveVariableCountersSourceCost(final TalonOfPainRemoveVariableCountersSourceCost cost) { + super(cost); + this.minimalCountersToPay = cost.minimalCountersToPay; + this.counterName = cost.counterName; + } + + @Override + public TalonOfPainRemoveVariableCountersSourceCost copy() { + return new TalonOfPainRemoveVariableCountersSourceCost(this); + } + + @Override + public Cost getFixedCostsFromAnnouncedValue(int xValue) { + return new RemoveCountersSourceCost(new Counter(counterName, xValue)); + } + + @Override + public int getMinValue(Ability source, Game game) { + return minimalCountersToPay; + } + + @Override + public int getMaxValue(Ability source, Game game) { + int maxValue = 0; + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + maxValue = permanent.getCounters(game).getCount(counterName); + } + return maxValue; + } + + @Override + public int announceXValue(Ability source, Game game) { + return source.getManaCostsToPay().getX(); + } + +} diff --git a/Mage.Sets/src/mage/cards/w/WitchEngine.java b/Mage.Sets/src/mage/cards/w/WitchEngine.java index 253c2e544f9..51f61adebe2 100644 --- a/Mage.Sets/src/mage/cards/w/WitchEngine.java +++ b/Mage.Sets/src/mage/cards/w/WitchEngine.java @@ -64,7 +64,7 @@ public class WitchEngine extends CardImpl { // Swampwalk this.addAbility(new SwampwalkAbility()); - // {tap}: Add {B}{B}{B}{B} to your mana pool. Target opponent gains control of Witch Engine. (Activate this ability only any time you could cast an instant.) + // {T}: Add {B}{B}{B}{B} to your mana pool. Target opponent gains control of Witch Engine. (Activate this ability only any time you could cast an instant.) Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BasicManaEffect(Mana.BlackMana(4)), new TapSourceCost()); ability.addEffect(new WitchEngineEffect()); ability.addTarget(new TargetOpponent()); diff --git a/Mage/src/main/java/mage/abilities/effects/common/DoUnlessAnyPlayerPaysManaEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DoUnlessAnyPlayerPaysManaEffect.java new file mode 100644 index 00000000000..29177424250 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/DoUnlessAnyPlayerPaysManaEffect.java @@ -0,0 +1,94 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.abilities.effects.common; + +import java.util.UUID; +import mage.MageObject; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.costs.Cost; +import mage.constants.Outcome; +import mage.game.Game; +import mage.players.Player; +import mage.util.CardUtil; + +/** + * + * @author LevelX2 + */ +public class DoUnlessAnyPlayerPaysManaEffect extends ManaEffect { + + private final ManaEffect manaEffect; + private final Cost cost; + private final String chooseUseText; + + public DoUnlessAnyPlayerPaysManaEffect(ManaEffect effect, Cost cost, String chooseUseText) { + this.manaEffect = effect; + this.cost = cost; + this.chooseUseText = chooseUseText; + } + + public DoUnlessAnyPlayerPaysManaEffect(final DoUnlessAnyPlayerPaysManaEffect effect) { + super(effect); + this.manaEffect = (ManaEffect) effect.manaEffect.copy(); + this.cost = effect.cost.copy(); + this.chooseUseText = effect.chooseUseText; + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = game.getObject(source.getSourceId()); + if (controller != null && sourceObject != null) { + String message = CardUtil.replaceSourceName(chooseUseText, sourceObject.getName()); + boolean result = true; + boolean doEffect = true; + // check if any player is willing to pay + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null && cost.canPay(source, source.getSourceId(), player.getId(), game) && player.chooseUse(Outcome.Detriment, message, source, game)) { + cost.clearPaid(); + if (cost.pay(source, game, source.getSourceId(), player.getId(), false, null)) { + if (!game.isSimulation()) { + game.informPlayers(player.getLogName() + " pays the cost to prevent the effect"); + } + doEffect = false; + } + } + } + // do the effects if nobody paid + if (doEffect) { + return manaEffect.apply(game, source); + } + return result; + } + return false; + } + + protected Player getPayingPlayer(Game game, Ability source) { + return game.getPlayer(source.getControllerId()); + } + + @Override + public String getText(Mode mode) { + if (!staticText.isEmpty()) { + return staticText; + } + return manaEffect.getText(mode) + " unless any player pays " + cost.getText(); + } + + @Override + public Mana getMana(Game game, Ability source) { + return manaEffect.getMana(game, source); + } + + @Override + public ManaEffect copy() { + return new DoUnlessAnyPlayerPaysManaEffect(this); + } + +}