From 650f184ee682ffd0d8122dadbaa5cd60720d41d8 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Mon, 11 Sep 2017 16:26:30 -0400 Subject: [PATCH 01/35] Begin Mairsil fix --- .../src/mage/cards/m/MairsilThePretender.java | 288 +++++++++--------- .../mage/abilities/ActivatedAbilityImpl.java | 62 ++++ .../ActivateIfConditionActivatedAbility.java | 32 +- .../LimitedTimesPerTurnActivatedAbility.java | 62 ---- 4 files changed, 203 insertions(+), 241 deletions(-) diff --git a/Mage.Sets/src/mage/cards/m/MairsilThePretender.java b/Mage.Sets/src/mage/cards/m/MairsilThePretender.java index 4e4b5cb0505..ca79b17b9d7 100644 --- a/Mage.Sets/src/mage/cards/m/MairsilThePretender.java +++ b/Mage.Sets/src/mage/cards/m/MairsilThePretender.java @@ -27,21 +27,14 @@ */ package mage.cards.m; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; -import java.util.Set; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.ActivatedAbility; +import mage.abilities.ActivatedAbilityImpl; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; -import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; import mage.cards.CardImpl; @@ -54,7 +47,6 @@ import mage.constants.Outcome; import mage.constants.SubLayer; import mage.constants.SuperType; import mage.constants.TargetController; -import mage.constants.WatcherScope; import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.FilterCard; @@ -63,15 +55,11 @@ import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.other.CounterCardPredicate; import mage.filter.predicate.other.OwnerPredicate; import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; -import mage.game.stack.StackAbility; import mage.players.Player; import mage.target.Target; import mage.target.common.TargetCardInHand; import mage.target.common.TargetCardInYourGraveyard; -import mage.watchers.Watcher; /** * @@ -93,8 +81,9 @@ public class MairsilThePretender extends CardImpl { // Mairsil, the Pretender has all activated abilities of all cards you own in exile with cage counters on them. You may activate each of those abilities only once each turn. Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new MairsilThePretenderGainAbilitiesEffect()); - ability.addEffect(new MairsilThePretenderRuleModifyingEffect()); - this.addAbility(ability, new MairsilThePretenderWatcher()); + this.addAbility(ability); +// ability.addEffect(new MairsilThePretenderRuleModifyingEffect()); +// this.addAbility(ability, new MairsilThePretenderWatcher()); } public MairsilThePretender(final MairsilThePretender card) { @@ -182,11 +171,8 @@ class MairsilThePretenderGainAbilitiesEffect extends ContinuousEffectImpl { if (filter.match(card, game)) { for (Ability ability : card.getAbilities()) { if (ability instanceof ActivatedAbility) { - UUID originaId = ability.getId(); - ActivatedAbility copyAbility = (ActivatedAbility) ability.copy(); - Effect effect = new DoNothingEffect(); - effect.setValue("key", originaId); - copyAbility.addEffect(effect); + ActivatedAbilityImpl copyAbility = (ActivatedAbilityImpl) ability.copy(); + copyAbility.setMaxActivationsPerTurn(1); perm.addAbility(copyAbility, card.getId(), game); } } @@ -203,134 +189,134 @@ class MairsilThePretenderGainAbilitiesEffect extends ContinuousEffectImpl { } } -class MairsilThePretenderWatcher extends Watcher { - - public final Map> activatedThisTurnAbilities = new HashMap<>(); - - public MairsilThePretenderWatcher() { - super(MairsilThePretenderWatcher.class.getSimpleName(), WatcherScope.GAME); - } - - public MairsilThePretenderWatcher(final MairsilThePretenderWatcher watcher) { - super(watcher); - for (Entry> entry : watcher.activatedThisTurnAbilities.entrySet()) { - activatedThisTurnAbilities.put(entry.getKey(), entry.getValue()); - } - } - - @Override - public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.ZONE_CHANGE && event instanceof ZoneChangeEvent) { - ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - if (zEvent.getFromZone() == Zone.BATTLEFIELD) { - Permanent permanent = zEvent.getTarget(); - if (permanent != null) { - this.activatedThisTurnAbilities.remove(permanent.getId()); - } - } - } - if (event.getType() == GameEvent.EventType.ACTIVATED_ABILITY) { - Set permAbilities; - if (activatedThisTurnAbilities.keySet().contains(event.getSourceId())) { - permAbilities = activatedThisTurnAbilities.get(event.getSourceId()); - } else { - permAbilities = new HashSet<>(); - } - StackAbility ability = (StackAbility) game.getStack().getStackObject(event.getSourceId()); - if (ability != null && ability.getStackAbility().isActivated()) { - for (Effect effect : ability.getAllEffects()) { - if (effect instanceof DoNothingEffect) { - permAbilities.add((UUID) effect.getValue("key")); - this.activatedThisTurnAbilities.put(event.getSourceId(), permAbilities); - } - } - } - } - } - - @Override - public void reset() { - activatedThisTurnAbilities.clear(); - } - - public Map> getActivatedThisTurnAbilities() { - return this.activatedThisTurnAbilities; - } - - @Override - public MairsilThePretenderWatcher copy() { - return new MairsilThePretenderWatcher(this); - } - -} - -class MairsilThePretenderRuleModifyingEffect extends ContinuousRuleModifyingEffectImpl { - - public MairsilThePretenderRuleModifyingEffect() { - super(Duration.WhileOnBattlefield, Outcome.Detriment); - } - - public MairsilThePretenderRuleModifyingEffect(final MairsilThePretenderRuleModifyingEffect effect) { - super(effect); - } - - @Override - public MairsilThePretenderRuleModifyingEffect copy() { - return new MairsilThePretenderRuleModifyingEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } - - @Override - public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ACTIVATE_ABILITY; - } - - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - Optional ability = game.getAbility(event.getTargetId(), event.getSourceId()); - MairsilThePretenderWatcher watcher = (MairsilThePretenderWatcher) game.getState().getWatchers().get(MairsilThePretenderWatcher.class.getSimpleName()); - if (watcher != null && ability != null && ability.isPresent()) { - for (Effect effect : ability.get().getAllEffects()) { - if (effect instanceof DoNothingEffect) { - UUID originalID = (UUID) effect.getValue("key"); - if (watcher.getActivatedThisTurnAbilities().keySet().contains(event.getSourceId())) { - if (watcher.getActivatedThisTurnAbilities().get(event.getSourceId()).contains(originalID)) { - return true; - } - } - } - } - } - return false; - } - - @Override - public String getInfoMessage(Ability source, GameEvent event, Game game) { - return "This ability can only be activated once each turn."; - } -} - -class DoNothingEffect extends OneShotEffect { - - DoNothingEffect() { - super(Outcome.Neutral); - } - - DoNothingEffect(final DoNothingEffect effect) { - super(effect); - } - - @Override - public DoNothingEffect copy() { - return new DoNothingEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } -} +//class MairsilThePretenderWatcher extends Watcher { +// +// public final Map> activatedThisTurnAbilities = new HashMap<>(); +// +// public MairsilThePretenderWatcher() { +// super(MairsilThePretenderWatcher.class.getSimpleName(), WatcherScope.GAME); +// } +// +// public MairsilThePretenderWatcher(final MairsilThePretenderWatcher watcher) { +// super(watcher); +// for (Entry> entry : watcher.activatedThisTurnAbilities.entrySet()) { +// activatedThisTurnAbilities.put(entry.getKey(), entry.getValue()); +// } +// } +// +// @Override +// public void watch(GameEvent event, Game game) { +// if (event.getType() == GameEvent.EventType.ZONE_CHANGE && event instanceof ZoneChangeEvent) { +// ZoneChangeEvent zEvent = (ZoneChangeEvent) event; +// if (zEvent.getFromZone() == Zone.BATTLEFIELD) { +// Permanent permanent = zEvent.getTarget(); +// if (permanent != null) { +// this.activatedThisTurnAbilities.remove(permanent.getId()); +// } +// } +// } +// if (event.getType() == GameEvent.EventType.ACTIVATED_ABILITY) { +// Set permAbilities; +// if (activatedThisTurnAbilities.keySet().contains(event.getSourceId())) { +// permAbilities = activatedThisTurnAbilities.get(event.getSourceId()); +// } else { +// permAbilities = new HashSet<>(); +// } +// StackAbility ability = (StackAbility) game.getStack().getStackObject(event.getSourceId()); +// if (ability != null && ability.getStackAbility().isActivated()) { +// for (Effect effect : ability.getAllEffects()) { +// if (effect instanceof DoNothingEffect) { +// permAbilities.add((UUID) effect.getValue("key")); +// this.activatedThisTurnAbilities.put(event.getSourceId(), permAbilities); +// } +// } +// } +// } +// } +// +// @Override +// public void reset() { +// activatedThisTurnAbilities.clear(); +// } +// +// public Map> getActivatedThisTurnAbilities() { +// return this.activatedThisTurnAbilities; +// } +// +// @Override +// public MairsilThePretenderWatcher copy() { +// return new MairsilThePretenderWatcher(this); +// } +// +//} +// +//class MairsilThePretenderRuleModifyingEffect extends ContinuousRuleModifyingEffectImpl { +// +// public MairsilThePretenderRuleModifyingEffect() { +// super(Duration.WhileOnBattlefield, Outcome.Detriment); +// } +// +// public MairsilThePretenderRuleModifyingEffect(final MairsilThePretenderRuleModifyingEffect effect) { +// super(effect); +// } +// +// @Override +// public MairsilThePretenderRuleModifyingEffect copy() { +// return new MairsilThePretenderRuleModifyingEffect(this); +// } +// +// @Override +// public boolean apply(Game game, Ability source) { +// return true; +// } +// +// @Override +// public boolean checksEventType(GameEvent event, Game game) { +// return event.getType() == GameEvent.EventType.ACTIVATE_ABILITY; +// } +// +// @Override +// public boolean applies(GameEvent event, Ability source, Game game) { +// Optional ability = game.getAbility(event.getTargetId(), event.getSourceId()); +// MairsilThePretenderWatcher watcher = (MairsilThePretenderWatcher) game.getState().getWatchers().get(MairsilThePretenderWatcher.class.getSimpleName()); +// if (watcher != null && ability != null && ability.isPresent()) { +// for (Effect effect : ability.get().getAllEffects()) { +// if (effect instanceof DoNothingEffect) { +// UUID originalID = (UUID) effect.getValue("key"); +// if (watcher.getActivatedThisTurnAbilities().keySet().contains(event.getSourceId())) { +// if (watcher.getActivatedThisTurnAbilities().get(event.getSourceId()).contains(originalID)) { +// return true; +// } +// } +// } +// } +// } +// return false; +// } +// +// @Override +// public String getInfoMessage(Ability source, GameEvent event, Game game) { +// return "This ability can only be activated once each turn."; +// } +//} +// +//class DoNothingEffect extends OneShotEffect { +// +// DoNothingEffect() { +// super(Outcome.Neutral); +// } +// +// DoNothingEffect(final DoNothingEffect effect) { +// super(effect); +// } +// +// @Override +// public DoNothingEffect copy() { +// return new DoNothingEffect(this); +// } +// +// @Override +// public boolean apply(Game game, Ability source) { +// return true; +// } +//} diff --git a/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java b/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java index 5021a83896f..0bbca8ccfd7 100644 --- a/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java @@ -29,6 +29,7 @@ package mage.abilities; import java.util.UUID; import mage.MageObject; +import mage.abilities.condition.Condition; import mage.abilities.costs.Cost; import mage.abilities.costs.Costs; import mage.abilities.costs.mana.ManaCosts; @@ -45,6 +46,7 @@ import mage.constants.Zone; import mage.game.Game; import mage.game.command.Emblem; import mage.game.permanent.Permanent; +import mage.util.CardUtil; /** * @@ -52,6 +54,19 @@ import mage.game.permanent.Permanent; */ public abstract class ActivatedAbilityImpl extends AbilityImpl implements ActivatedAbility { + static class ActivationInfo { + + public int turnNum; + public int activationCounter; + + public ActivationInfo(int turnNum, int activationCounter) { + this.turnNum = turnNum; + this.activationCounter = activationCounter; + } + } + + protected int maxActivationsPerTurn = Integer.MAX_VALUE; + protected Condition condition; protected TimingRule timing = TimingRule.INSTANT; protected TargetController mayActivate = TargetController.YOU; protected UUID activatorId; @@ -68,6 +83,8 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa mayActivate = ability.mayActivate; activatorId = ability.activatorId; checkPlayableMode = ability.checkPlayableMode; + maxActivationsPerTurn = ability.maxActivationsPerTurn; + condition = ability.condition; } public ActivatedAbilityImpl(Zone zone) { @@ -161,6 +178,9 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa @Override public boolean canActivate(UUID playerId, Game game) { //20091005 - 602.2 + if (!(hasMoreActivationsThisTurn(game) && (condition == null || condition.apply(game, this)))) { + return false; + } switch (mayActivate) { case ANY: break; @@ -255,4 +275,46 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa return checkPlayableMode; } + private boolean hasMoreActivationsThisTurn(Game game) { + ActivationInfo activationInfo = getActivationInfo(game); + return activationInfo == null || activationInfo.turnNum != game.getTurnNum() || activationInfo.activationCounter < maxActivationsPerTurn; + } + + @Override + public boolean activate(Game game, boolean noMana) { + if (hasMoreActivationsThisTurn(game)) { + if (super.activate(game, noMana)) { + ActivationInfo activationInfo = getActivationInfo(game); + if (activationInfo == null) { + activationInfo = new ActivationInfo(game.getTurnNum(), 1); + } else if (activationInfo.turnNum != game.getTurnNum()) { + activationInfo.turnNum = game.getTurnNum(); + activationInfo.activationCounter = 1; + } else { + activationInfo.activationCounter++; + } + setActivationInfo(activationInfo, game); + return true; + } + } + return false; + } + + public void setMaxActivationsPerTurn(int maxActivationsPerTurn) { + this.maxActivationsPerTurn = maxActivationsPerTurn; + } + + private ActivationInfo getActivationInfo(Game game) { + Integer turnNum = (Integer) game.getState().getValue(CardUtil.getCardZoneString("activationsTurn", sourceId, game)); + Integer activationCount = (Integer) game.getState().getValue(CardUtil.getCardZoneString("activationsCount", sourceId, game)); + if (turnNum == null || activationCount == null) { + return null; + } + return new ActivationInfo(turnNum, activationCount); + } + + private void setActivationInfo(ActivationInfo activationInfo, Game game) { + game.getState().setValue(CardUtil.getCardZoneString("activationsTurn", sourceId, game), activationInfo.turnNum); + game.getState().setValue(CardUtil.getCardZoneString("activationsCount", sourceId, game), activationInfo.activationCounter); + } } diff --git a/Mage/src/main/java/mage/abilities/common/ActivateIfConditionActivatedAbility.java b/Mage/src/main/java/mage/abilities/common/ActivateIfConditionActivatedAbility.java index 1e0753ce927..c44fe6cb163 100644 --- a/Mage/src/main/java/mage/abilities/common/ActivateIfConditionActivatedAbility.java +++ b/Mage/src/main/java/mage/abilities/common/ActivateIfConditionActivatedAbility.java @@ -25,10 +25,8 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.abilities.common; -import java.util.UUID; import mage.abilities.ActivatedAbilityImpl; import mage.abilities.condition.Condition; import mage.abilities.condition.InvertCondition; @@ -43,8 +41,6 @@ import mage.game.Game; */ public class ActivateIfConditionActivatedAbility extends ActivatedAbilityImpl { - private final Condition condition; - public ActivateIfConditionActivatedAbility(Zone zone, Effect effect, Cost cost, Condition condition) { super(zone, effect, cost); this.condition = condition; @@ -52,31 +48,11 @@ public class ActivateIfConditionActivatedAbility extends ActivatedAbilityImpl { public ActivateIfConditionActivatedAbility(ActivateIfConditionActivatedAbility ability) { super(ability); - this.condition = ability.condition; - } - - @Override - public boolean canActivate(UUID playerId, Game game) { - if (condition.apply(game, this)) { - return super.canActivate(playerId, game); - } - return false; - } - - @Override - public boolean activate(Game game, boolean noMana) { - if (canActivate(this.controllerId, game)) { - return super.activate(game, noMana); - } - return false; } @Override public boolean resolve(Game game) { - if (super.resolve(game)) { - return true; - } - return false; + return super.resolve(game); } @Override @@ -88,15 +64,15 @@ public class ActivateIfConditionActivatedAbility extends ActivatedAbilityImpl { sb.append(" Activate this ability only "); } if (condition.toString() != null) { - if (!condition.toString().startsWith("during") && - !condition.toString().startsWith("before")) { + if (!condition.toString().startsWith("during") + && !condition.toString().startsWith("before")) { sb.append("if "); } sb.append(condition.toString()).append('.'); } else { sb.append(" [Condition toString() == null] "); } - return sb.toString() ; + return sb.toString(); } @Override diff --git a/Mage/src/main/java/mage/abilities/common/LimitedTimesPerTurnActivatedAbility.java b/Mage/src/main/java/mage/abilities/common/LimitedTimesPerTurnActivatedAbility.java index 4e42a1678c3..3358d9dd9f7 100644 --- a/Mage/src/main/java/mage/abilities/common/LimitedTimesPerTurnActivatedAbility.java +++ b/Mage/src/main/java/mage/abilities/common/LimitedTimesPerTurnActivatedAbility.java @@ -36,28 +36,12 @@ import mage.constants.Zone; import mage.game.Game; import mage.util.CardUtil; -import java.util.UUID; - /** * * @author BetaSteward_at_googlemail.com */ public class LimitedTimesPerTurnActivatedAbility extends ActivatedAbilityImpl { - static class ActivationInfo { - - public int turnNum; - public int activationCounter; - - public ActivationInfo(int turnNum, int activationCounter) { - this.turnNum = turnNum; - this.activationCounter = activationCounter; - } - } - - private int maxActivationsPerTurn; - private Condition condition; - public LimitedTimesPerTurnActivatedAbility(Zone zone, Effect effect, Cost cost) { this(zone, effect, cost, 1); } @@ -78,38 +62,6 @@ public class LimitedTimesPerTurnActivatedAbility extends ActivatedAbilityImpl { this.condition = ability.condition; } - @Override - public boolean canActivate(UUID playerId, Game game) { - return super.canActivate(playerId, game) - && hasMoreActivationsThisTurn(game) - && (condition == null || condition.apply(game, this)); - } - - private boolean hasMoreActivationsThisTurn(Game game) { - ActivationInfo activationInfo = getActivationInfo(game); - return activationInfo == null || activationInfo.turnNum != game.getTurnNum() || activationInfo.activationCounter < maxActivationsPerTurn; - } - - @Override - public boolean activate(Game game, boolean noMana) { - if (hasMoreActivationsThisTurn(game)) { - if (super.activate(game, noMana)) { - ActivationInfo activationInfo = getActivationInfo(game); - if (activationInfo == null) { - activationInfo = new ActivationInfo(game.getTurnNum(), 1); - } else if (activationInfo.turnNum != game.getTurnNum()) { - activationInfo.turnNum = game.getTurnNum(); - activationInfo.activationCounter = 1; - } else { - activationInfo.activationCounter++; - } - setActivationInfo(activationInfo, game); - return true; - } - } - return false; - } - @Override public boolean resolve(Game game) { return super.resolve(game); @@ -142,18 +94,4 @@ public class LimitedTimesPerTurnActivatedAbility extends ActivatedAbilityImpl { public LimitedTimesPerTurnActivatedAbility copy() { return new LimitedTimesPerTurnActivatedAbility(this); } - - private ActivationInfo getActivationInfo(Game game) { - Integer turnNum = (Integer) game.getState().getValue(CardUtil.getCardZoneString("activationsTurn", sourceId, game)); - Integer activationCount = (Integer) game.getState().getValue(CardUtil.getCardZoneString("activationsCount", sourceId, game)); - if (turnNum == null || activationCount == null) { - return null; - } - return new ActivationInfo(turnNum, activationCount); - } - - private void setActivationInfo(ActivationInfo activationInfo, Game game) { - game.getState().setValue(CardUtil.getCardZoneString("activationsTurn", sourceId, game), activationInfo.turnNum); - game.getState().setValue(CardUtil.getCardZoneString("activationsCount", sourceId, game), activationInfo.activationCounter); - } } From 9b25dd0e393bfb47a3cf8ba19883b62f40677ec2 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Tue, 12 Sep 2017 09:33:12 -0400 Subject: [PATCH 02/35] revamped how conditional and limited-use activated abilities are implemented --- .../mage/cards/q/QuicksilverElemental.java | 45 ++++++++++++-- .../mage/abilities/ActivatedAbilityImpl.java | 10 +-- .../ConditionalActivatedAbility.java | 10 --- .../mana/ActivateIfConditionManaAbility.java | 16 +---- .../mana/ActivateOncePerTurnManaAbility.java | 62 ++----------------- .../mana/ActivatedManaAbilityImpl.java | 5 +- 6 files changed, 55 insertions(+), 93 deletions(-) diff --git a/Mage.Sets/src/mage/cards/q/QuicksilverElemental.java b/Mage.Sets/src/mage/cards/q/QuicksilverElemental.java index 5c5cefc1f9e..293843fd05d 100644 --- a/Mage.Sets/src/mage/cards/q/QuicksilverElemental.java +++ b/Mage.Sets/src/mage/cards/q/QuicksilverElemental.java @@ -37,6 +37,8 @@ import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.AsThoughManaEffect; import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.AsThoughEffectType; @@ -89,14 +91,14 @@ public class QuicksilverElemental extends CardImpl { } } -class QuicksilverElementalEffect extends ContinuousEffectImpl { +class QuicksilverElementalEffect extends OneShotEffect { - public QuicksilverElementalEffect() { - super(Duration.EndOfTurn, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); + QuicksilverElementalEffect() { + super(Outcome.Benefit); staticText = "{this} gains all activated abilities of target creature until end of turn"; } - public QuicksilverElementalEffect(final QuicksilverElementalEffect effect) { + QuicksilverElementalEffect(final QuicksilverElementalEffect effect) { super(effect); } @@ -112,13 +114,46 @@ class QuicksilverElementalEffect extends ContinuousEffectImpl { if (permanent != null && creature != null) { for (ActivatedAbility ability : creature.getAbilities().getActivatedAbilities(Zone.BATTLEFIELD)) { - permanent.addAbility(ability, source.getSourceId(), game); + Ability newAbility = ability.copy(); + newAbility.newOriginalId(); + game.addEffect(new GainAbilitySourceEffect(newAbility, Duration.EndOfTurn), source); } + return true; } return false; } } +//class QuicksilverElementalEffect extends ContinuousEffectImpl { +// +// public QuicksilverElementalEffect() { +// super(Duration.EndOfTurn, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); +// staticText = "{this} gains all activated abilities of target creature until end of turn"; +// } +// +// public QuicksilverElementalEffect(final QuicksilverElementalEffect effect) { +// super(effect); +// } +// +// @Override +// public QuicksilverElementalEffect copy() { +// return new QuicksilverElementalEffect(this); +// } +// +// @Override +// public boolean apply(Game game, Ability source) { +// Permanent permanent = game.getPermanent(source.getSourceId()); +// Permanent creature = game.getPermanent(source.getTargets().getFirstTarget()); +// +// if (permanent != null && creature != null) { +// for (ActivatedAbility ability : creature.getAbilities().getActivatedAbilities(Zone.BATTLEFIELD)) { +// permanent.addAbility(ability, source.getSourceId(), game); +// } +// } +// return false; +// } +//} + class QuickSilverElementalBlueManaEffect extends AsThoughEffectImpl implements AsThoughManaEffect { public QuickSilverElementalBlueManaEffect() { diff --git a/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java b/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java index 0bbca8ccfd7..32c3728ee9d 100644 --- a/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java @@ -275,7 +275,7 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa return checkPlayableMode; } - private boolean hasMoreActivationsThisTurn(Game game) { + protected boolean hasMoreActivationsThisTurn(Game game) { ActivationInfo activationInfo = getActivationInfo(game); return activationInfo == null || activationInfo.turnNum != game.getTurnNum() || activationInfo.activationCounter < maxActivationsPerTurn; } @@ -305,8 +305,8 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa } private ActivationInfo getActivationInfo(Game game) { - Integer turnNum = (Integer) game.getState().getValue(CardUtil.getCardZoneString("activationsTurn", sourceId, game)); - Integer activationCount = (Integer) game.getState().getValue(CardUtil.getCardZoneString("activationsCount", sourceId, game)); + Integer turnNum = (Integer) game.getState().getValue(CardUtil.getCardZoneString("activationsTurn" + originalId, sourceId, game)); + Integer activationCount = (Integer) game.getState().getValue(CardUtil.getCardZoneString("activationsCount" + originalId, sourceId, game)); if (turnNum == null || activationCount == null) { return null; } @@ -314,7 +314,7 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa } private void setActivationInfo(ActivationInfo activationInfo, Game game) { - game.getState().setValue(CardUtil.getCardZoneString("activationsTurn", sourceId, game), activationInfo.turnNum); - game.getState().setValue(CardUtil.getCardZoneString("activationsCount", sourceId, game), activationInfo.activationCounter); + game.getState().setValue(CardUtil.getCardZoneString("activationsTurn" + originalId, sourceId, game), activationInfo.turnNum); + game.getState().setValue(CardUtil.getCardZoneString("activationsCount" + originalId, sourceId, game), activationInfo.activationCounter); } } diff --git a/Mage/src/main/java/mage/abilities/decorator/ConditionalActivatedAbility.java b/Mage/src/main/java/mage/abilities/decorator/ConditionalActivatedAbility.java index 38339c569d8..0e159549ff2 100644 --- a/Mage/src/main/java/mage/abilities/decorator/ConditionalActivatedAbility.java +++ b/Mage/src/main/java/mage/abilities/decorator/ConditionalActivatedAbility.java @@ -4,7 +4,6 @@ */ package mage.abilities.decorator; -import java.util.UUID; import mage.abilities.ActivatedAbilityImpl; import mage.abilities.condition.Condition; import mage.abilities.costs.Cost; @@ -24,7 +23,6 @@ public class ConditionalActivatedAbility extends ActivatedAbilityImpl { private static final Effects emptyEffects = new Effects(); - private final Condition condition; private String ruleText = null; public ConditionalActivatedAbility(Zone zone, Effect effect, Cost cost, Condition condition) { @@ -64,14 +62,6 @@ public class ConditionalActivatedAbility extends ActivatedAbilityImpl { return super.getEffects(game, effectType); } - @Override - public boolean canActivate(UUID playerId, Game game) { - if (!condition.apply(game, this)) { - return false; - } - return super.canActivate(playerId, game); - } - @Override public ConditionalActivatedAbility copy() { return new ConditionalActivatedAbility(this); diff --git a/Mage/src/main/java/mage/abilities/mana/ActivateIfConditionManaAbility.java b/Mage/src/main/java/mage/abilities/mana/ActivateIfConditionManaAbility.java index f12d8e55651..d851810563c 100644 --- a/Mage/src/main/java/mage/abilities/mana/ActivateIfConditionManaAbility.java +++ b/Mage/src/main/java/mage/abilities/mana/ActivateIfConditionManaAbility.java @@ -27,7 +27,6 @@ */ package mage.abilities.mana; -import java.util.UUID; import mage.abilities.condition.Condition; import mage.abilities.costs.Cost; import mage.abilities.effects.common.AddConditionalColorlessManaEffect; @@ -37,8 +36,6 @@ import mage.game.Game; public class ActivateIfConditionManaAbility extends ActivatedManaAbilityImpl { - private final Condition condition; - public ActivateIfConditionManaAbility(Zone zone, BasicManaEffect effect, Cost cost, Condition condition) { super(zone, effect, cost); this.netMana.add(effect.getMana()); @@ -56,20 +53,9 @@ public class ActivateIfConditionManaAbility extends ActivatedManaAbilityImpl { this.condition = ability.condition; } - @Override - public boolean canActivate(UUID playerId, Game game) { - if (condition.apply(game, this)) { - return super.canActivate(playerId, game); - } - return false; - } - @Override public boolean activate(Game game, boolean noMana) { - if (canActivate(this.controllerId, game)) { - return super.activate(game, noMana); - } - return false; + return super.activate(game, noMana); } @Override diff --git a/Mage/src/main/java/mage/abilities/mana/ActivateOncePerTurnManaAbility.java b/Mage/src/main/java/mage/abilities/mana/ActivateOncePerTurnManaAbility.java index 56ec6843b09..dc5f46335a9 100644 --- a/Mage/src/main/java/mage/abilities/mana/ActivateOncePerTurnManaAbility.java +++ b/Mage/src/main/java/mage/abilities/mana/ActivateOncePerTurnManaAbility.java @@ -24,8 +24,7 @@ * 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.abilities.mana; import mage.Mana; @@ -34,9 +33,6 @@ import mage.abilities.effects.common.AddManaOfAnyColorEffect; import mage.abilities.effects.common.BasicManaEffect; import mage.constants.Zone; import mage.game.Game; -import mage.util.CardUtil; - -import java.util.UUID; /** * @@ -44,60 +40,26 @@ import java.util.UUID; */ public class ActivateOncePerTurnManaAbility extends ActivatedManaAbilityImpl { - static class ActivationInfo { - - public int turnNum; - public int activationCounter; - - public ActivationInfo(int turnNum, int activationCounter) { - this.turnNum = turnNum; - this.activationCounter = activationCounter; - } - } - public ActivateOncePerTurnManaAbility(Zone zone, BasicManaEffect effect, Cost cost) { super(zone, effect, cost); this.netMana.add(effect.getMana()); + this.maxActivationsPerTurn = 1; } public ActivateOncePerTurnManaAbility(Zone zone, AddManaOfAnyColorEffect effect, Cost cost) { super(zone, effect, cost); - this.netMana.add(new Mana(0,0,0,0,0,0,effect.getAmount(), 0)); + this.netMana.add(new Mana(0, 0, 0, 0, 0, 0, effect.getAmount(), 0)); + this.maxActivationsPerTurn = 1; } public ActivateOncePerTurnManaAbility(ActivateOncePerTurnManaAbility ability) { super(ability); } - @Override - public boolean canActivate(UUID playerId, Game game) { - if (super.canActivate(playerId, game)) { - ActivationInfo activationInfo = getActivationInfo(game); - if (activationInfo == null || activationInfo.turnNum != game.getTurnNum() || activationInfo.activationCounter < 1) { - return true; - } - } - return false; - } - @Override public boolean activate(Game game, boolean noMana) { if (canActivate(this.controllerId, game)) { - if (super.activate(game, noMana)) { - ActivationInfo activationInfo = getActivationInfo(game); - if (activationInfo == null) { - activationInfo = new ActivationInfo(game.getTurnNum(), 1); - } else { - if (activationInfo.turnNum != game.getTurnNum()) { - activationInfo.turnNum = game.getTurnNum(); - activationInfo.activationCounter = 1; - } else { - activationInfo.activationCounter++; - } - } - setActivationInfo(activationInfo, game); - return true; - } + return super.activate(game, noMana); } return false; } @@ -112,18 +74,4 @@ public class ActivateOncePerTurnManaAbility extends ActivatedManaAbilityImpl { return new ActivateOncePerTurnManaAbility(this); } - private ActivationInfo getActivationInfo(Game game) { - Integer turnNum = (Integer) game.getState().getValue(CardUtil.getCardZoneString("activationsTurn", sourceId, game)); - Integer activationCount = (Integer) game.getState().getValue(CardUtil.getCardZoneString("activationsCount", sourceId, game)); - if (turnNum == null || activationCount == null) { - return null; - } - return new ActivationInfo(turnNum, activationCount); - } - - private void setActivationInfo(ActivationInfo activationInfo, Game game) { - game.getState().setValue(CardUtil.getCardZoneString("activationsTurn", sourceId, game), activationInfo.turnNum); - game.getState().setValue(CardUtil.getCardZoneString("activationsCount", sourceId, game), activationInfo.activationCounter); - } - } diff --git a/Mage/src/main/java/mage/abilities/mana/ActivatedManaAbilityImpl.java b/Mage/src/main/java/mage/abilities/mana/ActivatedManaAbilityImpl.java index fef2dd0eb6e..61da85343ac 100644 --- a/Mage/src/main/java/mage/abilities/mana/ActivatedManaAbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/mana/ActivatedManaAbilityImpl.java @@ -69,10 +69,13 @@ public abstract class ActivatedManaAbilityImpl extends ActivatedAbilityImpl impl @Override public boolean canActivate(UUID playerId, Game game) { + if (!super.hasMoreActivationsThisTurn(game) || !(condition == null || condition.apply(game, this))) { + return false; + } if (!controlsAbility(playerId, game)) { return false; } - if (timing == TimingRule.SORCERY + if (timing == TimingRule.SORCERY && !game.canPlaySorcery(playerId) && !game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_AS_INSTANT, this, controllerId, game)) { return false; From 786a62befa08e21f2a44c8f757d3e63281d9cdaa Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Tue, 12 Sep 2017 10:10:18 -0400 Subject: [PATCH 03/35] updated various activated abilities --- .../src/mage/cards/c/CabalInquisitor.java | 16 +----- .../src/mage/cards/c/ChronatogTotem.java | 17 ++---- Mage.Sets/src/mage/cards/e/EvolvingWilds.java | 36 ++++--------- .../src/mage/cards/g/GargoyleCastle.java | 36 ++++--------- .../src/mage/cards/g/GroundlingPouncer.java | 12 +---- Mage.Sets/src/mage/cards/k/KyrenToy.java | 4 +- .../src/mage/cards/m/MulDayaChannelers.java | 52 +------------------ .../src/mage/cards/t/TerramorphicExpanse.java | 36 ++++--------- .../src/mage/cards/w/WellOfKnowledge.java | 3 -- 9 files changed, 40 insertions(+), 172 deletions(-) diff --git a/Mage.Sets/src/mage/cards/c/CabalInquisitor.java b/Mage.Sets/src/mage/cards/c/CabalInquisitor.java index ded5d90a146..43f4de72c2e 100644 --- a/Mage.Sets/src/mage/cards/c/CabalInquisitor.java +++ b/Mage.Sets/src/mage/cards/c/CabalInquisitor.java @@ -52,11 +52,10 @@ import mage.target.common.TargetCardInYourGraveyard; * * @author cbt33 */ - public class CabalInquisitor extends CardImpl { public CabalInquisitor(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.MINION); @@ -82,11 +81,8 @@ public class CabalInquisitor extends CardImpl { } } - class ActivateAsSorceryConditionalActivatedAbility extends ActivatedAbilityImpl { - private Condition condition; - private static final Effects emptyEffects = new Effects(); public ActivateAsSorceryConditionalActivatedAbility(Zone zone, Effect effect, ManaCosts cost, Condition condition) { @@ -95,10 +91,8 @@ class ActivateAsSorceryConditionalActivatedAbility extends ActivatedAbilityImpl timing = TimingRule.SORCERY; } - public ActivateAsSorceryConditionalActivatedAbility(final ActivateAsSorceryConditionalActivatedAbility ability) { super(ability); - this.condition = ability.condition; } @Override @@ -109,14 +103,6 @@ class ActivateAsSorceryConditionalActivatedAbility extends ActivatedAbilityImpl return super.getEffects(game, effectType); } - @Override - public boolean canActivate(UUID playerId, Game game) { - if (!condition.apply(game, this)) { - return false; - } - return super.canActivate(playerId, game); - } - @Override public ActivateAsSorceryConditionalActivatedAbility copy() { return new ActivateAsSorceryConditionalActivatedAbility(this); diff --git a/Mage.Sets/src/mage/cards/c/ChronatogTotem.java b/Mage.Sets/src/mage/cards/c/ChronatogTotem.java index 3633454e292..2cb60a672e0 100644 --- a/Mage.Sets/src/mage/cards/c/ChronatogTotem.java +++ b/Mage.Sets/src/mage/cards/c/ChronatogTotem.java @@ -59,14 +59,14 @@ import mage.game.permanent.token.Token; public class ChronatogTotem extends CardImpl { public ChronatogTotem(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); // {tap}: Add {U} to your mana pool. this.addAbility(new BlueManaAbility()); - + // {1}{U}: Chronatog Totem becomes a 1/2 blue Atog artifact creature until end of turn. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new ChronatogTotemToken(), "", Duration.EndOfTurn), new ManaCostsImpl<>("{1}{U}"))); - + // {0}: Chronatog Totem gets +3/+3 until end of turn. You skip your next turn. Activate this ability only once each turn and only if Chronatog Totem is a creature. Ability ability = new ChronatogTotemAbility( Zone.BATTLEFIELD, @@ -91,8 +91,6 @@ class ChronatogTotemAbility extends LimitedTimesPerTurnActivatedAbility { private static final Effects emptyEffects = new Effects(); - private final Condition condition; - public ChronatogTotemAbility(Zone zone, Effect effect, Cost cost, Condition condition) { super(zone, effect, cost); this.condition = condition; @@ -100,7 +98,6 @@ class ChronatogTotemAbility extends LimitedTimesPerTurnActivatedAbility { public ChronatogTotemAbility(ChronatogTotemAbility ability) { super(ability); - this.condition = ability.condition; } @Override @@ -111,14 +108,6 @@ class ChronatogTotemAbility extends LimitedTimesPerTurnActivatedAbility { return super.getEffects(game, effectType); } - @Override - public boolean canActivate(UUID playerId, Game game) { - if (!condition.apply(game, this)) { - return false; - } - return super.canActivate(playerId, game); - } - @Override public ChronatogTotemAbility copy() { return new ChronatogTotemAbility(this); diff --git a/Mage.Sets/src/mage/cards/e/EvolvingWilds.java b/Mage.Sets/src/mage/cards/e/EvolvingWilds.java index 69211f6845d..13c09f8abda 100644 --- a/Mage.Sets/src/mage/cards/e/EvolvingWilds.java +++ b/Mage.Sets/src/mage/cards/e/EvolvingWilds.java @@ -27,19 +27,19 @@ */ package mage.cards.e; -import mage.abilities.ActivatedAbilityImpl; -import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.StaticFilters; import mage.target.common.TargetCardInLibrary; import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; /** * @@ -48,10 +48,15 @@ import java.util.UUID; public class EvolvingWilds extends CardImpl { public EvolvingWilds(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.LAND},null); + super(ownerId, setInfo, new CardType[]{CardType.LAND}, null); // {T}, Sacrifice Evolving Wilds: Search your library for a basic land card and put it onto the battlefield tapped. Then shuffle your library. - this.addAbility(new EvolvingWildsAbility()); + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(StaticFilters.FILTER_BASIC_LAND_CARD), true), + new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); } public EvolvingWilds(final EvolvingWilds card) { @@ -64,24 +69,3 @@ public class EvolvingWilds extends CardImpl { } } - -class EvolvingWildsAbility extends ActivatedAbilityImpl { - - public EvolvingWildsAbility() { - super(Zone.BATTLEFIELD, null); - addCost(new TapSourceCost()); - addCost(new SacrificeSourceCost()); - TargetCardInLibrary target = new TargetCardInLibrary(StaticFilters.FILTER_BASIC_LAND_CARD); - addEffect(new SearchLibraryPutInPlayEffect(target, true, Outcome.PutLandInPlay)); - } - - public EvolvingWildsAbility(final EvolvingWildsAbility ability) { - super(ability); - } - - @Override - public EvolvingWildsAbility copy() { - return new EvolvingWildsAbility(this); - } - -} diff --git a/Mage.Sets/src/mage/cards/g/GargoyleCastle.java b/Mage.Sets/src/mage/cards/g/GargoyleCastle.java index 69ab8a9efa9..56ec46d63cb 100644 --- a/Mage.Sets/src/mage/cards/g/GargoyleCastle.java +++ b/Mage.Sets/src/mage/cards/g/GargoyleCastle.java @@ -28,10 +28,11 @@ package mage.cards.g; import java.util.UUID; -import mage.abilities.ActivatedAbilityImpl; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.mana.ColorlessManaAbility; import mage.cards.CardImpl; @@ -52,7 +53,13 @@ public class GargoyleCastle extends CardImpl { this.addAbility(new ColorlessManaAbility()); // {T}, {5}, Sacrifice Gargoyle Castle: Put a 3/4 colorless Gargoyle artifact creature token with flying onto the battlefield. - this.addAbility(new GargoyleCastleAbility()); + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new CreateTokenEffect(new GargoyleToken()), + new ManaCostsImpl("{5}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); } public GargoyleCastle(final GargoyleCastle card) { @@ -64,25 +71,4 @@ public class GargoyleCastle extends CardImpl { return new GargoyleCastle(this); } -} - -class GargoyleCastleAbility extends ActivatedAbilityImpl { - - public GargoyleCastleAbility() { - super(Zone.BATTLEFIELD, null); - addCost(new TapSourceCost()); - addCost(new GenericManaCost(5)); - addCost(new SacrificeSourceCost()); - addEffect(new CreateTokenEffect(new GargoyleToken())); - } - - public GargoyleCastleAbility(final GargoyleCastleAbility ability) { - super(ability); - } - - @Override - public GargoyleCastleAbility copy() { - return new GargoyleCastleAbility(this); - } - -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/g/GroundlingPouncer.java b/Mage.Sets/src/mage/cards/g/GroundlingPouncer.java index 41b3e883e15..c03cd462e13 100644 --- a/Mage.Sets/src/mage/cards/g/GroundlingPouncer.java +++ b/Mage.Sets/src/mage/cards/g/GroundlingPouncer.java @@ -65,7 +65,7 @@ public class GroundlingPouncer extends CardImpl { } public GroundlingPouncer(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G/U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G/U}"); this.subtype.add(SubType.FAERIE); this.power = new MageInt(2); @@ -97,7 +97,6 @@ class GroundlingPouncerAbility extends LimitedTimesPerTurnActivatedAbility { private static final Effects emptyEffects = new Effects(); - private final Condition condition; private final String ruleText; public GroundlingPouncerAbility(Zone zone, Effect effect, Cost cost, Condition condition, String rule) { @@ -108,7 +107,6 @@ class GroundlingPouncerAbility extends LimitedTimesPerTurnActivatedAbility { public GroundlingPouncerAbility(GroundlingPouncerAbility ability) { super(ability); - this.condition = ability.condition; this.ruleText = ability.ruleText; } @@ -120,14 +118,6 @@ class GroundlingPouncerAbility extends LimitedTimesPerTurnActivatedAbility { return super.getEffects(game, effectType); } - @Override - public boolean canActivate(UUID playerId, Game game) { - if (!condition.apply(game, this)) { - return false; - } - return super.canActivate(playerId, game); - } - @Override public GroundlingPouncerAbility copy() { return new GroundlingPouncerAbility(this); diff --git a/Mage.Sets/src/mage/cards/k/KyrenToy.java b/Mage.Sets/src/mage/cards/k/KyrenToy.java index dd757a25c09..0dc4decc0c0 100644 --- a/Mage.Sets/src/mage/cards/k/KyrenToy.java +++ b/Mage.Sets/src/mage/cards/k/KyrenToy.java @@ -53,7 +53,7 @@ import mage.players.Player; public class KyrenToy extends CardImpl { public KyrenToy(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); // {1}, {T}: Put a charge counter on Kyren Toy. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.CHARGE.createInstance(1)), new GenericManaCost(1)); @@ -95,7 +95,7 @@ public class KyrenToy extends CardImpl { KyrenToyManaEffect() { super(); - staticText = "Add X mana of {C} to your mana pool, and then add {C} to your mana pool"; + staticText = "Add an amount of {C} to your mana pool equal to X plus one"; } KyrenToyManaEffect(final KyrenToyManaEffect effect) { diff --git a/Mage.Sets/src/mage/cards/m/MulDayaChannelers.java b/Mage.Sets/src/mage/cards/m/MulDayaChannelers.java index 5b84f8caa4e..b03c18ee684 100644 --- a/Mage.Sets/src/mage/cards/m/MulDayaChannelers.java +++ b/Mage.Sets/src/mage/cards/m/MulDayaChannelers.java @@ -30,17 +30,13 @@ package mage.cards.m; import java.util.UUID; import mage.MageInt; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.condition.Condition; import mage.abilities.condition.common.TopLibraryCardTypeCondition; -import mage.abilities.costs.Cost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.effects.common.AddManaOfAnyColorEffect; -import mage.abilities.effects.common.ManaEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.effects.common.continuous.PlayWithTheTopCardRevealedEffect; -import mage.abilities.mana.ActivatedManaAbilityImpl; import mage.abilities.mana.SimpleManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -48,7 +44,6 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Duration; import mage.constants.Zone; -import mage.game.Game; /** * @@ -59,7 +54,7 @@ public class MulDayaChannelers extends CardImpl { private static final String rule1 = "As long as the top card of your library is a creature card, {this} gets +3/+3"; public MulDayaChannelers(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}{G}"); this.subtype.add(SubType.ELF); this.subtype.add(SubType.DRUID); this.subtype.add(SubType.SHAMAN); @@ -81,7 +76,7 @@ public class MulDayaChannelers extends CardImpl { new TopLibraryCardTypeCondition(CardType.LAND), "As long as the top card of your library is a land card, Mul Daya Channelers has \"{T}: Add two mana of any one color to your mana pool.\""); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); - + } public MulDayaChannelers(final MulDayaChannelers card) { @@ -93,46 +88,3 @@ public class MulDayaChannelers extends CardImpl { return new MulDayaChannelers(this); } } - - -class MulDayaChannelersActivateIfConditionManaAbility extends ActivatedManaAbilityImpl { - - private Condition condition; - - public MulDayaChannelersActivateIfConditionManaAbility(Zone zone, ManaEffect effect, Cost cost, Condition condition) { - super(zone, effect, cost); - this.condition = condition; - } - - public MulDayaChannelersActivateIfConditionManaAbility(MulDayaChannelersActivateIfConditionManaAbility ability) { - super(ability); - this.condition = ability.condition; - } - - @Override - public boolean canActivate(UUID playerId, Game game) { - if (condition.apply(game, this)) { - return super.canActivate(playerId, game); - } - return false; - } - - @Override - public boolean activate(Game game, boolean noMana) { - if (canActivate(this.controllerId, game)) { - return super.activate(game, noMana); - } - return false; - } - - @Override - public String getRule() { - return "As long as the top card of your library is a land card, {this} has \"{T}: Add two mana of any one color to your mana pool."; - } - - @Override - public MulDayaChannelersActivateIfConditionManaAbility copy() { - return new MulDayaChannelersActivateIfConditionManaAbility(this); - } - -} diff --git a/Mage.Sets/src/mage/cards/t/TerramorphicExpanse.java b/Mage.Sets/src/mage/cards/t/TerramorphicExpanse.java index 1038660daf7..5a4239c0926 100644 --- a/Mage.Sets/src/mage/cards/t/TerramorphicExpanse.java +++ b/Mage.Sets/src/mage/cards/t/TerramorphicExpanse.java @@ -25,22 +25,21 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.cards.t; -import mage.abilities.ActivatedAbilityImpl; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.StaticFilters; import mage.target.common.TargetCardInLibrary; import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; /** * @@ -49,8 +48,14 @@ import java.util.UUID; public class TerramorphicExpanse extends CardImpl { public TerramorphicExpanse(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.LAND},null); - this.addAbility(new TerramorphicExpanseAbility()); + super(ownerId, setInfo, new CardType[]{CardType.LAND}, null); + + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(StaticFilters.FILTER_BASIC_LAND_CARD), true), + new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); } public TerramorphicExpanse(final TerramorphicExpanse card) { @@ -63,24 +68,3 @@ public class TerramorphicExpanse extends CardImpl { } } - -class TerramorphicExpanseAbility extends ActivatedAbilityImpl { - - public TerramorphicExpanseAbility() { - super(Zone.BATTLEFIELD, null); - addCost(new TapSourceCost()); - addCost(new SacrificeSourceCost()); - TargetCardInLibrary target = new TargetCardInLibrary(StaticFilters.FILTER_BASIC_LAND_CARD); - addEffect(new SearchLibraryPutInPlayEffect(target, true, Outcome.PutLandInPlay)); - } - - public TerramorphicExpanseAbility(final TerramorphicExpanseAbility ability) { - super(ability); - } - - @Override - public TerramorphicExpanseAbility copy() { - return new TerramorphicExpanseAbility(this); - } - -} diff --git a/Mage.Sets/src/mage/cards/w/WellOfKnowledge.java b/Mage.Sets/src/mage/cards/w/WellOfKnowledge.java index 22afc30cae3..d7353371654 100644 --- a/Mage.Sets/src/mage/cards/w/WellOfKnowledge.java +++ b/Mage.Sets/src/mage/cards/w/WellOfKnowledge.java @@ -30,7 +30,6 @@ package mage.cards.w; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.ActivatedAbilityImpl; -import mage.abilities.condition.Condition; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.Effects; @@ -71,8 +70,6 @@ public class WellOfKnowledge extends CardImpl { class WellOfKnowledgeConditionalActivatedAbility extends ActivatedAbilityImpl { - private final Condition condition; - public WellOfKnowledgeConditionalActivatedAbility() { super(Zone.BATTLEFIELD, new WellOfKnowledgeEffect(), new GenericManaCost(2)); condition = new IsStepCondition(PhaseStep.DRAW, false); From a26c5a509ff88f9ba8ca63d5215e2aa442d945e3 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Tue, 12 Sep 2017 12:14:01 -0400 Subject: [PATCH 04/35] updated various activated abilities --- .../src/mage/cards/a/AncientHellkite.java | 100 ++++-------------- .../src/mage/cards/b/BrutalDeceiver.java | 52 ++++----- .../src/mage/cards/c/CallousDeceiver.java | 2 +- Mage.Sets/src/mage/cards/c/CruelDeceiver.java | 27 +++-- Mage.Sets/src/mage/cards/f/FeralDeceiver.java | 54 ++++++++-- Mage.Sets/src/mage/cards/h/HarshDeceiver.java | 55 ++++++++-- .../common/FeralDeceiverAbility.java | 50 --------- .../ConditionalActivatedAbility.java | 1 - .../ConditionalGainActivatedAbility.java | 2 - .../mana/ActivateIfConditionManaAbility.java | 1 - 10 files changed, 163 insertions(+), 181 deletions(-) delete mode 100644 Mage/src/main/java/mage/abilities/common/FeralDeceiverAbility.java diff --git a/Mage.Sets/src/mage/cards/a/AncientHellkite.java b/Mage.Sets/src/mage/cards/a/AncientHellkite.java index a44e3c9817f..bb830ed9732 100644 --- a/Mage.Sets/src/mage/cards/a/AncientHellkite.java +++ b/Mage.Sets/src/mage/cards/a/AncientHellkite.java @@ -25,28 +25,24 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.cards.a; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.ActivatedAbilityImpl; -import mage.abilities.costs.Cost; -import mage.abilities.costs.CostImpl; -import mage.abilities.costs.mana.ColoredManaCost; +import mage.abilities.condition.common.SourceAttackingCondition; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.decorator.ConditionalActivatedAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.ColoredManaSymbol; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; /** @@ -55,19 +51,37 @@ import mage.target.common.TargetCreaturePermanent; */ public class AncientHellkite extends CardImpl { + private final UUID originalId; + public AncientHellkite(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{R}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}{R}{R}"); this.subtype.add(SubType.DRAGON); this.power = new MageInt(6); this.toughness = new MageInt(6); this.addAbility(FlyingAbility.getInstance()); - this.addAbility(new AncientHellkiteAbility()); + Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new ManaCostsImpl("{R}"), SourceAttackingCondition.instance); + ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature defending player controls"))); + originalId = ability.getOriginalId(); + this.addAbility(ability); } public AncientHellkite(final AncientHellkite card) { super(card); + this.originalId = card.originalId; + } + + @Override + public void adjustTargets(Ability ability, Game game) { + if (ability.getOriginalId().equals(originalId)) { + ability.getTargets().clear(); + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); + UUID defenderId = game.getCombat().getDefenderId(ability.getSourceId()); + filter.add(new ControllerIdPredicate(defenderId)); + TargetCreaturePermanent target = new TargetCreaturePermanent(filter); + ability.addTarget(target); + } } @Override @@ -76,71 +90,3 @@ public class AncientHellkite extends CardImpl { } } - -class AncientHellkiteAbility extends ActivatedAbilityImpl { - - private static final FilterCreaturePermanent filterTemplate = new FilterCreaturePermanent("creature defending player controls"); - - public AncientHellkiteAbility() { - super(Zone.BATTLEFIELD, new DamageTargetEffect(1)); - addCost(new AncientHellkiteCost()); - addManaCost(new ColoredManaCost(ColoredManaSymbol.R)); - addTarget(new TargetCreaturePermanent(filterTemplate)); - } - - public AncientHellkiteAbility(final AncientHellkiteAbility ability) { - super(ability); - } - - @Override - public AncientHellkiteAbility copy() { - return new AncientHellkiteAbility(this); - } - - @Override - public boolean activate(Game game, boolean noMana) { - UUID defenderId = game.getCombat().getDefenderId(sourceId); - if (defenderId != null) { - FilterCreaturePermanent filter = filterTemplate.copy(); - filter.add(new ControllerIdPredicate(defenderId)); - - this.getTargets().clear(); - TargetCreaturePermanent target = new TargetCreaturePermanent(filter); - this.addTarget(target); - return super.activate(game, noMana); - } - return false; - } -} - -class AncientHellkiteCost extends CostImpl { - - public AncientHellkiteCost() { - this.text = "Activate this ability only if Ancient Hellkite is attacking"; - } - - public AncientHellkiteCost(final AncientHellkiteCost cost) { - super(cost); - } - - @Override - public AncientHellkiteCost copy() { - return new AncientHellkiteCost(this); - } - - @Override - public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { - Permanent permanent = game.getPermanent(sourceId); - if (permanent != null && permanent.isAttacking()) { - return true; - } - return false; - } - - @Override - public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { - this.paid = true; - return paid; - } - -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/b/BrutalDeceiver.java b/Mage.Sets/src/mage/cards/b/BrutalDeceiver.java index 0ff4dc40918..e443ace2d94 100644 --- a/Mage.Sets/src/mage/cards/b/BrutalDeceiver.java +++ b/Mage.Sets/src/mage/cards/b/BrutalDeceiver.java @@ -29,13 +29,13 @@ package mage.cards.b; import java.util.UUID; import mage.MageInt; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.LimitedTimesPerTurnActivatedAbility; import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.costs.Cost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.LookLibraryControllerEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; @@ -43,6 +43,7 @@ import mage.abilities.keyword.FirstStrikeAbility; import mage.cards.*; import mage.constants.CardType; import mage.constants.Duration; +import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.Zone; import mage.game.Game; @@ -55,7 +56,7 @@ import mage.players.Player; public class BrutalDeceiver extends CardImpl { public BrutalDeceiver(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); this.subtype.add(SubType.SPIRIT); this.power = new MageInt(2); @@ -65,9 +66,7 @@ public class BrutalDeceiver extends CardImpl { this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new LookLibraryControllerEffect(), new GenericManaCost(1))); // {2}: Reveal the top card of your library. If it's a land card, {this} gets +1/+0 and gains first strike until end of turn. - Ability ability = new BrutalDeceiverAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl("{2}")); - ability.addEffect(new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn)); - this.addAbility(ability); + this.addAbility(new LimitedTimesPerTurnActivatedAbility(Zone.BATTLEFIELD, new BrutalDeceiverEffect(), new ManaCostsImpl("{2}"))); } public BrutalDeceiver(final BrutalDeceiver card) { @@ -80,38 +79,39 @@ public class BrutalDeceiver extends CardImpl { } } -class BrutalDeceiverAbility extends LimitedTimesPerTurnActivatedAbility { +class BrutalDeceiverEffect extends OneShotEffect { - public BrutalDeceiverAbility(Zone zone, Effect effect, Cost cost) { - super(zone, effect, cost); + public BrutalDeceiverEffect() { + super(Outcome.BoostCreature); + this.staticText = "Reveal the top card of your library. If it's a land card, {this} gets +1/+0 and gains first strike until end of turn"; } - public BrutalDeceiverAbility(BrutalDeceiverAbility ability) { - super(ability); + public BrutalDeceiverEffect(final BrutalDeceiverEffect effect) { + super(effect); } @Override - public BrutalDeceiverAbility copy() { - return new BrutalDeceiverAbility(this); + public BrutalDeceiverEffect copy() { + return new BrutalDeceiverEffect(this); } @Override - public boolean checkIfClause(Game game) { - Player player = game.getPlayer(this.getControllerId()); - if (player != null) { + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = source.getSourceObject(game); + if (controller != null && sourceObject != null) { Cards cards = new CardsImpl(); - Card card = player.getLibrary().getFromTop(game); - cards.add(card); - player.revealCards("Brutal Deceiver", cards, game); - if (card != null && card.isLand()) { - return true; + Card card = controller.getLibrary().getFromTop(game); + if (card != null) { + cards.add(card); + controller.revealCards(sourceObject.getIdName(), cards, game); + if (card.isLand()) { + game.addEffect(new BoostSourceEffect(1, 0, Duration.EndOfTurn), source); + game.addEffect(new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), source); + } } + return true; } return false; } - - @Override - public String getRule() { - return "{2}: Reveal the top card of your library. If it's a land card, {this} gets +1/+0 and gains first strike until end of turn. Activate this ability only once each turn."; - } } diff --git a/Mage.Sets/src/mage/cards/c/CallousDeceiver.java b/Mage.Sets/src/mage/cards/c/CallousDeceiver.java index 4aa3f68801a..03c905e245a 100644 --- a/Mage.Sets/src/mage/cards/c/CallousDeceiver.java +++ b/Mage.Sets/src/mage/cards/c/CallousDeceiver.java @@ -56,7 +56,7 @@ import mage.players.Player; public class CallousDeceiver extends CardImpl { public CallousDeceiver(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); this.subtype.add(SubType.SPIRIT); this.power = new MageInt(1); diff --git a/Mage.Sets/src/mage/cards/c/CruelDeceiver.java b/Mage.Sets/src/mage/cards/c/CruelDeceiver.java index ed6b1ef8e38..95bab5f5e99 100644 --- a/Mage.Sets/src/mage/cards/c/CruelDeceiver.java +++ b/Mage.Sets/src/mage/cards/c/CruelDeceiver.java @@ -29,16 +29,18 @@ package mage.cards.c; import java.util.UUID; import mage.MageInt; +import mage.MageObject; import mage.abilities.Ability; +import mage.abilities.common.DealsDamageToACreatureTriggeredAbility; import mage.abilities.common.LimitedTimesPerTurnActivatedAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.LookLibraryControllerEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; -import mage.abilities.keyword.TrampleAbility; import mage.cards.*; import mage.constants.CardType; import mage.constants.SubType; @@ -55,7 +57,7 @@ import mage.players.Player; public class CruelDeceiver extends CardImpl { public CruelDeceiver(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); this.subtype.add(SubType.SPIRIT); this.power = new MageInt(2); @@ -82,7 +84,7 @@ class CruelDeceiverEffect extends OneShotEffect { public CruelDeceiverEffect() { super(Outcome.AddAbility); - this.staticText = "Reveal the top card of your library. If it's a land card, {this} gets +2/+2 and gains trample until end of turn"; + this.staticText = "Reveal the top card of your library. If it's a land card, Cruel Deceiver gains \"Whenever Cruel Deceiver deals damage to a creature, destroy that creature\" until end of turn"; } public CruelDeceiverEffect(final CruelDeceiverEffect effect) { @@ -96,15 +98,18 @@ class CruelDeceiverEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = source.getSourceObject(game); + if (controller != null && sourceObject != null) { Cards cards = new CardsImpl(); - Card card = player.getLibrary().getFromTop(game); - cards.add(card); - player.revealCards("Cruel Deceiver", cards, game); - if (card != null && card.isLand()) { - game.addEffect(new BoostSourceEffect(2,2,Duration.EndOfTurn), source); - game.addEffect(new GainAbilitySourceEffect(TrampleAbility.getInstance(),Duration.EndOfTurn), source); + Card card = controller.getLibrary().getFromTop(game); + if (card != null) { + cards.add(card); + controller.revealCards(sourceObject.getIdName(), cards, game); + if (card.isLand()) { + game.addEffect(new BoostSourceEffect(1, 0, Duration.EndOfTurn), source); + game.addEffect(new GainAbilitySourceEffect(new DealsDamageToACreatureTriggeredAbility(new DestroyTargetEffect(true), false, false, true), Duration.EndOfTurn), source); + } } return true; } diff --git a/Mage.Sets/src/mage/cards/f/FeralDeceiver.java b/Mage.Sets/src/mage/cards/f/FeralDeceiver.java index c590aced713..5bde2e76fc3 100644 --- a/Mage.Sets/src/mage/cards/f/FeralDeceiver.java +++ b/Mage.Sets/src/mage/cards/f/FeralDeceiver.java @@ -29,21 +29,29 @@ package mage.cards.f; import java.util.UUID; import mage.MageInt; +import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.common.FeralDeceiverAbility; +import mage.abilities.common.LimitedTimesPerTurnActivatedAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.LookLibraryControllerEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.TrampleAbility; +import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.CardsImpl; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Duration; +import mage.constants.Outcome; import mage.constants.Zone; +import mage.game.Game; +import mage.players.Player; /** * @@ -52,19 +60,17 @@ import mage.constants.Zone; public class FeralDeceiver extends CardImpl { public FeralDeceiver(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}"); this.subtype.add(SubType.SPIRIT); this.power = new MageInt(3); this.toughness = new MageInt(2); // {1}: Look at the top card of your library. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new LookLibraryControllerEffect(), new GenericManaCost(1))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new LookLibraryControllerEffect(), new GenericManaCost(1))); // {2}: Reveal the top card of your library. If it's a land card, {this} gets +2/+2 and gains trample until end of turn. - Ability ability = new FeralDeceiverAbility(Zone.BATTLEFIELD, new BoostSourceEffect(2,2,Duration.EndOfTurn), new ManaCostsImpl("{2}")); - ability.addEffect(new GainAbilitySourceEffect(TrampleAbility.getInstance(),Duration.EndOfTurn)); - this.addAbility(ability); + this.addAbility(new LimitedTimesPerTurnActivatedAbility(Zone.BATTLEFIELD, new FeralDeceiverEffect(), new ManaCostsImpl("{2}"))); } public FeralDeceiver(final FeralDeceiver card) { @@ -77,3 +83,39 @@ public class FeralDeceiver extends CardImpl { } } +class FeralDeceiverEffect extends OneShotEffect { + + public FeralDeceiverEffect() { + super(Outcome.BoostCreature); + this.staticText = "Reveal the top card of your library. If it's a land card, {this} gets +2/+2 and gains trample until end of turn"; + } + + public FeralDeceiverEffect(final FeralDeceiverEffect effect) { + super(effect); + } + + @Override + public FeralDeceiverEffect copy() { + return new FeralDeceiverEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = source.getSourceObject(game); + if (controller != null && sourceObject != null) { + Cards cards = new CardsImpl(); + Card card = controller.getLibrary().getFromTop(game); + if (card != null) { + cards.add(card); + controller.revealCards(sourceObject.getIdName(), cards, game); + if (card.isLand()) { + game.addEffect(new BoostSourceEffect(2, 2, Duration.EndOfTurn), source); + game.addEffect(new GainAbilitySourceEffect(TrampleAbility.getInstance(), Duration.EndOfTurn), source); + } + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/h/HarshDeceiver.java b/Mage.Sets/src/mage/cards/h/HarshDeceiver.java index 6debef53fae..af887e3e3b8 100644 --- a/Mage.Sets/src/mage/cards/h/HarshDeceiver.java +++ b/Mage.Sets/src/mage/cards/h/HarshDeceiver.java @@ -29,20 +29,28 @@ package mage.cards.h; import java.util.UUID; import mage.MageInt; +import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.common.FeralDeceiverAbility; +import mage.abilities.common.LimitedTimesPerTurnActivatedAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.LookLibraryControllerEffect; import mage.abilities.effects.common.UntapSourceEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.CardsImpl; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Duration; +import mage.constants.Outcome; import mage.constants.Zone; +import mage.game.Game; +import mage.players.Player; /** * @@ -51,19 +59,17 @@ import mage.constants.Zone; public class HarshDeceiver extends CardImpl { public HarshDeceiver(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); this.subtype.add(SubType.SPIRIT); this.power = new MageInt(1); this.toughness = new MageInt(4); // {1}: Look at the top card of your library. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new LookLibraryControllerEffect(), new GenericManaCost(1))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new LookLibraryControllerEffect(), new GenericManaCost(1))); // {2}: Reveal the top card of your library. If it's a land card, untap {this} and it gets +1/+1 until end of turn. - Ability ability = new FeralDeceiverAbility(Zone.BATTLEFIELD, new UntapSourceEffect(), new ManaCostsImpl("{2}")); - ability.addEffect(new BoostSourceEffect(1,1,Duration.EndOfTurn)); - this.addAbility(ability); + this.addAbility(new LimitedTimesPerTurnActivatedAbility(Zone.BATTLEFIELD, new HarshDeceiverEffect(), new ManaCostsImpl("{2}"))); } public HarshDeceiver(final HarshDeceiver card) { @@ -75,3 +81,40 @@ public class HarshDeceiver extends CardImpl { return new HarshDeceiver(this); } } + +class HarshDeceiverEffect extends OneShotEffect { + + public HarshDeceiverEffect() { + super(Outcome.BoostCreature); + this.staticText = "Reveal the top card of your library. If it's a land card, untap {this} and it gets +1/+1 until end of turn"; + } + + public HarshDeceiverEffect(final HarshDeceiverEffect effect) { + super(effect); + } + + @Override + public HarshDeceiverEffect copy() { + return new HarshDeceiverEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = source.getSourceObject(game); + if (controller != null && sourceObject != null) { + Cards cards = new CardsImpl(); + Card card = controller.getLibrary().getFromTop(game); + if (card != null) { + cards.add(card); + controller.revealCards(sourceObject.getIdName(), cards, game); + if (card.isLand()) { + new UntapSourceEffect().apply(game, source); + game.addEffect(new BoostSourceEffect(1, 1, Duration.EndOfTurn), source); + } + } + return true; + } + return false; + } +} diff --git a/Mage/src/main/java/mage/abilities/common/FeralDeceiverAbility.java b/Mage/src/main/java/mage/abilities/common/FeralDeceiverAbility.java deleted file mode 100644 index 49c73bb6131..00000000000 --- a/Mage/src/main/java/mage/abilities/common/FeralDeceiverAbility.java +++ /dev/null @@ -1,50 +0,0 @@ -package mage.abilities.common; - -import mage.abilities.costs.Cost; -import mage.abilities.effects.Effect; -import mage.cards.Card; -import mage.cards.Cards; -import mage.cards.CardsImpl; -import mage.constants.CardType; -import mage.constants.Zone; -import mage.game.Game; -import mage.players.Player; - -/** - * Created by Eric on 9/24/2016. - */ -public class FeralDeceiverAbility extends LimitedTimesPerTurnActivatedAbility { - - public FeralDeceiverAbility(Zone zone, Effect effect, Cost cost) { - super(zone, effect, cost); - } - - public FeralDeceiverAbility(FeralDeceiverAbility ability) { - super(ability); - } - - @Override - public FeralDeceiverAbility copy() { - return new FeralDeceiverAbility(this); - } - - @Override - public boolean checkIfClause(Game game) { - Player player = game.getPlayer(this.getControllerId()); - if (player != null) { - Cards cards = new CardsImpl(); - Card card = player.getLibrary().getFromTop(game); - cards.add(card); - player.revealCards("Feral Deceiver", cards, game); - if (card != null && card.isLand()) { - return true; - } - } - return false; - } - - @Override - public String getRule() { - return "{2}: Reveal the top card of your library. If it's a land card, {this} gets +2/+2 and gains trample until end of turn. Activate this ability only once each turn."; - } -} diff --git a/Mage/src/main/java/mage/abilities/decorator/ConditionalActivatedAbility.java b/Mage/src/main/java/mage/abilities/decorator/ConditionalActivatedAbility.java index 0e159549ff2..86186e4b013 100644 --- a/Mage/src/main/java/mage/abilities/decorator/ConditionalActivatedAbility.java +++ b/Mage/src/main/java/mage/abilities/decorator/ConditionalActivatedAbility.java @@ -50,7 +50,6 @@ public class ConditionalActivatedAbility extends ActivatedAbilityImpl { public ConditionalActivatedAbility(final ConditionalActivatedAbility ability) { super(ability); - this.condition = ability.condition; this.ruleText = ability.ruleText; } diff --git a/Mage/src/main/java/mage/abilities/decorator/ConditionalGainActivatedAbility.java b/Mage/src/main/java/mage/abilities/decorator/ConditionalGainActivatedAbility.java index 9fe5123f838..41660dda3e3 100644 --- a/Mage/src/main/java/mage/abilities/decorator/ConditionalGainActivatedAbility.java +++ b/Mage/src/main/java/mage/abilities/decorator/ConditionalGainActivatedAbility.java @@ -46,7 +46,6 @@ import mage.game.Game; */ public class ConditionalGainActivatedAbility extends ActivatedAbilityImpl { - private final Condition condition; private String staticText = ""; private static final Effects emptyEffects = new Effects(); @@ -71,7 +70,6 @@ public class ConditionalGainActivatedAbility extends ActivatedAbilityImpl { public ConditionalGainActivatedAbility(ConditionalGainActivatedAbility ability) { super(ability); - this.condition = ability.condition; this.staticText = ability.staticText; } diff --git a/Mage/src/main/java/mage/abilities/mana/ActivateIfConditionManaAbility.java b/Mage/src/main/java/mage/abilities/mana/ActivateIfConditionManaAbility.java index d851810563c..f6c63bc2d46 100644 --- a/Mage/src/main/java/mage/abilities/mana/ActivateIfConditionManaAbility.java +++ b/Mage/src/main/java/mage/abilities/mana/ActivateIfConditionManaAbility.java @@ -50,7 +50,6 @@ public class ActivateIfConditionManaAbility extends ActivatedManaAbilityImpl { public ActivateIfConditionManaAbility(ActivateIfConditionManaAbility ability) { super(ability); - this.condition = ability.condition; } @Override From 155329ad0f20c11fc1660d1279d439ac8340c02e Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Tue, 12 Sep 2017 15:42:34 -0400 Subject: [PATCH 05/35] small change --- .../src/mage/cards/m/MairsilThePretender.java | 134 ------------------ 1 file changed, 134 deletions(-) diff --git a/Mage.Sets/src/mage/cards/m/MairsilThePretender.java b/Mage.Sets/src/mage/cards/m/MairsilThePretender.java index ca79b17b9d7..12657930276 100644 --- a/Mage.Sets/src/mage/cards/m/MairsilThePretender.java +++ b/Mage.Sets/src/mage/cards/m/MairsilThePretender.java @@ -82,8 +82,6 @@ public class MairsilThePretender extends CardImpl { // Mairsil, the Pretender has all activated abilities of all cards you own in exile with cage counters on them. You may activate each of those abilities only once each turn. Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new MairsilThePretenderGainAbilitiesEffect()); this.addAbility(ability); -// ability.addEffect(new MairsilThePretenderRuleModifyingEffect()); -// this.addAbility(ability, new MairsilThePretenderWatcher()); } public MairsilThePretender(final MairsilThePretender card) { @@ -188,135 +186,3 @@ class MairsilThePretenderGainAbilitiesEffect extends ContinuousEffectImpl { return new MairsilThePretenderGainAbilitiesEffect(this); } } - -//class MairsilThePretenderWatcher extends Watcher { -// -// public final Map> activatedThisTurnAbilities = new HashMap<>(); -// -// public MairsilThePretenderWatcher() { -// super(MairsilThePretenderWatcher.class.getSimpleName(), WatcherScope.GAME); -// } -// -// public MairsilThePretenderWatcher(final MairsilThePretenderWatcher watcher) { -// super(watcher); -// for (Entry> entry : watcher.activatedThisTurnAbilities.entrySet()) { -// activatedThisTurnAbilities.put(entry.getKey(), entry.getValue()); -// } -// } -// -// @Override -// public void watch(GameEvent event, Game game) { -// if (event.getType() == GameEvent.EventType.ZONE_CHANGE && event instanceof ZoneChangeEvent) { -// ZoneChangeEvent zEvent = (ZoneChangeEvent) event; -// if (zEvent.getFromZone() == Zone.BATTLEFIELD) { -// Permanent permanent = zEvent.getTarget(); -// if (permanent != null) { -// this.activatedThisTurnAbilities.remove(permanent.getId()); -// } -// } -// } -// if (event.getType() == GameEvent.EventType.ACTIVATED_ABILITY) { -// Set permAbilities; -// if (activatedThisTurnAbilities.keySet().contains(event.getSourceId())) { -// permAbilities = activatedThisTurnAbilities.get(event.getSourceId()); -// } else { -// permAbilities = new HashSet<>(); -// } -// StackAbility ability = (StackAbility) game.getStack().getStackObject(event.getSourceId()); -// if (ability != null && ability.getStackAbility().isActivated()) { -// for (Effect effect : ability.getAllEffects()) { -// if (effect instanceof DoNothingEffect) { -// permAbilities.add((UUID) effect.getValue("key")); -// this.activatedThisTurnAbilities.put(event.getSourceId(), permAbilities); -// } -// } -// } -// } -// } -// -// @Override -// public void reset() { -// activatedThisTurnAbilities.clear(); -// } -// -// public Map> getActivatedThisTurnAbilities() { -// return this.activatedThisTurnAbilities; -// } -// -// @Override -// public MairsilThePretenderWatcher copy() { -// return new MairsilThePretenderWatcher(this); -// } -// -//} -// -//class MairsilThePretenderRuleModifyingEffect extends ContinuousRuleModifyingEffectImpl { -// -// public MairsilThePretenderRuleModifyingEffect() { -// super(Duration.WhileOnBattlefield, Outcome.Detriment); -// } -// -// public MairsilThePretenderRuleModifyingEffect(final MairsilThePretenderRuleModifyingEffect effect) { -// super(effect); -// } -// -// @Override -// public MairsilThePretenderRuleModifyingEffect copy() { -// return new MairsilThePretenderRuleModifyingEffect(this); -// } -// -// @Override -// public boolean apply(Game game, Ability source) { -// return true; -// } -// -// @Override -// public boolean checksEventType(GameEvent event, Game game) { -// return event.getType() == GameEvent.EventType.ACTIVATE_ABILITY; -// } -// -// @Override -// public boolean applies(GameEvent event, Ability source, Game game) { -// Optional ability = game.getAbility(event.getTargetId(), event.getSourceId()); -// MairsilThePretenderWatcher watcher = (MairsilThePretenderWatcher) game.getState().getWatchers().get(MairsilThePretenderWatcher.class.getSimpleName()); -// if (watcher != null && ability != null && ability.isPresent()) { -// for (Effect effect : ability.get().getAllEffects()) { -// if (effect instanceof DoNothingEffect) { -// UUID originalID = (UUID) effect.getValue("key"); -// if (watcher.getActivatedThisTurnAbilities().keySet().contains(event.getSourceId())) { -// if (watcher.getActivatedThisTurnAbilities().get(event.getSourceId()).contains(originalID)) { -// return true; -// } -// } -// } -// } -// } -// return false; -// } -// -// @Override -// public String getInfoMessage(Ability source, GameEvent event, Game game) { -// return "This ability can only be activated once each turn."; -// } -//} -// -//class DoNothingEffect extends OneShotEffect { -// -// DoNothingEffect() { -// super(Outcome.Neutral); -// } -// -// DoNothingEffect(final DoNothingEffect effect) { -// super(effect); -// } -// -// @Override -// public DoNothingEffect copy() { -// return new DoNothingEffect(this); -// } -// -// @Override -// public boolean apply(Game game, Ability source) { -// return true; -// } -//} From 32359386a03b39c9a1de2b2594dd6a0b6c1c9243 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Thu, 14 Sep 2017 12:27:05 +0200 Subject: [PATCH 06/35] Added Scarwood Bandits --- .../src/mage/cards/s/ScarwoodBandits.java | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/ScarwoodBandits.java diff --git a/Mage.Sets/src/mage/cards/s/ScarwoodBandits.java b/Mage.Sets/src/mage/cards/s/ScarwoodBandits.java new file mode 100644 index 00000000000..226defb05f3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ScarwoodBandits.java @@ -0,0 +1,134 @@ +/* + * 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.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.common.SourceOnBattlefieldCondition; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.Cost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.GainControlTargetEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.ForestwalkAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +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; +import mage.target.common.TargetArtifactPermanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author L_J + */ +public class ScarwoodBandits extends CardImpl { + + public ScarwoodBandits(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}{G}"); + this.subtype.add("Human"); + this.subtype.add("Rogue"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Forestwalk + this.addAbility(new ForestwalkAbility()); + + // {2}{G}, {tap}: Unless an opponent pays {2}, gain control of target artifact for as long as Scarwood Bandits remains on the battlefield. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ScarwoodBanditsEffect(new GenericManaCost(2)), new ManaCostsImpl("{2}{G}")); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetArtifactPermanent()); + this.addAbility(ability); + } + + public ScarwoodBandits(final ScarwoodBandits card) { + super(card); + } + + @Override + public ScarwoodBandits copy() { + return new ScarwoodBandits(this); + } +} + +class ScarwoodBanditsEffect extends OneShotEffect { + + protected Cost cost; + + public ScarwoodBanditsEffect(Cost cost) { + super(Outcome.Detriment); + this.staticText = "Unless an opponent pays {2}, gain control of target artifact for as long as Scarwood Bandits remains on the battlefield"; + this.cost = cost; + } + + public ScarwoodBanditsEffect(final ScarwoodBanditsEffect effect) { + super(effect); + this.cost = effect.cost.copy(); + } + + @Override + public ScarwoodBanditsEffect copy() { + return new ScarwoodBanditsEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Permanent targetArtifact = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (targetArtifact != null) { + Player player = game.getPlayer(targetArtifact.getControllerId()); + if (player != null) { + cost.clearPaid(); + if (player.chooseUse(Outcome.Benefit, "Pay {2}? (Otherwise Scarwood Bandits' controller gains control of" + targetArtifact.getLogName() + ")", source, game)) { + cost.pay(source, game, targetArtifact.getControllerId(), targetArtifact.getControllerId(), false, null); + } + if (!cost.isPaid()) { + ConditionalContinuousEffect effect = new ConditionalContinuousEffect( + new GainControlTargetEffect(Duration.Custom), + new SourceOnBattlefieldCondition(), + "Gain control of target artifact for as long as Scarwood Bandits remains on the battlefield."); + effect.setTargetPointer(new FixedTarget(targetArtifact.getId())); + game.addEffect(effect, source); + } + } + } + return true; + } + return false; + } +} From e65cb0f018ca96f90762456aeba04c5a2c0eea88 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Thu, 14 Sep 2017 12:28:27 +0200 Subject: [PATCH 07/35] Added Scarwood Bandits --- Mage.Sets/src/mage/sets/TheDark.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/TheDark.java b/Mage.Sets/src/mage/sets/TheDark.java index 7ff996766d8..293189e1d4c 100644 --- a/Mage.Sets/src/mage/sets/TheDark.java +++ b/Mage.Sets/src/mage/sets/TheDark.java @@ -68,7 +68,7 @@ public class TheDark extends ExpansionSet { cards.add(new SetCardInfo("Carnivorous Plant", 38, Rarity.COMMON, mage.cards.c.CarnivorousPlant.class)); cards.add(new SetCardInfo("Cave People", 59, Rarity.UNCOMMON, mage.cards.c.CavePeople.class)); cards.add(new SetCardInfo("City of Shadows", 113, Rarity.RARE, mage.cards.c.CityOfShadows.class)); - cards.add(new SetCardInfo("Cleansing", 77, Rarity.RARE, mage.cards.c.Cleansing.class)); + cards.add(new SetCardInfo("Cleansing", 77, Rarity.RARE, mage.cards.c.Cleansing.class)); cards.add(new SetCardInfo("Coal Golem", 96, Rarity.UNCOMMON, mage.cards.c.CoalGolem.class)); cards.add(new SetCardInfo("Dance of Many", 21, Rarity.RARE, mage.cards.d.DanceOfMany.class)); cards.add(new SetCardInfo("Dark Heart of the Wood", 117, Rarity.COMMON, mage.cards.d.DarkHeartOfTheWood.class)); @@ -105,7 +105,7 @@ public class TheDark extends ExpansionSet { cards.add(new SetCardInfo("Marsh Viper", 44, Rarity.COMMON, mage.cards.m.MarshViper.class)); cards.add(new SetCardInfo("Maze of Ith", 114, Rarity.UNCOMMON, mage.cards.m.MazeOfIth.class)); cards.add(new SetCardInfo("Merfolk Assassin", 31, Rarity.UNCOMMON, mage.cards.m.MerfolkAssassin.class)); - cards.add(new SetCardInfo("Mind Bomb", 32, Rarity.RARE, mage.cards.m.MindBomb.class)); + cards.add(new SetCardInfo("Mind Bomb", 32, Rarity.RARE, mage.cards.m.MindBomb.class)); cards.add(new SetCardInfo("Morale", 87, Rarity.COMMON, mage.cards.m.Morale.class)); cards.add(new SetCardInfo("Murk Dwellers", 11, Rarity.COMMON, mage.cards.m.MurkDwellers.class)); cards.add(new SetCardInfo("Niall Silvain", 45, Rarity.RARE, mage.cards.n.NiallSilvain.class)); @@ -116,6 +116,7 @@ public class TheDark extends ExpansionSet { cards.add(new SetCardInfo("Riptide", 34, Rarity.COMMON, mage.cards.r.Riptide.class)); cards.add(new SetCardInfo("Safe Haven", 115, Rarity.RARE, mage.cards.s.SafeHaven.class)); cards.add(new SetCardInfo("Savaen Elves", 47, Rarity.COMMON, mage.cards.s.SavaenElves.class)); + cards.add(new SetCardInfo("Scarwood Bandits", 48, Rarity.RARE, mage.cards.s.ScarwoodBandits.class)); cards.add(new SetCardInfo("Scarwood Goblins", 119, Rarity.COMMON, mage.cards.s.ScarwoodGoblins.class)); cards.add(new SetCardInfo("Scarwood Hag", 49, Rarity.UNCOMMON, mage.cards.s.ScarwoodHag.class)); cards.add(new SetCardInfo("Scavenger Folk", 50, Rarity.COMMON, mage.cards.s.ScavengerFolk.class)); From 98c2332b3c1bdb1398e47e22088b60ab664b297a Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 07:04:44 -0400 Subject: [PATCH 08/35] a few small changes --- Mage.Sets/src/mage/cards/c/CruelDeceiver.java | 4 +--- Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java | 3 +++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Mage.Sets/src/mage/cards/c/CruelDeceiver.java b/Mage.Sets/src/mage/cards/c/CruelDeceiver.java index 95bab5f5e99..dd515075b0b 100644 --- a/Mage.Sets/src/mage/cards/c/CruelDeceiver.java +++ b/Mage.Sets/src/mage/cards/c/CruelDeceiver.java @@ -39,7 +39,6 @@ import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.LookLibraryControllerEffect; -import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.cards.*; import mage.constants.CardType; @@ -84,7 +83,7 @@ class CruelDeceiverEffect extends OneShotEffect { public CruelDeceiverEffect() { super(Outcome.AddAbility); - this.staticText = "Reveal the top card of your library. If it's a land card, Cruel Deceiver gains \"Whenever Cruel Deceiver deals damage to a creature, destroy that creature\" until end of turn"; + this.staticText = "Reveal the top card of your library. If it's a land card, {this} gains \"Whenever Cruel Deceiver deals damage to a creature, destroy that creature\" until end of turn"; } public CruelDeceiverEffect(final CruelDeceiverEffect effect) { @@ -107,7 +106,6 @@ class CruelDeceiverEffect extends OneShotEffect { cards.add(card); controller.revealCards(sourceObject.getIdName(), cards, game); if (card.isLand()) { - game.addEffect(new BoostSourceEffect(1, 0, Duration.EndOfTurn), source); game.addEffect(new GainAbilitySourceEffect(new DealsDamageToACreatureTriggeredAbility(new DestroyTargetEffect(true), false, false, true), Duration.EndOfTurn), source); } } diff --git a/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java b/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java index 32c3728ee9d..cb8d83d4837 100644 --- a/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java @@ -276,6 +276,9 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa } protected boolean hasMoreActivationsThisTurn(Game game) { + if (maxActivationsPerTurn == Integer.MAX_VALUE) { + return true; + } ActivationInfo activationInfo = getActivationInfo(game); return activationInfo == null || activationInfo.turnNum != game.getTurnNum() || activationInfo.activationCounter < maxActivationsPerTurn; } From e401bebb4ecc69a00ee604b169b93913583a507b Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 06:57:43 -0400 Subject: [PATCH 09/35] fixed Sword-Point Diplomacy --- Mage.Sets/src/mage/cards/s/SwordPointDiplomacy.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Mage.Sets/src/mage/cards/s/SwordPointDiplomacy.java b/Mage.Sets/src/mage/cards/s/SwordPointDiplomacy.java index 7dd227bed81..75d9e447129 100644 --- a/Mage.Sets/src/mage/cards/s/SwordPointDiplomacy.java +++ b/Mage.Sets/src/mage/cards/s/SwordPointDiplomacy.java @@ -72,7 +72,7 @@ class SwordPointDiplomacyEffect extends OneShotEffect { SwordPointDiplomacyEffect() { super(Outcome.Benefit); - this.staticText = ""; + this.staticText = "Reveal the top three cards of your library. For each of those cards, put that card into your hand unless any opponent pays 3 life. Then exile the rest."; } SwordPointDiplomacyEffect(final SwordPointDiplomacyEffect effect) { @@ -102,10 +102,10 @@ class SwordPointDiplomacyEffect extends OneShotEffect { Cost cost = new PayLifeCost(3); for (UUID oppId : game.getOpponents(controller.getId())) { Player opponent = game.getPlayer(oppId); - if (!(opponent != null + if (opponent != null && cost.canPay(source, source.getSourceId(), opponent.getId(), game) && opponent.chooseUse(Outcome.Neutral, "Pay 3 life to prevent " + controller.getLogName() + " from getting " + card.getLogName() + "?", source, game) - && cost.pay(source, game, source.getSourceId(), opponent.getId(), true))) { + && cost.pay(source, game, source.getSourceId(), opponent.getId(), true)) { keepIt = false; } } From 9b25dc15c6499e683282c5f81fd088a809015cc5 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Thu, 14 Sep 2017 15:38:58 +0200 Subject: [PATCH 10/35] Updated Scarwood Bandits' subtypes and condition --- .../src/mage/cards/s/ScarwoodBandits.java | 117 +++++++++++++----- 1 file changed, 87 insertions(+), 30 deletions(-) diff --git a/Mage.Sets/src/mage/cards/s/ScarwoodBandits.java b/Mage.Sets/src/mage/cards/s/ScarwoodBandits.java index 226defb05f3..02573e4d6ad 100644 --- a/Mage.Sets/src/mage/cards/s/ScarwoodBandits.java +++ b/Mage.Sets/src/mage/cards/s/ScarwoodBandits.java @@ -29,6 +29,7 @@ package mage.cards.s; import java.util.UUID; import mage.MageInt; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.SourceOnBattlefieldCondition; @@ -38,19 +39,24 @@ import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.Effects; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.ForestwalkAbility; +import mage.abilities.Mode; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetArtifactPermanent; -import mage.target.targetpointer.FixedTarget; +import mage.util.CardUtil; /** * @@ -60,8 +66,8 @@ public class ScarwoodBandits extends CardImpl { public ScarwoodBandits(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}{G}"); - this.subtype.add("Human"); - this.subtype.add("Rogue"); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ROGUE); this.power = new MageInt(2); this.toughness = new MageInt(2); @@ -69,7 +75,14 @@ public class ScarwoodBandits extends CardImpl { this.addAbility(new ForestwalkAbility()); // {2}{G}, {tap}: Unless an opponent pays {2}, gain control of target artifact for as long as Scarwood Bandits remains on the battlefield. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ScarwoodBanditsEffect(new GenericManaCost(2)), new ManaCostsImpl("{2}{G}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, + new DoUnlessAnyOpponentPaysEffect( + new ConditionalContinuousEffect( + new GainControlTargetEffect(Duration.Custom, true), + new SourceOnBattlefieldCondition(), + "gain control of target artifact for as long as {this} remains on the battlefield"), + new GenericManaCost(2)), + new ManaCostsImpl("{2}{G}")); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetArtifactPermanent()); this.addAbility(ability); @@ -85,50 +98,94 @@ public class ScarwoodBandits extends CardImpl { } } -class ScarwoodBanditsEffect extends OneShotEffect { +class DoUnlessAnyOpponentPaysEffect extends OneShotEffect { - protected Cost cost; + protected Effects executingEffects = new Effects(); + private final Cost cost; + private String chooseUseText; - public ScarwoodBanditsEffect(Cost cost) { - super(Outcome.Detriment); - this.staticText = "Unless an opponent pays {2}, gain control of target artifact for as long as Scarwood Bandits remains on the battlefield"; + public DoUnlessAnyOpponentPaysEffect(Effect effect, Cost cost) { + this(effect, cost, null); + } + + public DoUnlessAnyOpponentPaysEffect(Effect effect, Cost cost, String chooseUseText) { + super(Outcome.Benefit); + this.executingEffects.add(effect); this.cost = cost; + this.chooseUseText = chooseUseText; } - public ScarwoodBanditsEffect(final ScarwoodBanditsEffect effect) { + public DoUnlessAnyOpponentPaysEffect(final DoUnlessAnyOpponentPaysEffect effect) { super(effect); + this.executingEffects = effect.executingEffects.copy(); this.cost = effect.cost.copy(); + this.chooseUseText = effect.chooseUseText; } - @Override - public ScarwoodBanditsEffect copy() { - return new ScarwoodBanditsEffect(this); + public void addEffect(Effect effect) { + executingEffects.add(effect); } @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - Permanent targetArtifact = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (targetArtifact != null) { - Player player = game.getPlayer(targetArtifact.getControllerId()); - if (player != null) { + MageObject sourceObject = game.getObject(source.getSourceId()); + if (controller != null && sourceObject != null) { + String message; + if (chooseUseText == null) { + String effectText = executingEffects.getText(source.getModes().getMode()); + message = "Pay " + cost.getText() + " to prevent (" + effectText.substring(0, effectText.length() - 1) + ")?"; + } else { + message = chooseUseText; + } + message = CardUtil.replaceSourceName(message, sourceObject.getName()); + boolean result = true; + boolean doEffect = true; + // check if any opponent is willing to pay + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null && player != controller && cost.canPay(source, source.getSourceId(), player.getId(), game) && player.chooseUse(Outcome.Detriment, message, source, game)) { cost.clearPaid(); - if (player.chooseUse(Outcome.Benefit, "Pay {2}? (Otherwise Scarwood Bandits' controller gains control of" + targetArtifact.getLogName() + ")", source, game)) { - cost.pay(source, game, targetArtifact.getControllerId(), targetArtifact.getControllerId(), false, null); - } - if (!cost.isPaid()) { - ConditionalContinuousEffect effect = new ConditionalContinuousEffect( - new GainControlTargetEffect(Duration.Custom), - new SourceOnBattlefieldCondition(), - "Gain control of target artifact for as long as Scarwood Bandits remains on the battlefield."); - effect.setTargetPointer(new FixedTarget(targetArtifact.getId())); - game.addEffect(effect, source); + 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; + break; } } - } - return true; + } + // do the effects if nobody paid + if (doEffect) { + for (Effect effect : executingEffects) { + effect.setTargetPointer(this.targetPointer); + if (effect instanceof OneShotEffect) { + result &= effect.apply(game, source); + } else { + game.addEffect((ContinuousEffect) effect, 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; + } + String effectsText = executingEffects.getText(mode); + return effectsText.substring(0, effectsText.length() - 1) + " unless any opponent pays " + cost.getText(); + } + + @Override + public DoUnlessAnyOpponentPaysEffect copy() { + return new DoUnlessAnyOpponentPaysEffect(this); + } } From f569331e2da494106508fe8568ccb978f2bb5ff2 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Thu, 14 Sep 2017 15:53:15 +0200 Subject: [PATCH 11/35] Updated Scarwood Bandits --- Mage.Sets/src/mage/cards/s/ScarwoodBandits.java | 1 - 1 file changed, 1 deletion(-) diff --git a/Mage.Sets/src/mage/cards/s/ScarwoodBandits.java b/Mage.Sets/src/mage/cards/s/ScarwoodBandits.java index 02573e4d6ad..d6fd2a6c256 100644 --- a/Mage.Sets/src/mage/cards/s/ScarwoodBandits.java +++ b/Mage.Sets/src/mage/cards/s/ScarwoodBandits.java @@ -151,7 +151,6 @@ class DoUnlessAnyOpponentPaysEffect extends OneShotEffect { game.informPlayers(player.getLogName() + " pays the cost to prevent the effect"); } doEffect = false; - break; } } } From 1ae29e900a9953fa0bfe114a790b793e833d4de1 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 10:02:32 -0400 Subject: [PATCH 12/35] Implemented Guided Passage --- Mage.Sets/src/mage/cards/g/GuidedPassage.java | 149 ++++++++++++++++++ Mage.Sets/src/mage/sets/Apocalypse.java | 1 + .../common/DoUnlessAnyPlayerPaysEffect.java | 1 - 3 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 Mage.Sets/src/mage/cards/g/GuidedPassage.java diff --git a/Mage.Sets/src/mage/cards/g/GuidedPassage.java b/Mage.Sets/src/mage/cards/g/GuidedPassage.java new file mode 100644 index 00000000000..fb04a3237b5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GuidedPassage.java @@ -0,0 +1,149 @@ +/* + * 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.cards.g; + +import java.util.Set; +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.common.FilterCreatureCard; +import mage.filter.common.FilterLandCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetCard; +import mage.target.common.TargetOpponent; + +/** + * + * @author TheElk801 + */ +public class GuidedPassage extends CardImpl { + + public GuidedPassage(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{U}{R}{G}"); + + // Reveal the cards in your library. An opponent chooses from among them a creature card, a land card, and a noncreature, nonland card. You put the chosen cards into your hand. Then shuffle your library. + this.getSpellAbility().addEffect(new GuidedPassageEffect()); + } + + public GuidedPassage(final GuidedPassage card) { + super(card); + } + + @Override + public GuidedPassage copy() { + return new GuidedPassage(this); + } +} + +class GuidedPassageEffect extends OneShotEffect { + + private static final FilterCard filter = new FilterCard("noncreature, nonland card"); + + static { + filter.add(Predicates.not(new CardTypePredicate(CardType.CREATURE))); + filter.add(Predicates.not(new CardTypePredicate(CardType.LAND))); + } + + GuidedPassageEffect() { + super(Outcome.Benefit); + this.staticText = "Reveal the cards in your library. An opponent chooses from among them a creature card, a land card, and a noncreature, nonland card. You put the chosen cards into your hand. Then shuffle your library."; + } + + GuidedPassageEffect(final GuidedPassageEffect effect) { + super(effect); + } + + @Override + public GuidedPassageEffect copy() { + return new GuidedPassageEffect(this); + } + + @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) { + return false; + } + int libSize = controller.getLibrary().size(); + if (libSize == 0) { + controller.shuffleLibrary(source, game); + return true; + } + CardsImpl cards = new CardsImpl(); + cards.addAll(controller.getLibrary().getTopCards(game, libSize)); + controller.revealCards(sourceObject.getIdName(), cards, game); + + Player opponent; + Set opponents = game.getOpponents(controller.getId()); + if (opponents.size() == 1) { + opponent = game.getPlayer(opponents.iterator().next()); + } else { + Target target = new TargetOpponent(true); + controller.chooseTarget(Outcome.Detriment, target, source, game); + opponent = game.getPlayer(target.getFirstTarget()); + } + TargetCard target1 = new TargetCard(1, Zone.LIBRARY, new FilterCreatureCard()); + TargetCard target2 = new TargetCard(1, Zone.LIBRARY, new FilterLandCard()); + TargetCard target3 = new TargetCard(1, Zone.LIBRARY, new FilterCard(filter)); + opponent.chooseTarget(Outcome.Detriment, cards, target1, source, game); + opponent.chooseTarget(Outcome.Detriment, cards, target2, source, game); + opponent.chooseTarget(Outcome.Detriment, cards, target3, source, game); + Cards cardsToHand = new CardsImpl(); + Card cardToHand; + cardToHand = game.getCard(target1.getFirstTarget()); + if (cardToHand != null) { + cardsToHand.add(cardToHand); + } + cardToHand = game.getCard(target2.getFirstTarget()); + if (cardToHand != null) { + cardsToHand.add(cardToHand); + } + cardToHand = game.getCard(target3.getFirstTarget()); + if (cardToHand != null) { + cardsToHand.add(cardToHand); + } + controller.moveCards(cardsToHand, Zone.HAND, source, game); + controller.shuffleLibrary(source, game); + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/Apocalypse.java b/Mage.Sets/src/mage/sets/Apocalypse.java index 8dd861e76e9..122dc92c5cc 100644 --- a/Mage.Sets/src/mage/sets/Apocalypse.java +++ b/Mage.Sets/src/mage/sets/Apocalypse.java @@ -70,6 +70,7 @@ public class Apocalypse extends ExpansionSet { cards.add(new SetCardInfo("Goblin Ringleader", 62, Rarity.UNCOMMON, mage.cards.g.GoblinRingleader.class)); cards.add(new SetCardInfo("Goblin Trenches", 104, Rarity.RARE, mage.cards.g.GoblinTrenches.class)); cards.add(new SetCardInfo("Grave Defiler", 40, Rarity.UNCOMMON, mage.cards.g.GraveDefiler.class)); + cards.add(new SetCardInfo("Guided Passage", 105, Rarity.RARE, mage.cards.g.GuidedPassage.class)); cards.add(new SetCardInfo("Haunted Angel", 12, Rarity.UNCOMMON, mage.cards.h.HauntedAngel.class)); cards.add(new SetCardInfo("Helionaut", 13, Rarity.COMMON, mage.cards.h.Helionaut.class)); cards.add(new SetCardInfo("Ice Cave", 24, Rarity.RARE, mage.cards.i.IceCave.class)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/DoUnlessAnyPlayerPaysEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DoUnlessAnyPlayerPaysEffect.java index 15bff459823..b05f8501cf7 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DoUnlessAnyPlayerPaysEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DoUnlessAnyPlayerPaysEffect.java @@ -98,7 +98,6 @@ public class DoUnlessAnyPlayerPaysEffect extends OneShotEffect { game.informPlayers(player.getLogName() + " pays the cost to prevent the effect"); } doEffect = false; - break; } } } From 6a9770030b6e2cc062a35d9ba970e5f2ddcbba5a Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 10:59:02 -0400 Subject: [PATCH 13/35] updated XLN spoiler --- Utils/mtg-cards-data.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index e65553aad7e..bec858c9f85 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -32334,6 +32334,7 @@ Axis of Mortality|Ixalan|3|M|{4}{W}{W}|Enchantment|||At the beginning of your up Bellowing Aegisaur|Ixalan|4|U|{5}{W}|Creature - Dinosaur|3|5|Enrage - Whenever Bellowing Aegisaur is dealt damage, put a +1/+1 counter on each other creature you control.| Bishop of Rebirth|Ixalan|5|R|Creature - Vampire Cleric|3|4|Vigilance$Whenever Bishop of Rebirth attacks, you may return target creature card with converted mana cost 3 or less from your graveyard to the battlefield.| Duskborne Skymarcher|Ixalan|9|U|{W}|Creature - Vampire Cleric|1|1|Flying${W}, {T}: Target attacking vampire gets +1/+1 until end of turn.| +Emissary of Sunrise|Ixalan|10|U|{2}{W}|Creature - Human Cleric|2|1|First strike$When Emissary of Sunrise enters the battlefield, it explores. (Reveal the top card of your library. Put that card into your hand if it's a land. Otherwise, put a +1/+1 counter on this creature, then put the card back or put it into your graveyard.)| Goring Ceratops|Ixalan|13|R|Creature - Dinosaur|3|3|Double strike$Whenever Goring Ceratops attacks, other creatures you control gain double strike until end of turn.| Imperial Lancer|Ixalan|15|U|{W}|Creature - Human Knight|1|1|Imperial Lancer has double strike as long as you control a Dinosaur.| Ixalan's Binding|Ixalan|17|U|{3}{W}|Enchantment|||When Ixalan's Binding enters the battlefield, exile target nonland permanent an opponent controls until Ixalan's Binding leaves the battlefield.$Your opponents can't cast spells with the same name as the exiled card.| @@ -32474,6 +32475,7 @@ Pirate's Cutlass|Ixalan|242|C|{3}|Artifact - Equipment|||When Pirate's Cutlass e Primal Amulet|Ixalan|243a|R|{4}|Artifact|||Instant and sorcery spells you cast cost {1} less to cast.$Whenever you cast an instant or sorcery spell, put a charge counter on Primal Amulet. Then if there are four or more charge counters on it, you may remove those counters and transform it.| Primal Wellspring|Ixalan|243b|R||Land|||Add one mana of any color to your mana pool. When that mana is spent to cast an instant or sorcery spell, copy that spell and you may choose new targets for the copy.| Sentinel Totem|Ixalan|245|U|{1}|Artifact|||When Sentinel Totem enters the battlefield, scry 1.${T}, Exile Sentinel Totem: Exile all cards from all graveyards.| +Shadowed Caravel|Ixalan|246|R|{2}|Artifact - Vehicle|2|2|Whenever a creature you control explores, put a +1/+1 counter on Shadowed Caravel.$Crew 2| Sleek Schooner|Ixalan|247|U|{3}|Artifact - Vehicle|4|3|Crew 1| Sorcerous Spyglass|Ixalan|248|R|{2}|Artifact|||As Sorcerous Spyglass enters the battlefield, look at an opponent's hand, then choose any card name.$Activated abilities of sources with the chosen name can't be activated unless they're mana abilities.| Spires of Orazca|Ixalan|249b|R||Land|||{T}: Add {C} to your mana pool.${T}: Untap target attacking creature an opponent controls and remove it from combat.| @@ -32483,6 +32485,7 @@ Treasure Map|Ixalan|250a|R|{2}|Artifact|||{1}, {T}: Scry 1. Put a landmark count Vanquisher's Banner|Ixalan|251|R|{5}|Artifact|||As Vanquisher's Banner enters the battlefield, choose a creature type.$Creatures you control of the chosen type get +1/+1.$Whenever you cast a creature spell of the chosen type, draw a card.| Dragonskull Summit|Ixalan|252|R||Land|||Dragonskull Summit enters the battlefield tapped unless you control a Swamp or a Mountain.${T}: Add {B} or {R} to your mana pool.| Drowned Catacomb|Ixalan|253|R||Land|||Drowned Catacomb enters the battlefield tapped unless you control an Island or a Swamp.${T}: Add {U} or {B} to your mana pool.| +Field of Ruin|Ixalan|254|U||Land|||{T}: Add {C} to your mana pool.${2}, {T}, Sacrifice Field of Ruin: Destroy target nonbasic land an opponent controls. Each player searches his or her library for a basic land card, puts it onto the battlefield, then shuffles his or her library.| Glacial Fortress|Ixalan|255|R||Land|||Glacial Fortress enters the battlefield tapped unless you control a Plains or an Island.${T}: Add {W} or {U} to your mana pool.| Rootbound Crag|Ixalan|256|R||Land|||Rootbound Crag enters the battlefield tapped unless you control a Mountain or a Forest.${T}: Add {R} or {G} to your mana pool.| Sunpetal Grove|Ixalan|257|R||Land|||Sunpetal Grove enters the battlefield tapped unless you control a Forest or a Plains.${T}: Add {G} or {W} to your mana pool.| From ceaf2bdde771ddb2e0a0be6ef092deb0f2f145c0 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 11:03:57 -0400 Subject: [PATCH 14/35] updated XLN spoiler --- Utils/mtg-cards-data.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index bec858c9f85..9d507cc3890 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -32427,6 +32427,7 @@ Unfriendly Fire|Ixalan|172|C|{4}{R}|Instant|||Unfriendly Fire deals 4 damage to Wily Goblin|Ixalan|174|U|{R}{R}|Creature - Goblin Pirate|1|1|When Wily Goblin enters the battlefield, create a colorless Treasure artifact token with "{T}, Sacrifice this artifact: Add one mana of any color to your mana pool."| Carnage Tyrant|Ixalan|179|M|{4}{G}{G}|Creature - Dinosaur|7|6|Carnage Tyrant can't be countered.$Trample, hexproof| Commune with Dinosaurs|Ixalan|181|C|{G}|Sorcery|||| +Deathgorge Scavenger|Ixalan|184|R|{2}{G}|Creature - Dinosaur|3|2|Whenever Deathgorge Scavenger enters the battlefield or attacks, you may exile target card from a graveyard. If a creature card is exiled this way, you gain 2 life. If a noncreature card is exiled this way, Deathgorge Scavenger gets +1/+1 until end of turn.| Deeproot Champion|Ixalan|185|R|{1}{G}|Creature - Merfolk Shaman|1|1|Whenever you cast a noncreature spell, put a +1/+1 counter on Deeproot Champion.| Drover of the Mighty|Ixalan|187|U|{1}{G}|Creature - Human Druid|1|1|Drover of the Mighty gets +2/+2 as long as you control a Dinosaur.${T}: Add one mana of any color to your mana pool.| Emperor's Vanguard|Ixalan|189|R|{3}{G}|Creature - Human Scout|4|3|Whenever Emperor's Vanguard deals combat damage to a player, it explores.| From dff87b11637a45ffc1fc4dd88dae5a96e054816e Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 11:08:45 -0400 Subject: [PATCH 15/35] Implemented Emissary of Sunrise --- .../src/mage/cards/e/EmissaryOfSunrise.java | 69 +++++++++++++++++++ Mage.Sets/src/mage/sets/Ixalan.java | 1 + 2 files changed, 70 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/e/EmissaryOfSunrise.java diff --git a/Mage.Sets/src/mage/cards/e/EmissaryOfSunrise.java b/Mage.Sets/src/mage/cards/e/EmissaryOfSunrise.java new file mode 100644 index 00000000000..0587f17b366 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EmissaryOfSunrise.java @@ -0,0 +1,69 @@ +/* + * 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.cards.e; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.keyword.ExploreSourceEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author TheElk801 + */ +public class EmissaryOfSunrise extends CardImpl { + + public EmissaryOfSunrise(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.CLERIC); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // First strike + this.addAbility(FirstStrikeAbility.getInstance()); + + // When Emissary of Sunrise enters the battlefield, it explores. + this.addAbility(new EntersBattlefieldTriggeredAbility(new ExploreSourceEffect())); + } + + public EmissaryOfSunrise(final EmissaryOfSunrise card) { + super(card); + } + + @Override + public EmissaryOfSunrise copy() { + return new EmissaryOfSunrise(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Ixalan.java b/Mage.Sets/src/mage/sets/Ixalan.java index 4af16f86595..9db95b74e6d 100644 --- a/Mage.Sets/src/mage/sets/Ixalan.java +++ b/Mage.Sets/src/mage/sets/Ixalan.java @@ -79,6 +79,7 @@ public class Ixalan extends ExpansionSet { cards.add(new SetCardInfo("Duress", 105, Rarity.COMMON, mage.cards.d.Duress.class)); cards.add(new SetCardInfo("Dusk Legion Dreadnought", 236, Rarity.UNCOMMON, mage.cards.d.DuskLegionDreadnought.class)); cards.add(new SetCardInfo("Duskborne Skymarcher", 9, Rarity.UNCOMMON, mage.cards.d.DuskborneSkymarcher.class)); + cards.add(new SetCardInfo("Emissary of Sunrise", 10, Rarity.UNCOMMON, mage.cards.e.EmissaryOfSunrise.class)); cards.add(new SetCardInfo("Emperor's Vanguard", 189, Rarity.RARE, mage.cards.e.EmperorsVanguard.class)); cards.add(new SetCardInfo("Entrancing Melody", 55, Rarity.RARE, mage.cards.e.EntrancingMelody.class)); cards.add(new SetCardInfo("Fathom Fleet Captain", 106, Rarity.RARE, mage.cards.f.FathomFleetCaptain.class)); From 68a42726a88a0fa4cca1ffe42850632c72689202 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 11:19:29 -0400 Subject: [PATCH 16/35] Implemented Shadowed Caravel, generalized explore triggers --- .../src/mage/cards/l/LurkingChupacabra.java | 46 +----------- .../src/mage/cards/s/ShadowedCaravel.java | 74 +++++++++++++++++++ .../src/mage/cards/w/WildgrowthWalker.java | 45 +---------- Mage.Sets/src/mage/sets/Ixalan.java | 1 + .../CreatureExploresTriggeredAbility.java | 43 +++++++++++ 5 files changed, 124 insertions(+), 85 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/s/ShadowedCaravel.java create mode 100644 Mage/src/main/java/mage/abilities/effects/common/CreatureExploresTriggeredAbility.java diff --git a/Mage.Sets/src/mage/cards/l/LurkingChupacabra.java b/Mage.Sets/src/mage/cards/l/LurkingChupacabra.java index 6c011ea8f05..7f607f32f94 100644 --- a/Mage.Sets/src/mage/cards/l/LurkingChupacabra.java +++ b/Mage.Sets/src/mage/cards/l/LurkingChupacabra.java @@ -30,8 +30,7 @@ package mage.cards.l; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CreatureExploresTriggeredAbility; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.constants.SubType; import mage.cards.CardImpl; @@ -39,12 +38,8 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.TargetController; -import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerPredicate; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; /** @@ -53,7 +48,7 @@ import mage.target.common.TargetCreaturePermanent; */ public class LurkingChupacabra extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature an opponent controls"); static { filter.add(new ControllerPredicate(TargetController.OPPONENT)); @@ -68,7 +63,7 @@ public class LurkingChupacabra extends CardImpl { this.toughness = new MageInt(3); // Whenever a creature you control explores, target creature an opponent controls gets -2/-2 until end of turn - Ability ability = new LurkingChupacabraTriggeredAbility(new BoostTargetEffect(-2, -2, Duration.EndOfTurn)); + Ability ability = new CreatureExploresTriggeredAbility(new BoostTargetEffect(-2, -2, Duration.EndOfTurn)); ability.addTarget(new TargetCreaturePermanent(filter)); } @@ -81,38 +76,3 @@ public class LurkingChupacabra extends CardImpl { return new LurkingChupacabra(this); } } - -class LurkingChupacabraTriggeredAbility extends TriggeredAbilityImpl { - - LurkingChupacabraTriggeredAbility(Effect effect) { - super(Zone.BATTLEFIELD, effect, false); - } - - LurkingChupacabraTriggeredAbility(final LurkingChupacabraTriggeredAbility effect) { - super(effect); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.EXPLORED; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - Permanent creature = game.getPermanentOrLKIBattlefield(event.getSourceId()); - if (creature != null) { - return creature.getControllerId().equals(controllerId); - } - return false; - } - - @Override - public LurkingChupacabraTriggeredAbility copy() { - return new LurkingChupacabraTriggeredAbility(this); - } - - @Override - public String getRule() { - return "Whenever a creature you control explores, target creature an opponent controls gets -2/-2 until end of turn"; - } -} diff --git a/Mage.Sets/src/mage/cards/s/ShadowedCaravel.java b/Mage.Sets/src/mage/cards/s/ShadowedCaravel.java new file mode 100644 index 00000000000..ab340946d07 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ShadowedCaravel.java @@ -0,0 +1,74 @@ +/* + * 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.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CreatureExploresTriggeredAbility; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.constants.SubType; +import mage.abilities.keyword.CrewAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.counters.CounterType; + +/** + * + * @author TheElk801 + */ +public class ShadowedCaravel extends CardImpl { + + public ShadowedCaravel(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); + + this.subtype.add(SubType.VEHICLE); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Whenever a creature you control explores, put a +1/+1 counter on Shadowed Caravel. + Effect effect = new AddCountersSourceEffect(CounterType.P1P1.createInstance()); + Ability ability = new CreatureExploresTriggeredAbility(effect); + this.addAbility(ability); + + // Crew 2 + this.addAbility(new CrewAbility(2)); + + } + + public ShadowedCaravel(final ShadowedCaravel card) { + super(card); + } + + @Override + public ShadowedCaravel copy() { + return new ShadowedCaravel(this); + } +} diff --git a/Mage.Sets/src/mage/cards/w/WildgrowthWalker.java b/Mage.Sets/src/mage/cards/w/WildgrowthWalker.java index 8066b2dad33..7830ef9d03b 100644 --- a/Mage.Sets/src/mage/cards/w/WildgrowthWalker.java +++ b/Mage.Sets/src/mage/cards/w/WildgrowthWalker.java @@ -30,20 +30,15 @@ package mage.cards.w; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CreatureExploresTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.counters.CounterType; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; -import mage.game.permanent.Permanent; /** * @@ -60,8 +55,9 @@ public class WildgrowthWalker extends CardImpl { // Whenever a creature you control explores, put a +1/+1 counter on Wildgrowth Walker and you gain 3 life. Effect effect = new AddCountersSourceEffect(CounterType.P1P1.createInstance()); - Ability ability = new WildgrowthWalkerTriggeredAbility(effect); + Ability ability = new CreatureExploresTriggeredAbility(effect); effect = new GainLifeEffect(3); + effect.setText("and you gain 3 life"); ability.addEffect(effect); this.addAbility(ability); } @@ -75,38 +71,3 @@ public class WildgrowthWalker extends CardImpl { return new WildgrowthWalker(this); } } - -class WildgrowthWalkerTriggeredAbility extends TriggeredAbilityImpl { - - WildgrowthWalkerTriggeredAbility(Effect effect) { - super(Zone.BATTLEFIELD, effect, false); - } - - WildgrowthWalkerTriggeredAbility(final WildgrowthWalkerTriggeredAbility effect) { - super(effect); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == EventType.EXPLORED; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - Permanent creature = game.getPermanentOrLKIBattlefield(event.getSourceId()); - if (creature != null) { - return creature.getControllerId().equals(controllerId); - } - return false; - } - - @Override - public WildgrowthWalkerTriggeredAbility copy() { - return new WildgrowthWalkerTriggeredAbility(this); - } - - @Override - public String getRule() { - return "Whenever a creature you control explores, put a +1/+1 counter on {this} and you gain 3 life"; - } -} diff --git a/Mage.Sets/src/mage/sets/Ixalan.java b/Mage.Sets/src/mage/sets/Ixalan.java index 9db95b74e6d..751beb6597f 100644 --- a/Mage.Sets/src/mage/sets/Ixalan.java +++ b/Mage.Sets/src/mage/sets/Ixalan.java @@ -169,6 +169,7 @@ public class Ixalan extends ExpansionSet { cards.add(new SetCardInfo("Search for Azcanta", 74, Rarity.RARE, mage.cards.s.SearchForAzcanta.class)); cards.add(new SetCardInfo("Sentinel Totem", 245, Rarity.UNCOMMON, mage.cards.s.SentinelTotem.class)); cards.add(new SetCardInfo("Settle the Wreckage", 34, Rarity.RARE, mage.cards.s.SettleTheWreckage.class)); + cards.add(new SetCardInfo("Shadowed Caravel", 246, Rarity.RARE, mage.cards.s.ShadowedCaravel.class)); cards.add(new SetCardInfo("Shapers of Nature", 228, Rarity.UNCOMMON, mage.cards.s.ShapersOfNature.class)); cards.add(new SetCardInfo("Shapers' Sanctuary", 206, Rarity.RARE, mage.cards.s.ShapersSanctuary.class)); cards.add(new SetCardInfo("Siren Stormtamer", 79, Rarity.UNCOMMON, mage.cards.s.SirenStormtamer.class)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/CreatureExploresTriggeredAbility.java b/Mage/src/main/java/mage/abilities/effects/common/CreatureExploresTriggeredAbility.java new file mode 100644 index 00000000000..e78b559cc46 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/CreatureExploresTriggeredAbility.java @@ -0,0 +1,43 @@ +package mage.abilities.effects.common; + +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; + +public class CreatureExploresTriggeredAbility extends TriggeredAbilityImpl { + + public CreatureExploresTriggeredAbility(Effect effect) { + super(Zone.BATTLEFIELD, effect, false); + } + + public CreatureExploresTriggeredAbility(final CreatureExploresTriggeredAbility effect) { + super(effect); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.EXPLORED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Permanent creature = game.getPermanentOrLKIBattlefield(event.getSourceId()); + if (creature != null) { + return creature.getControllerId().equals(controllerId); + } + return false; + } + + @Override + public CreatureExploresTriggeredAbility copy() { + return new CreatureExploresTriggeredAbility(this); + } + + @Override + public String getRule() { + return "Whenever a creature you control explores, " + super.getRule(); + } +} From 73a8d64d5c58fd375ebfa7b52cecf741235a416e Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 13:36:17 -0400 Subject: [PATCH 17/35] fixed Thraben Sentry --- Mage.Sets/src/mage/cards/t/ThrabenSentry.java | 13 +++---------- Mage.Sets/src/mage/sets/Ixalan.java | 1 + .../common/DiesCreatureTriggeredAbility.java | 11 ++++++----- Mage/src/main/java/mage/filter/StaticFilters.java | 2 +- .../common/FilterControlledCreaturePermanent.java | 10 ++++++---- 5 files changed, 17 insertions(+), 20 deletions(-) diff --git a/Mage.Sets/src/mage/cards/t/ThrabenSentry.java b/Mage.Sets/src/mage/cards/t/ThrabenSentry.java index 335871c0318..cf553d55043 100644 --- a/Mage.Sets/src/mage/cards/t/ThrabenSentry.java +++ b/Mage.Sets/src/mage/cards/t/ThrabenSentry.java @@ -37,22 +37,15 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.AnotherPredicate; +import mage.filter.common.FilterControlledCreaturePermanent; /** * @author nantuko */ public class ThrabenSentry extends CardImpl { - - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); - - static { - filter.add(new AnotherPredicate()); - } public ThrabenSentry(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.SOLDIER); @@ -66,7 +59,7 @@ public class ThrabenSentry extends CardImpl { // Whenever another creature you control dies, you may transform Thraben Sentry. this.addAbility(new TransformAbility()); - this.addAbility(new DiesCreatureTriggeredAbility(new TransformSourceEffect(true), true, filter)); + this.addAbility(new DiesCreatureTriggeredAbility(new TransformSourceEffect(true), true, new FilterControlledCreaturePermanent())); } public ThrabenSentry(final ThrabenSentry card) { diff --git a/Mage.Sets/src/mage/sets/Ixalan.java b/Mage.Sets/src/mage/sets/Ixalan.java index 751beb6597f..623026e62d0 100644 --- a/Mage.Sets/src/mage/sets/Ixalan.java +++ b/Mage.Sets/src/mage/sets/Ixalan.java @@ -155,6 +155,7 @@ public class Ixalan extends ExpansionSet { cards.add(new SetCardInfo("Ravenous Daggertooth", 202, Rarity.COMMON, mage.cards.r.RavenousDaggertooth.class)); cards.add(new SetCardInfo("Regisaur Alpha", 227, Rarity.RARE, mage.cards.r.RegisaurAlpha.class)); cards.add(new SetCardInfo("Revel in Riches", 117, Rarity.RARE, mage.cards.r.RevelInRiches.class)); + cards.add(new SetCardInfo("Rigging Runner", 157, Rarity.UNCOMMON, mage.cards.r.RiggingRunner.class)); cards.add(new SetCardInfo("Rile", 158, Rarity.COMMON, mage.cards.r.Rile.class)); cards.add(new SetCardInfo("Ripjaw Raptor", 203, Rarity.RARE, mage.cards.r.RipjawRaptor.class)); cards.add(new SetCardInfo("River Sneak", 70, Rarity.UNCOMMON, mage.cards.r.RiverSneak.class)); diff --git a/Mage/src/main/java/mage/abilities/common/DiesCreatureTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/DiesCreatureTriggeredAbility.java index 6e160f70208..671945e5f95 100644 --- a/Mage/src/main/java/mage/abilities/common/DiesCreatureTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/DiesCreatureTriggeredAbility.java @@ -3,6 +3,7 @@ package mage.abilities.common; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; import mage.constants.Zone; +import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.AnotherPredicate; import mage.game.Game; @@ -15,7 +16,7 @@ import mage.target.targetpointer.FixedTarget; */ public class DiesCreatureTriggeredAbility extends TriggeredAbilityImpl { - protected FilterCreaturePermanent filter; + protected FilterPermanent filter; private boolean setTargetPointer; public DiesCreatureTriggeredAbility(Effect effect, boolean optional) { @@ -34,15 +35,15 @@ public class DiesCreatureTriggeredAbility extends TriggeredAbilityImpl { this.setTargetPointer = setTargetPointer; } - public DiesCreatureTriggeredAbility(Effect effect, boolean optional, FilterCreaturePermanent filter) { + public DiesCreatureTriggeredAbility(Effect effect, boolean optional, FilterPermanent filter) { this(effect, optional, filter, false); } - public DiesCreatureTriggeredAbility(Effect effect, boolean optional, FilterCreaturePermanent filter, boolean setTargetPointer) { + public DiesCreatureTriggeredAbility(Effect effect, boolean optional, FilterPermanent filter, boolean setTargetPointer) { this(Zone.BATTLEFIELD, effect, optional, filter, setTargetPointer); } - public DiesCreatureTriggeredAbility(Zone zone, Effect effect, boolean optional, FilterCreaturePermanent filter, boolean setTargetPointer) { + public DiesCreatureTriggeredAbility(Zone zone, Effect effect, boolean optional, FilterPermanent filter, boolean setTargetPointer) { super(zone, effect, optional); this.filter = filter; this.setTargetPointer = setTargetPointer; @@ -68,7 +69,7 @@ public class DiesCreatureTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { ZoneChangeEvent zEvent = (ZoneChangeEvent) event; if (zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getToZone() == Zone.GRAVEYARD) { - if (filter.match(zEvent.getTarget(), sourceId, controllerId, game)) { + if (filter.match(zEvent.getTarget(), sourceId, controllerId, game) && zEvent.getTarget().isCreature()) { if (setTargetPointer) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(event.getTargetId())); diff --git a/Mage/src/main/java/mage/filter/StaticFilters.java b/Mage/src/main/java/mage/filter/StaticFilters.java index 620c7582d53..05a02cc4881 100644 --- a/Mage/src/main/java/mage/filter/StaticFilters.java +++ b/Mage/src/main/java/mage/filter/StaticFilters.java @@ -41,7 +41,7 @@ public final class StaticFilters { public static final FilterControlledPermanent FILTER_CONTROLLED_PERMANENT_ARTIFACT = new FilterControlledArtifactPermanent(); public static final FilterControlledPermanent FILTER_CONTROLLED_PERMANENT_ARTIFACT_OR_CREATURE = new FilterControlledPermanent("artifact or creature you control"); - public static final FilterControlledPermanent FILTER_CONTROLLED_A_CREATURE = new FilterControlledCreaturePermanent("a creature you control"); + public static final FilterPermanent FILTER_CONTROLLED_A_CREATURE = new FilterControlledCreaturePermanent("a creature you control"); public static final FilterControlledCreaturePermanent FILTER_CONTROLLED_ANOTHER_CREATURE = new FilterControlledCreaturePermanent("another creature"); public static final FilterControlledPermanent FILTER_CONTROLLED_PERMANENT_NON_LAND = new FilterControlledPermanent("nonland permanent"); public static final FilterLandPermanent FILTER_LAND = new FilterLandPermanent(); diff --git a/Mage/src/main/java/mage/filter/common/FilterControlledCreaturePermanent.java b/Mage/src/main/java/mage/filter/common/FilterControlledCreaturePermanent.java index f8fcd1a77c6..a10d4b7b735 100644 --- a/Mage/src/main/java/mage/filter/common/FilterControlledCreaturePermanent.java +++ b/Mage/src/main/java/mage/filter/common/FilterControlledCreaturePermanent.java @@ -25,19 +25,21 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.filter.common; import mage.constants.CardType; import mage.constants.SubType; +import mage.constants.TargetController; +import mage.filter.FilterPermanent; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.ControllerPredicate; /** * * @author BetaSteward_at_googlemail.com */ -public class FilterControlledCreaturePermanent extends FilterControlledPermanent { +public class FilterControlledCreaturePermanent extends FilterPermanent { public FilterControlledCreaturePermanent() { this("creature you control"); @@ -46,8 +48,8 @@ public class FilterControlledCreaturePermanent extends FilterControlledPermanent public FilterControlledCreaturePermanent(String name) { super(name); this.add(new CardTypePredicate(CardType.CREATURE)); - } - + this.add(new ControllerPredicate(TargetController.YOU)); + } public FilterControlledCreaturePermanent(SubType subtype, String name) { super(name); From 4f4950b7ed6c6c231c1b5e010fc2764cb163cae2 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 13:52:58 -0400 Subject: [PATCH 18/35] Implemented Perilous Voyage --- .../src/mage/cards/p/PerilousVoyage.java | 107 ++++++++++++++++++ Mage.Sets/src/mage/sets/Ixalan.java | 1 + Utils/mtg-cards-data.txt | 1 + 3 files changed, 109 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/p/PerilousVoyage.java diff --git a/Mage.Sets/src/mage/cards/p/PerilousVoyage.java b/Mage.Sets/src/mage/cards/p/PerilousVoyage.java new file mode 100644 index 00000000000..78313865e15 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PerilousVoyage.java @@ -0,0 +1,107 @@ +/* + * 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.cards.p; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterNonlandPermanent; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; + +/** + * + * @author TheElk801 + */ +public class PerilousVoyage extends CardImpl { + + private static final FilterNonlandPermanent filter = new FilterNonlandPermanent("nonland permanent you don't control"); + + static { + filter.add(new ControllerPredicate(TargetController.NOT_YOU)); + } + + public PerilousVoyage(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}"); + + // Return target nonland permanent you don't control to its owner's hand. If its converted mana cost was 2 or less, scry 2. + this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()); + this.getSpellAbility().addEffect(new PerilousVoyageEffect()); + this.getSpellAbility().addTarget(new TargetPermanent()); + } + + public PerilousVoyage(final PerilousVoyage card) { + super(card); + } + + @Override + public PerilousVoyage copy() { + return new PerilousVoyage(this); + } +} + +class PerilousVoyageEffect extends OneShotEffect { + + PerilousVoyageEffect() { + super(Outcome.Benefit); + this.staticText = "Return target nonland permanent you don't control to its owner's hand. If its converted mana cost was 2 or less, scry 2"; + } + + PerilousVoyageEffect(final PerilousVoyageEffect effect) { + super(effect); + } + + @Override + public PerilousVoyageEffect copy() { + return new PerilousVoyageEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(source.getFirstTarget()); + if (permanent != null) { + boolean isLittle = permanent.getConvertedManaCost() < 3; + permanent.moveToZone(Zone.HAND, source.getSourceId(), game, true); + if (isLittle && player != null) { + player.scry(2, source, game); + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/Ixalan.java b/Mage.Sets/src/mage/sets/Ixalan.java index 623026e62d0..fdd7c295241 100644 --- a/Mage.Sets/src/mage/sets/Ixalan.java +++ b/Mage.Sets/src/mage/sets/Ixalan.java @@ -136,6 +136,7 @@ public class Ixalan extends ExpansionSet { cards.add(new SetCardInfo("Opt", 65, Rarity.COMMON, mage.cards.o.Opt.class)); cards.add(new SetCardInfo("Otepec Huntmaster", 153, Rarity.UNCOMMON, mage.cards.o.OtepecHuntmaster.class)); cards.add(new SetCardInfo("Overflowing Insight", 64, Rarity.MYTHIC, mage.cards.o.OverflowingInsight.class)); + cards.add(new SetCardInfo("Perilous Voyage", 67, Rarity.UNCOMMON, mage.cards.p.PerilousVoyage.class)); cards.add(new SetCardInfo("Pillar of Origins", 241, Rarity.UNCOMMON, mage.cards.p.PillarOfOrigins.class)); cards.add(new SetCardInfo("Pirate's Cutlass", 242, Rarity.COMMON, mage.cards.p.PiratesCutlass.class)); cards.add(new SetCardInfo("Plains", 260, Rarity.LAND, mage.cards.basiclands.Plains.class)); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 9d507cc3890..dac7f4d4aba 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -32364,6 +32364,7 @@ Kopala, Warden of Waves|Ixalan|61|R|{1}{U}{U}|Legendary Creature - Merfolk Wizar Lookout's Dispersal|Ixalan|62|U|{2}{U}|Instant|||Lookout's Dispersal costs {1} less to cast if you control a Pirate.$Counter target spell unless its controller pays {4}.| Overflowing Insight|Ixalan|64|M|{4}{U}{U}{U}|Sorcery|||Target player draws seven cards.| Opt|Ixalan|65|C|{U}|Instant|||Scry 1.$Draw a card.| +Perilous Voyage|Ixalan|67|U|{1}{U}|Instant|||Return target nonland permanent you don't control to its owner's hand. If its converted mana cost was 2 or less, scry 2.| Prosperous Pirates|Ixalan|69|C|{4}{U}|Creature - Human Pirate|3|4|When Prosperous Pirates enters the battlefield, create two colorless Treasure artifact tokens with "{T}, Sacrifice this artifact: Add one mana of any color to your mana pool."| River Sneak|Ixalan|70|U|{1}{U}|Creature - Merfolk Warrior|1|1|River Sneak can't be blocked.$Whenever another Merfolk enters the battlefield under your control, River sneak gets +1/+1 until end of turn.| River's Rebuke|Ixalan|71|R|{4}{U}{U}|Sorcery|||Return all nonland permanents target player controls to their owner's hand.| From 9fa7729133779a89c6e5324f5eccf771ee46ba2e Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 13:55:00 -0400 Subject: [PATCH 19/35] Implemented Perilous Voyage --- Mage.Sets/src/mage/cards/p/PerilousVoyage.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Mage.Sets/src/mage/cards/p/PerilousVoyage.java b/Mage.Sets/src/mage/cards/p/PerilousVoyage.java index 78313865e15..a20473e1ada 100644 --- a/Mage.Sets/src/mage/cards/p/PerilousVoyage.java +++ b/Mage.Sets/src/mage/cards/p/PerilousVoyage.java @@ -30,7 +30,6 @@ package mage.cards.p; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -60,9 +59,8 @@ public class PerilousVoyage extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}"); // Return target nonland permanent you don't control to its owner's hand. If its converted mana cost was 2 or less, scry 2. - this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()); this.getSpellAbility().addEffect(new PerilousVoyageEffect()); - this.getSpellAbility().addTarget(new TargetPermanent()); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } public PerilousVoyage(final PerilousVoyage card) { From ec9a198d0a4efb9b3c9d9efd5eee71f84a7b5632 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 14:20:20 -0400 Subject: [PATCH 20/35] Implemented Deathgorge Scavenger --- .../src/mage/cards/d/DeathgorgeScavenger.java | 109 ++++++++++++++++++ Mage.Sets/src/mage/sets/Ixalan.java | 1 + 2 files changed, 110 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/d/DeathgorgeScavenger.java diff --git a/Mage.Sets/src/mage/cards/d/DeathgorgeScavenger.java b/Mage.Sets/src/mage/cards/d/DeathgorgeScavenger.java new file mode 100644 index 00000000000..13b6ae13b3f --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DeathgorgeScavenger.java @@ -0,0 +1,109 @@ +/* + * 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.cards.d; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.cards.Card; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInGraveyard; + +/** + * + * @author TheElk801 + */ +public class DeathgorgeScavenger extends CardImpl { + + public DeathgorgeScavenger(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); + + this.subtype.add(SubType.DINOSAUR); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Whenever Deathgorge Scavenger enters the battlefield or attacks, you may exile target card from a graveyard. If a creature card is exiled this way, you gain 2 life. If a noncreature card is exiled this way, Deathgorge Scavenger gets +1/+1 until end of turn. + Ability ability = new EntersBattlefieldOrAttacksSourceTriggeredAbility(new DeathgorgeScavengerEffect(), true); + ability.addTarget(new TargetCardInGraveyard()); + this.addAbility(ability); + } + + public DeathgorgeScavenger(final DeathgorgeScavenger card) { + super(card); + } + + @Override + public DeathgorgeScavenger copy() { + return new DeathgorgeScavenger(this); + } +} + +class DeathgorgeScavengerEffect extends OneShotEffect { + + public DeathgorgeScavengerEffect() { + super(Outcome.Benefit); + this.staticText = "exile target card from a graveyard. If a creature card is exiled this way, you gain 2 life. If a noncreature card is exiled this way, {this} gets +1/+1 until end of turn"; + } + + public DeathgorgeScavengerEffect(final DeathgorgeScavengerEffect effect) { + super(effect); + } + + @Override + public DeathgorgeScavengerEffect copy() { + return new DeathgorgeScavengerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Card card = game.getCard(getTargetPointer().getFirst(game, source)); + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null && card != null) { + controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, Zone.GRAVEYARD, true); + if (card.isCreature()) { + controller.gainLife(2, game); + } else { + new BoostSourceEffect(1, 1, Duration.EndOfTurn).apply(game, source); + } + return true; + } + return false; + } + +} diff --git a/Mage.Sets/src/mage/sets/Ixalan.java b/Mage.Sets/src/mage/sets/Ixalan.java index fdd7c295241..9ca5f5b349c 100644 --- a/Mage.Sets/src/mage/sets/Ixalan.java +++ b/Mage.Sets/src/mage/sets/Ixalan.java @@ -63,6 +63,7 @@ public class Ixalan extends ExpansionSet { cards.add(new SetCardInfo("Deadeye Quartermaster", 50, Rarity.UNCOMMON, mage.cards.d.DeadeyeQuartermaster.class)); cards.add(new SetCardInfo("Deadeye Tormentor", 98, Rarity.COMMON, mage.cards.d.DeadeyeTormentor.class)); cards.add(new SetCardInfo("Deadeye Tracker", 99, Rarity.RARE, mage.cards.d.DeadeyeTracker.class)); + cards.add(new SetCardInfo("Deathgorge Scavenger", 184, Rarity.RARE, mage.cards.d.DeathgorgeScavenger.class)); cards.add(new SetCardInfo("Deathless Ancient", 100, Rarity.UNCOMMON, mage.cards.d.DeathlessAncient.class)); cards.add(new SetCardInfo("Deeproot Champion", 185, Rarity.RARE, mage.cards.d.DeeprootChampion.class)); cards.add(new SetCardInfo("Deeproot Waters", 51, Rarity.UNCOMMON, mage.cards.d.DeeprootWaters.class)); From 1cdc8d31778b65f7f039dbda8c746d7e4587569f Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 14:47:07 -0400 Subject: [PATCH 21/35] Implemented Field of Ruin --- Mage.Sets/src/mage/cards/f/FieldOfRuin.java | 134 ++++++++++++++++++++ Mage.Sets/src/mage/sets/Ixalan.java | 1 + Utils/mtg-cards-data.txt | 1 + 3 files changed, 136 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/f/FieldOfRuin.java diff --git a/Mage.Sets/src/mage/cards/f/FieldOfRuin.java b/Mage.Sets/src/mage/cards/f/FieldOfRuin.java new file mode 100644 index 00000000000..45e3c514be3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FieldOfRuin.java @@ -0,0 +1,134 @@ +/* + * 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.cards.f; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SuperType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.StaticFilters; +import mage.filter.common.FilterLandPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.SupertypePredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInLibrary; +import mage.target.common.TargetLandPermanent; + +/** + * + * @author TheElk801 + */ +public class FieldOfRuin extends CardImpl { + + private static final FilterLandPermanent filter = new FilterLandPermanent("nonbasic land an opponent controls"); + + static { + filter.add(new ControllerPredicate(TargetController.OPPONENT)); + filter.add(Predicates.not(new SupertypePredicate(SuperType.BASIC))); + } + + public FieldOfRuin(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // {T}: Add {C} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + + // {2}, {T}, Sacrifice Field of Ruin: Destroy target nonbasic land an opponent controls. Each player searches his or her library for a basic land card, puts it onto the battlefield, then shuffles his or her library. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new TapSourceCost()); + ability.addCost(new ManaCostsImpl("{2}")); + ability.addCost(new SacrificeSourceCost()); + ability.addEffect(new FieldOfRuinEffect()); + ability.addTarget(new TargetLandPermanent(filter)); + } + + public FieldOfRuin(final FieldOfRuin card) { + super(card); + } + + @Override + public FieldOfRuin copy() { + return new FieldOfRuin(this); + } +} + +class FieldOfRuinEffect extends OneShotEffect { + + FieldOfRuinEffect() { + super(Outcome.Benefit); + this.staticText = "Each player searches his or her library for a basic land card, puts it onto the battlefield, then shuffles his or her library."; + } + + FieldOfRuinEffect(final FieldOfRuinEffect effect) { + super(effect); + } + + @Override + public FieldOfRuinEffect copy() { + return new FieldOfRuinEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + TargetCardInLibrary target = new TargetCardInLibrary(0, 1, StaticFilters.FILTER_BASIC_LAND_CARD); + if (player.searchLibrary(target, game)) { + for (UUID cardId : target.getTargets()) { + Card card = player.getLibrary().getCard(cardId, game); + if (card != null) { + card.putOntoBattlefield(game, Zone.LIBRARY, source.getSourceId(), player.getId(), true); + } + + } + player.shuffleLibrary(source, game); + } + } + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/Ixalan.java b/Mage.Sets/src/mage/sets/Ixalan.java index 9ca5f5b349c..fd1e610dd85 100644 --- a/Mage.Sets/src/mage/sets/Ixalan.java +++ b/Mage.Sets/src/mage/sets/Ixalan.java @@ -86,6 +86,7 @@ public class Ixalan extends ExpansionSet { cards.add(new SetCardInfo("Fathom Fleet Captain", 106, Rarity.RARE, mage.cards.f.FathomFleetCaptain.class)); cards.add(new SetCardInfo("Favorable Winds", 56, Rarity.UNCOMMON, mage.cards.f.FavorableWinds.class)); cards.add(new SetCardInfo("Fell Flagship", 238, Rarity.RARE, mage.cards.f.FellFlagship.class)); + cards.add(new SetCardInfo("Field of Ruin", 254, Rarity.UNCOMMON, mage.cards.f.FieldOfRuin.class)); cards.add(new SetCardInfo("Forest", 276, Rarity.LAND, mage.cards.basiclands.Forest.class)); cards.add(new SetCardInfo("Forest", 277, Rarity.LAND, mage.cards.basiclands.Forest.class)); cards.add(new SetCardInfo("Forest", 278, Rarity.LAND, mage.cards.basiclands.Forest.class)); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index dac7f4d4aba..b375b744a08 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -32372,6 +32372,7 @@ Azcanta, The Sunken Ruin|Ixalan|74b|R||Legendary Land|||(Transforms from Search Search for Azcanta|Ixalan|74a|R|{1}{U}|Legendary Enchantment|||| Siren Stormtamer|Ixalan|79|U|{U}|Creature - Siren Pirate Wizard|1|1|Flying${U}, Sacrifice Siren Stormtamer: Counter target spell or ability that targets you or a creature you control.| Spell Pierce|Ixalan|81|C|{U}|Instant|||Counter target noncreature spell unless its controller pays {2}.| +Spell Swindle|Ixalan|82|R|{3}{U}{U}|Instant|||Counter target spell. Create X colorless Treasure artifact tokens, where X is that spell's converted mana cost. They have "T, Sacrifice this artifact: Add one mana of any color to your mana pool."| Storm Fleet Aerialist|Ixalan|83|U|{1}{U}|Creature - Human Pirate|1|2|Flying$Raid - Storm Fleet Aerialist enters the battlefield with a +1/+1 counter on it if you attacked with a creature this turn.| Storm Fleet Spy|Ixalan|84|U|{2}{U}|Creature - Human Pirate|2|2|Raid - When Storm Fleet Spy enters the battlefield, if you attacked with a creature this turn, draw a card.| Arguel's Blood Fast|Ixalan|90a|R|{1}{B}|Legendary Enchantment|||{1}{B}, Pay 2 life: Draw a card.$At the beginning of your upkeep, if you have 5 or less life, you may transform Arguel's Blood Fast.| From 75ce112a5df025fe6769b2ba5cc06657464ffb73 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 14:54:42 -0400 Subject: [PATCH 22/35] Implemented Spell Swindle --- Mage.Sets/src/mage/cards/s/SpellSwindle.java | 93 ++++++++++++++++++++ Mage.Sets/src/mage/sets/Ixalan.java | 1 + 2 files changed, 94 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/SpellSwindle.java diff --git a/Mage.Sets/src/mage/cards/s/SpellSwindle.java b/Mage.Sets/src/mage/cards/s/SpellSwindle.java new file mode 100644 index 00000000000..6745cc8009a --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SpellSwindle.java @@ -0,0 +1,93 @@ +/* + * 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.cards.s; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.permanent.token.TreasureToken; +import mage.game.stack.StackObject; +import mage.target.TargetSpell; + +/** + * + * @author TheElk801 + */ +public class SpellSwindle extends CardImpl { + + public SpellSwindle(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{U}{U}"); + + // Counter target spell. Create X colorless Treasure artifact tokens, where X is that spell's converted mana cost. They have "T, Sacrifice this artifact: Add one mana of any color to your mana pool." + this.getSpellAbility().addTarget(new TargetSpell()); + this.getSpellAbility().addEffect(new SpellSwindleEffect()); + } + + public SpellSwindle(final SpellSwindle card) { + super(card); + } + + @Override + public SpellSwindle copy() { + return new SpellSwindle(this); + } +} + +class SpellSwindleEffect extends OneShotEffect { + + public SpellSwindleEffect() { + super(Outcome.Detriment); + staticText = "Counter target spell. Create X colorless Treasure artifact tokens, where X is that spell's converted mana cost. " + + "They have \"{T}, Sacrifice this artifact: Add one mana of any color to your mana pool"; + } + + public SpellSwindleEffect(final SpellSwindleEffect effect) { + super(effect); + } + + @Override + public SpellSwindleEffect copy() { + return new SpellSwindleEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + StackObject stackObject = game.getStack().getStackObject(targetPointer.getFirst(game, source)); + if (stackObject != null) { + game.getStack().counter(source.getFirstTarget(), source.getSourceId(), game); + return new CreateTokenEffect(new TreasureToken(), stackObject.getConvertedManaCost()).apply(game, source); + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/Ixalan.java b/Mage.Sets/src/mage/sets/Ixalan.java index fd1e610dd85..9395a410cd8 100644 --- a/Mage.Sets/src/mage/sets/Ixalan.java +++ b/Mage.Sets/src/mage/sets/Ixalan.java @@ -185,6 +185,7 @@ public class Ixalan extends ExpansionSet { cards.add(new SetCardInfo("Snapping Sailback", 208, Rarity.UNCOMMON, mage.cards.s.SnappingSailback.class)); cards.add(new SetCardInfo("Sorcerous Spyglass", 248, Rarity.RARE, mage.cards.s.SorcerousSpyglass.class)); cards.add(new SetCardInfo("Spell Pierce", 81, Rarity.RARE, mage.cards.s.SpellPierce.class)); + cards.add(new SetCardInfo("Spell Swindle", 82, Rarity.RARE, mage.cards.s.SpellSwindle.class)); cards.add(new SetCardInfo("Spires of Orazca", 249, Rarity.RARE, mage.cards.s.SpiresOfOrazca.class)); cards.add(new SetCardInfo("Star of Extinction", 161, Rarity.MYTHIC, mage.cards.s.StarOfExtinction.class)); cards.add(new SetCardInfo("Stone Quarry", 289, Rarity.COMMON, mage.cards.s.StoneQuarry.class)); From 90cd60150d0acaed148f9e9b33bd201876a3e673 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 17:11:37 -0400 Subject: [PATCH 23/35] Implemented Vineshaper Mystic --- .../src/mage/cards/v/VineshaperMystic.java | 84 +++++++++++++++++++ Mage.Sets/src/mage/sets/Ixalan.java | 1 + Utils/mtg-cards-data.txt | 3 + 3 files changed, 88 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/v/VineshaperMystic.java diff --git a/Mage.Sets/src/mage/cards/v/VineshaperMystic.java b/Mage.Sets/src/mage/cards/v/VineshaperMystic.java new file mode 100644 index 00000000000..28471aa8fce --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VineshaperMystic.java @@ -0,0 +1,84 @@ +/* + * 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.cards.v; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.target.TargetPermanent; + +/** + * + * @author TheElk801 + */ +public class VineshaperMystic extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("Merfolk you control"); + + static { + filter.add(new SubtypePredicate(SubType.MERFOLK)); + filter.add(new ControllerPredicate(TargetController.YOU)); + } + + public VineshaperMystic(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); + + this.subtype.add(SubType.MERFOLK); + this.subtype.add(SubType.SHAMAN); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // When Vineshaper Mystic enters the battlefield, put a +1/+1 counter on each of up to two target Merfolk you control. + Effect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance()); + effect.setText("put a +1/+1 counter on each of up to two target Merfolk you control"); + Ability ability = new EntersBattlefieldTriggeredAbility(effect, false); + ability.addTarget(new TargetPermanent(0, 2, filter, false)); + this.addAbility(ability); + } + + public VineshaperMystic(final VineshaperMystic card) { + super(card); + } + + @Override + public VineshaperMystic copy() { + return new VineshaperMystic(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Ixalan.java b/Mage.Sets/src/mage/sets/Ixalan.java index 9395a410cd8..752e9defbd1 100644 --- a/Mage.Sets/src/mage/sets/Ixalan.java +++ b/Mage.Sets/src/mage/sets/Ixalan.java @@ -216,6 +216,7 @@ public class Ixalan extends ExpansionSet { cards.add(new SetCardInfo("Vanquisher's Banner", 251, Rarity.RARE, mage.cards.v.VanquishersBanner.class)); cards.add(new SetCardInfo("Verdant Sun's Avatar", 213, Rarity.RARE, mage.cards.v.VerdantSunsAvatar.class)); cards.add(new SetCardInfo("Vicious Conquistador", 128, Rarity.UNCOMMON, mage.cards.v.ViciousConquistador.class)); + cards.add(new SetCardInfo("Vineshaper Mystic", 214, Rarity.UNCOMMON, mage.cards.v.VineshaperMystic.class)); cards.add(new SetCardInfo("Vona, Butcher of Magan", 231, Rarity.MYTHIC, mage.cards.v.VonaButcherOfMagan.class)); cards.add(new SetCardInfo("Vraska's Contempt", 129, Rarity.RARE, mage.cards.v.VraskasContempt.class)); cards.add(new SetCardInfo("Vraska, Relic Seeker", 232, Rarity.MYTHIC, mage.cards.v.VraskaRelicSeeker.class)); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index b375b744a08..d59d306d67c 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -32426,6 +32426,8 @@ Tilonalli's Knight|Ixalan|169|C|{1}{R}|Creature - Human Knight|2|2|Whenever Tilo Tilonalli's Skinshifter|Ixalan|170|R|{2}{R}|Creature - Human Shaman|0|1|Whenever Tilonalli's Skinshifter attacks, it becomes a copy of another target nonlegendary attacking creature until end of turn.| Trove of Temptation|Ixalan|171|U|{3}{R}|Enchantment|||Each opponent must attack you or a planeswalker you control with at least one creature each combat if able.$At the beginning of your end step, create a colorless Treasure artifact token with "t, Sacrifice this artifact: Add one mana of any color to your mana pool.”| Unfriendly Fire|Ixalan|172|C|{4}{R}|Instant|||Unfriendly Fire deals 4 damage to target creature or player.| +Vance's Blasting Cannons|Ixalan|173a|R|{3}{R}|Legendary Enchantment|||At the beginning of your upkeep, exile the top card of your library. If it's a nonland card, you may cast that card this turn.$Whenever you cast your third spell in a turn, transform Vance's Blasting Cannons.| +Spitfire Bastion|Ixalan|173b|R||Legendary Land|||{t}: Add {r} to your mana pool.${2}{r}, {t}: Spitfire Bastion deals 3 damage to target creature or player.| Wily Goblin|Ixalan|174|U|{R}{R}|Creature - Goblin Pirate|1|1|When Wily Goblin enters the battlefield, create a colorless Treasure artifact token with "{T}, Sacrifice this artifact: Add one mana of any color to your mana pool."| Carnage Tyrant|Ixalan|179|M|{4}{G}{G}|Creature - Dinosaur|7|6|Carnage Tyrant can't be countered.$Trample, hexproof| Commune with Dinosaurs|Ixalan|181|C|{G}|Sorcery|||| @@ -32449,6 +32451,7 @@ Snapping Sailback|Ixalan|208|U|{4}{G}|Creature - Dinosaur|4|4|Flash$Enrage — W Thundering Spineback|Ixalan|210|U|{5}{G}{G}|Creature - Dinosaur|5|5|Other Dinosaurs you control get +1/+1.${5}{G}: Create a 3/3 green Dinosaur creature token with trample.| Tishana's Wayfinder|Ixalan|211|C|{2}{G}|Creature - Merfolk Scout|2|2|When Tishana's Wayfinder enters the battlefield, it explores.| Verdant Sun's Avatar|Ixalan|213|R|{5}{G}{G}|Creature - Dinosaur Avatar|5|5|When Verdant Sun's Avatar or another creature enters the battlefield under your control, you gain life equal to that creature's toughness.| +Vineshaper Mystic|Ixalan|214|U|{2}{G}|Creature - Merfolk Shaman|1|3|When Vineshaper Mystic enters the battlefield, put a +1/+1 counter on each of up to two target Merfolk you control.| Waker of the Wilds|Ixalan|215|R|{2}{G}{G}|Creature - Merfolk Shaman|3|3|{X}{G}{G}: Put X +1/+1 counters on target land you control. That land becomes a 0/0 Elemental creature with haste. It's still a land.| Wildgrowth Walker|Ixalan|216|U|{1}{G}|Creature - Elemental|1|3|Whenever a creature you control explores, put a +1/+1 counter on Wildgrowth Walker and you gain 3 life.| Admiral Beckett Brass|Ixalan|217|M|{1}{U}{B}{R}|Legendary Creature - Human Pirate|3|3|Other Pirates you control get +1/+1.$At the beginning of your end step, gain control of target nonland permanent controlled by a player who was dealt damage by three or more Pirates this turn.| From c54ddefed54c12946ca258d664892c2454b7f7b4 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 14 Sep 2017 23:43:33 +0200 Subject: [PATCH 24/35] Fixed bug of Scarwood Bandits. --- .../src/mage/cards/s/ScarwoodBandits.java | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/Mage.Sets/src/mage/cards/s/ScarwoodBandits.java b/Mage.Sets/src/mage/cards/s/ScarwoodBandits.java index d6fd2a6c256..09c803e2250 100644 --- a/Mage.Sets/src/mage/cards/s/ScarwoodBandits.java +++ b/Mage.Sets/src/mage/cards/s/ScarwoodBandits.java @@ -31,20 +31,20 @@ import java.util.UUID; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; +import mage.abilities.Mode; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.SourceOnBattlefieldCondition; -import mage.abilities.costs.common.TapSourceCost; 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.decorator.ConditionalContinuousEffect; -import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.Effect; import mage.abilities.effects.Effects; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.abilities.keyword.ForestwalkAbility; -import mage.abilities.Mode; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -53,7 +53,6 @@ import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.Zone; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetArtifactPermanent; import mage.util.CardUtil; @@ -65,7 +64,7 @@ import mage.util.CardUtil; public class ScarwoodBandits extends CardImpl { public ScarwoodBandits(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{G}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.ROGUE); this.power = new MageInt(2); @@ -73,16 +72,16 @@ public class ScarwoodBandits extends CardImpl { // Forestwalk this.addAbility(new ForestwalkAbility()); - + // {2}{G}, {tap}: Unless an opponent pays {2}, gain control of target artifact for as long as Scarwood Bandits remains on the battlefield. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, - new DoUnlessAnyOpponentPaysEffect( - new ConditionalContinuousEffect( - new GainControlTargetEffect(Duration.Custom, true), - new SourceOnBattlefieldCondition(), - "gain control of target artifact for as long as {this} remains on the battlefield"), - new GenericManaCost(2)), - new ManaCostsImpl("{2}{G}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, + new DoUnlessAnyOpponentPaysEffect( + new ConditionalContinuousEffect( + new GainControlTargetEffect(Duration.Custom, true), + SourceOnBattlefieldCondition.instance, + "gain control of target artifact for as long as {this} remains on the battlefield"), + new GenericManaCost(2)), + new ManaCostsImpl("{2}{G}")); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetArtifactPermanent()); this.addAbility(ability); From d0dfd46c5f6c4aadf0014dca7d3794279c9214d1 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 14 Sep 2017 23:45:48 +0200 Subject: [PATCH 25/35] Fixed problem that prevented project generation. --- .../FilterControlledCreaturePermanent.java | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/Mage/src/main/java/mage/filter/common/FilterControlledCreaturePermanent.java b/Mage/src/main/java/mage/filter/common/FilterControlledCreaturePermanent.java index a10d4b7b735..34e81d3e432 100644 --- a/Mage/src/main/java/mage/filter/common/FilterControlledCreaturePermanent.java +++ b/Mage/src/main/java/mage/filter/common/FilterControlledCreaturePermanent.java @@ -1,16 +1,16 @@ /* * 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 @@ -20,7 +20,7 @@ * 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. @@ -29,17 +29,14 @@ package mage.filter.common; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.TargetController; -import mage.filter.FilterPermanent; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.mageobject.SubtypePredicate; -import mage.filter.predicate.permanent.ControllerPredicate; /** * * @author BetaSteward_at_googlemail.com */ -public class FilterControlledCreaturePermanent extends FilterPermanent { +public class FilterControlledCreaturePermanent extends FilterControlledPermanent { public FilterControlledCreaturePermanent() { this("creature you control"); @@ -48,7 +45,7 @@ public class FilterControlledCreaturePermanent extends FilterPermanent { public FilterControlledCreaturePermanent(String name) { super(name); this.add(new CardTypePredicate(CardType.CREATURE)); - this.add(new ControllerPredicate(TargetController.YOU)); + // this.add(new ControllerPredicate(TargetController.YOU)); } public FilterControlledCreaturePermanent(SubType subtype, String name) { From 7663827a30c4f6445cf63d3fc87eb041be453526 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 18:14:32 -0400 Subject: [PATCH 26/35] Implemented Vance's Blasting Cannons/Spitfire Bastion --- .../src/mage/cards/s/SpitfireBastion.java | 74 +++++++ .../mage/cards/v/VancesBlastingCannons.java | 194 ++++++++++++++++++ Mage.Sets/src/mage/sets/Ixalan.java | 2 + .../abilities/keyword/ConspireAbility.java | 9 +- 4 files changed, 276 insertions(+), 3 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/s/SpitfireBastion.java create mode 100644 Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java diff --git a/Mage.Sets/src/mage/cards/s/SpitfireBastion.java b/Mage.Sets/src/mage/cards/s/SpitfireBastion.java new file mode 100644 index 00000000000..5de16e5abe0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SpitfireBastion.java @@ -0,0 +1,74 @@ +/* + * 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.cards.s; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.mana.RedManaAbility; +import mage.constants.SuperType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author TheElk801 + */ +public class SpitfireBastion extends CardImpl { + + public SpitfireBastion(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + this.addSuperType(SuperType.LEGENDARY); + this.nightCard = true; + + // {T}: Add {R} to your mana pool. + this.addAbility(new RedManaAbility()); + + // {2}{R}, {T}: Spitfire Bastion deals 3 damage to target creature or player. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(3), new TapSourceCost()); + ability.addCost(new ManaCostsImpl("{2}{R}")); + ability.addTarget(new TargetCreatureOrPlayer()); + this.addAbility(ability); + } + + public SpitfireBastion(final SpitfireBastion card) { + super(card); + } + + @Override + public SpitfireBastion copy() { + return new SpitfireBastion(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java b/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java new file mode 100644 index 00000000000..4444aa205b4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java @@ -0,0 +1,194 @@ +/* + * 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.cards.v; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.keyword.TransformAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.s.SpitfireBastion; +import mage.constants.AsThoughEffectType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SuperType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.targetpointer.FixedTarget; +import mage.watchers.common.CastSpellLastTurnWatcher; + +/** + * + * @author TheElk801 + */ +public class VancesBlastingCannons extends CardImpl { + + public VancesBlastingCannons(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}"); + + this.addSuperType(SuperType.LEGENDARY); + this.transformable = true; + this.secondSideCardClazz = SpitfireBastion.class; + + // At the beginning of your upkeep, exile the top card of your library. If it's a nonland card, you may cast that card this turn. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new VancesBlastingCannonsExileEffect(), TargetController.YOU, false)); + + // Whenever you cast your third spell in a turn, transform Vance's Blasting Cannons. + this.addAbility(new TransformAbility()); + this.addAbility(new VancesBlastingCannonsFlipTrigger(), new CastSpellLastTurnWatcher()); + } + + public VancesBlastingCannons(final VancesBlastingCannons card) { + super(card); + } + + @Override + public VancesBlastingCannons copy() { + return new VancesBlastingCannons(this); + } +} + +class VancesBlastingCannonsExileEffect extends OneShotEffect { + + public VancesBlastingCannonsExileEffect() { + super(Outcome.Benefit); + this.staticText = "exile the top card of your library. If it's a nonland card, you may cast that card this turn"; + } + + public VancesBlastingCannonsExileEffect(final VancesBlastingCannonsExileEffect effect) { + super(effect); + } + + @Override + public VancesBlastingCannonsExileEffect copy() { + return new VancesBlastingCannonsExileEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (controller != null && sourcePermanent != null) { + Card card = controller.getLibrary().getFromTop(game); + if (card != null) { + String exileName = sourcePermanent.getIdName() + " Date: Thu, 14 Sep 2017 20:28:56 -0400 Subject: [PATCH 27/35] updated some mistakes --- Mage.Sets/src/mage/cards/f/FieldOfRuin.java | 2 +- Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/cards/f/FieldOfRuin.java b/Mage.Sets/src/mage/cards/f/FieldOfRuin.java index 45e3c514be3..ccd0cc0f343 100644 --- a/Mage.Sets/src/mage/cards/f/FieldOfRuin.java +++ b/Mage.Sets/src/mage/cards/f/FieldOfRuin.java @@ -119,7 +119,7 @@ class FieldOfRuinEffect extends OneShotEffect { for (UUID cardId : target.getTargets()) { Card card = player.getLibrary().getCard(cardId, game); if (card != null) { - card.putOntoBattlefield(game, Zone.LIBRARY, source.getSourceId(), player.getId(), true); + card.putOntoBattlefield(game, Zone.LIBRARY, source.getSourceId(), player.getId()); } } diff --git a/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java b/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java index 4444aa205b4..4247174359f 100644 --- a/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java +++ b/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java @@ -108,7 +108,7 @@ class VancesBlastingCannonsExileEffect extends OneShotEffect { if (controller != null && sourcePermanent != null) { Card card = controller.getLibrary().getFromTop(game); if (card != null) { - String exileName = sourcePermanent.getIdName() + " Date: Thu, 14 Sep 2017 20:57:04 -0400 Subject: [PATCH 28/35] fixed Wasitora not forcing sacrifice of shroud creatures --- .../src/mage/cards/w/WasitoraNekoruQueen.java | 54 ++----------------- 1 file changed, 5 insertions(+), 49 deletions(-) diff --git a/Mage.Sets/src/mage/cards/w/WasitoraNekoruQueen.java b/Mage.Sets/src/mage/cards/w/WasitoraNekoruQueen.java index f825f379386..1a15867d24a 100644 --- a/Mage.Sets/src/mage/cards/w/WasitoraNekoruQueen.java +++ b/Mage.Sets/src/mage/cards/w/WasitoraNekoruQueen.java @@ -30,8 +30,7 @@ package mage.cards.w; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.effects.Effect; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.FlyingAbility; @@ -42,18 +41,13 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Outcome; import mage.constants.SuperType; -import mage.constants.Zone; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.game.Game; -import mage.game.events.DamagedPlayerEvent; -import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.game.permanent.token.WasitoraCatDragonToken; import mage.players.Player; import mage.target.TargetPermanent; -import mage.target.targetpointer.FixedTarget; /** * @@ -77,7 +71,7 @@ public class WasitoraNekoruQueen extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // Whenever Wasitora, Nekoru Queen deals combat damage to a player, that player sacrifices a creature. If the player can't, you create a 3/3 black, red, and green Cat Dragon creature token with flying - this.addAbility(new WasitoraNekoruQueenTriggeredAbility()); + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new WasitoraNekoruQueenEffect(), false, true)); } public WasitoraNekoruQueen(final WasitoraNekoruQueen card) { @@ -90,44 +84,6 @@ public class WasitoraNekoruQueen extends CardImpl { } } -class WasitoraNekoruQueenTriggeredAbility extends TriggeredAbilityImpl { - - public WasitoraNekoruQueenTriggeredAbility() { - super(Zone.BATTLEFIELD, new WasitoraNekoruQueenEffect()); - } - - public WasitoraNekoruQueenTriggeredAbility(final WasitoraNekoruQueenTriggeredAbility ability) { - super(ability); - } - - @Override - public WasitoraNekoruQueenTriggeredAbility copy() { - return new WasitoraNekoruQueenTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == EventType.DAMAGED_PLAYER; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event; - if (damageEvent.isCombatDamage() && event.getSourceId().equals(this.getSourceId())) { - for (Effect effect : this.getEffects()) { - effect.setTargetPointer(new FixedTarget(event.getPlayerId())); - } - return true; - } - return false; - } - - @Override - public String getRule() { - return "Whenever {this} deals combat damage to a player, that player sacrifices a creature. If the player can't, you create a 3/3 black, red, and green Cat Dragon creature token with flying"; - } -} - class WasitoraNekoruQueenEffect extends OneShotEffect { public WasitoraNekoruQueenEffect() { @@ -151,11 +107,11 @@ class WasitoraNekoruQueenEffect extends OneShotEffect { if (damagedPlayer != null && controller != null) { FilterControlledPermanent filter = new FilterControlledPermanent("creature"); filter.add(new CardTypePredicate(CardType.CREATURE)); - TargetPermanent target = new TargetPermanent(filter); - if (damagedPlayer.choose(Outcome.Sacrifice, target, source.getId(), game)) { + TargetPermanent target = new TargetPermanent(1, 1, filter, true); + if (damagedPlayer.choose(Outcome.Sacrifice, target, source.getSourceId(), game)) { Permanent objectToBeSacrificed = game.getPermanent(target.getFirstTarget()); if (objectToBeSacrificed != null) { - if (objectToBeSacrificed.sacrifice(source.getId(), game)) { + if (objectToBeSacrificed.sacrifice(source.getSourceId(), game)) { return true; } } From 10a57b1594bbe678f6850e63cf25f3a2eadd16fd Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 21:12:25 -0400 Subject: [PATCH 29/35] Implemented Energy Storm --- Mage.Sets/src/mage/cards/e/EnergyStorm.java | 82 +++++++++++++++++++ Mage.Sets/src/mage/sets/IceAge.java | 1 + Mage.Sets/src/mage/sets/MastersEditionII.java | 1 + .../main/java/mage/filter/StaticFilters.java | 6 ++ 4 files changed, 90 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/e/EnergyStorm.java diff --git a/Mage.Sets/src/mage/cards/e/EnergyStorm.java b/Mage.Sets/src/mage/cards/e/EnergyStorm.java new file mode 100644 index 00000000000..3bf51c4a3f3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EnergyStorm.java @@ -0,0 +1,82 @@ +/* + * 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.cards.e; + +import java.util.UUID; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DontUntapInControllersUntapStepAllEffect; +import mage.abilities.effects.common.PreventAllDamageByAllObjectsEffect; +import mage.abilities.keyword.CumulativeUpkeepAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.StaticFilters; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.AbilityPredicate; + +/** + * + * @author TheElk801 + */ +public class EnergyStorm extends CardImpl { + + private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures with flying"); + + static { + filter.add(new AbilityPredicate(FlyingAbility.class)); + } + + public EnergyStorm(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}"); + + // Cumulative upkeep {1} + this.addAbility(new CumulativeUpkeepAbility(new ManaCostsImpl("{1}"))); + + // Prevent all damage that would be dealt by instant and sorcery spells. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, + new PreventAllDamageByAllObjectsEffect(StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELLS, Duration.WhileOnBattlefield, false) + )); + + // Creatures with flying don't untap during their controllers' untap steps. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DontUntapInControllersUntapStepAllEffect(Duration.WhileOnBattlefield, TargetController.ANY, filter))); + } + + public EnergyStorm(final EnergyStorm card) { + super(card); + } + + @Override + public EnergyStorm copy() { + return new EnergyStorm(this); + } +} diff --git a/Mage.Sets/src/mage/sets/IceAge.java b/Mage.Sets/src/mage/sets/IceAge.java index 4f09b0c9a74..8aec0808015 100644 --- a/Mage.Sets/src/mage/sets/IceAge.java +++ b/Mage.Sets/src/mage/sets/IceAge.java @@ -108,6 +108,7 @@ public class IceAge extends ExpansionSet { cards.add(new SetCardInfo("Elder Druid", 120, Rarity.RARE, mage.cards.e.ElderDruid.class)); cards.add(new SetCardInfo("Elemental Augury", 364, Rarity.RARE, mage.cards.e.ElementalAugury.class)); cards.add(new SetCardInfo("Enduring Renewal", 247, Rarity.RARE, mage.cards.e.EnduringRenewal.class)); + cards.add(new SetCardInfo("Energy Storm", 248, Rarity.RARE, mage.cards.e.EnergyStorm.class)); cards.add(new SetCardInfo("Enervate", 67, Rarity.COMMON, mage.cards.e.Enervate.class)); cards.add(new SetCardInfo("Errantry", 183, Rarity.COMMON, mage.cards.e.Errantry.class)); cards.add(new SetCardInfo("Fanatical Fever", 122, Rarity.UNCOMMON, mage.cards.f.FanaticalFever.class)); diff --git a/Mage.Sets/src/mage/sets/MastersEditionII.java b/Mage.Sets/src/mage/sets/MastersEditionII.java index dafcebca4f1..88ddf68df45 100644 --- a/Mage.Sets/src/mage/sets/MastersEditionII.java +++ b/Mage.Sets/src/mage/sets/MastersEditionII.java @@ -114,6 +114,7 @@ public class MastersEditionII extends ExpansionSet { cards.add(new SetCardInfo("Elvish Hunter", 157, Rarity.COMMON, ElvishHunter.class)); cards.add(new SetCardInfo("Elvish Ranger", 158, Rarity.COMMON, mage.cards.e.ElvishRanger.class)); cards.add(new SetCardInfo("Elvish Spirit Guide", 159, Rarity.UNCOMMON, mage.cards.e.ElvishSpiritGuide.class)); + cards.add(new SetCardInfo("Energy Storm", 11, Rarity.RARE, mage.cards.e.EnergyStorm.class)); cards.add(new SetCardInfo("Enervate", 47, Rarity.COMMON, mage.cards.e.Enervate.class)); cards.add(new SetCardInfo("Errantry", 124, Rarity.COMMON, mage.cards.e.Errantry.class)); cards.add(new SetCardInfo("Farrel's Mantle", 13, Rarity.UNCOMMON, mage.cards.f.FarrelsMantle.class)); diff --git a/Mage/src/main/java/mage/filter/StaticFilters.java b/Mage/src/main/java/mage/filter/StaticFilters.java index 05a02cc4881..462f2672015 100644 --- a/Mage/src/main/java/mage/filter/StaticFilters.java +++ b/Mage/src/main/java/mage/filter/StaticFilters.java @@ -64,6 +64,7 @@ public final class StaticFilters { public static final FilterSpell FILTER_SPELL = new FilterSpell(); public static final FilterSpell FILTER_INSTANT_OR_SORCERY_SPELL = new FilterSpell("instant or sorcery spell"); + public static final FilterSpell FILTER_INSTANT_OR_SORCERY_SPELLS = new FilterSpell("instant or sorcery spells"); public static final FilterPermanent FILTER_CREATURE_TOKENS = new FilterCreaturePermanent("creature tokens"); @@ -125,6 +126,11 @@ public final class StaticFilters { new CardTypePredicate(CardType.INSTANT), new CardTypePredicate(CardType.SORCERY) )); + + FILTER_INSTANT_OR_SORCERY_SPELLS.add(Predicates.or( + new CardTypePredicate(CardType.INSTANT), + new CardTypePredicate(CardType.SORCERY) + )); } } From 96bd19f1ba9e6d06860447fbb469c6814904c76a Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 21:26:19 -0400 Subject: [PATCH 30/35] Implemented An-Zerrin Ruins --- Mage.Sets/src/mage/cards/a/AnZerrinRuins.java | 110 ++++++++++++++++++ Mage.Sets/src/mage/sets/Homelands.java | 2 + Mage.Sets/src/mage/sets/MastersEditionII.java | 1 + 3 files changed, 113 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/a/AnZerrinRuins.java diff --git a/Mage.Sets/src/mage/cards/a/AnZerrinRuins.java b/Mage.Sets/src/mage/cards/a/AnZerrinRuins.java new file mode 100644 index 00000000000..b7a26eccdc4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AnZerrinRuins.java @@ -0,0 +1,110 @@ +/* + * 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.cards.a; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.ChooseCreatureTypeEffect; +import mage.abilities.effects.common.DontUntapInControllersUntapStepAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; + +/** + * + * @author TheElk801 + */ +public class AnZerrinRuins extends CardImpl { + + public AnZerrinRuins(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}{R}"); + + // As An-Zerrin Ruins enters the battlefield, choose a creature type. + this.addAbility(new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.UnboostCreature))); + + // Creatures of the chosen type don't untap during their controllers' untap steps. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AnZerrinRuinsDontUntapEffect())); + } + + public AnZerrinRuins(final AnZerrinRuins card) { + super(card); + } + + @Override + public AnZerrinRuins copy() { + return new AnZerrinRuins(this); + } +} + +class AnZerrinRuinsDontUntapEffect extends DontUntapInControllersUntapStepAllEffect { + + public AnZerrinRuinsDontUntapEffect() { + super(Duration.WhileOnBattlefield, TargetController.ANY, new FilterCreaturePermanent()); + } + + public AnZerrinRuinsDontUntapEffect(final AnZerrinRuinsDontUntapEffect effect) { + super(effect); + } + + @Override + public AnZerrinRuinsDontUntapEffect copy() { + return new AnZerrinRuinsDontUntapEffect(this); + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (super.applies(event, source, game)) { + Permanent sourcePerm = game.getPermanent(source.getSourceId()); + Permanent permanent = game.getPermanent(event.getTargetId()); + if (permanent != null && sourcePerm != null) { + SubType subtype = (SubType) game.getState().getValue(sourcePerm.getId() + "_type"); + if (permanent.getSubtype(game).contains(subtype)) { + return true; + } + } + } + return false; + } + + @Override + public String getText(Mode mode) { + return "Creatures of the chosen type don't untap during their controllers' untap steps."; + } +} diff --git a/Mage.Sets/src/mage/sets/Homelands.java b/Mage.Sets/src/mage/sets/Homelands.java index 26330b11805..6b41c9983f5 100644 --- a/Mage.Sets/src/mage/sets/Homelands.java +++ b/Mage.Sets/src/mage/sets/Homelands.java @@ -73,6 +73,7 @@ public class Homelands extends ExpansionSet { cards.add(new SetCardInfo("Ambush", 78, Rarity.COMMON, mage.cards.a.Ambush.class)); cards.add(new SetCardInfo("Ambush Party", 79, Rarity.COMMON, mage.cards.a.AmbushParty.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Ambush Party", 80, Rarity.COMMON, mage.cards.a.AmbushParty.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("An-Zerrin Ruins", 87, Rarity.RARE, mage.cards.a.AnZerrinRuins.class)); cards.add(new SetCardInfo("Anaba Ancestor", 81, Rarity.RARE, mage.cards.a.AnabaAncestor.class)); cards.add(new SetCardInfo("Anaba Bodyguard", 82, Rarity.COMMON, mage.cards.a.AnabaBodyguard.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Anaba Bodyguard", 83, Rarity.COMMON, mage.cards.a.AnabaBodyguard.class, NON_FULL_USE_VARIOUS)); @@ -82,6 +83,7 @@ public class Homelands extends ExpansionSet { cards.add(new SetCardInfo("An-Havva Constable", 51, Rarity.RARE, mage.cards.a.AnHavvaConstable.class)); cards.add(new SetCardInfo("An-Havva Inn", 52, Rarity.UNCOMMON, mage.cards.a.AnHavvaInn.class)); cards.add(new SetCardInfo("An-Havva Township", 136, Rarity.UNCOMMON, mage.cards.a.AnHavvaTownship.class)); + cards.add(new SetCardInfo("An-Zerrin Ruins", 87, Rarity.RARE, mage.cards.a.AnZerrinRuins.class)); cards.add(new SetCardInfo("Aysen Abbey", 137, Rarity.UNCOMMON, mage.cards.a.AysenAbbey.class)); cards.add(new SetCardInfo("Aysen Bureaucrats", 104, Rarity.COMMON, mage.cards.a.AysenBureaucrats.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aysen Bureaucrats", 105, Rarity.COMMON, mage.cards.a.AysenBureaucrats.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage.Sets/src/mage/sets/MastersEditionII.java b/Mage.Sets/src/mage/sets/MastersEditionII.java index 88ddf68df45..43b4d13976c 100644 --- a/Mage.Sets/src/mage/sets/MastersEditionII.java +++ b/Mage.Sets/src/mage/sets/MastersEditionII.java @@ -69,6 +69,7 @@ public class MastersEditionII extends ExpansionSet { cards.add(new SetCardInfo("Adarkar Sentinel", 201, Rarity.COMMON, mage.cards.a.AdarkarSentinel.class)); cards.add(new SetCardInfo("Aeolipile", 202, Rarity.COMMON, mage.cards.a.Aeolipile.class)); cards.add(new SetCardInfo("Ambush Party", 115, Rarity.COMMON, mage.cards.a.AmbushParty.class)); + cards.add(new SetCardInfo("An-Zerrin Ruins", 117, Rarity.RARE, mage.cards.a.AnZerrinRuins.class)); cards.add(new SetCardInfo("Anarchy", 116, Rarity.RARE, mage.cards.a.Anarchy.class)); cards.add(new SetCardInfo("Angel of Fury", 2, Rarity.RARE, mage.cards.a.AngelOfFury.class)); cards.add(new SetCardInfo("Angel of Light", 3, Rarity.UNCOMMON, mage.cards.a.AngelOfLight.class)); From 0d43fcf7294e5bff992e79a52a93c445746d5708 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 21:57:13 -0400 Subject: [PATCH 31/35] Implemented Repeating Barrage --- .../src/mage/cards/r/RepeatingBarrage.java | 75 +++++++++++++++++++ Mage.Sets/src/mage/sets/Ixalan.java | 1 + Utils/mtg-cards-data.txt | 1 + 3 files changed, 77 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/r/RepeatingBarrage.java diff --git a/Mage.Sets/src/mage/cards/r/RepeatingBarrage.java b/Mage.Sets/src/mage/cards/r/RepeatingBarrage.java new file mode 100644 index 00000000000..315b5a02c3a --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RepeatingBarrage.java @@ -0,0 +1,75 @@ +/* + * 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.cards.r; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.condition.common.RaidCondition; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.target.common.TargetCreatureOrPlayer; +import mage.watchers.common.PlayerAttackedWatcher; + +/** + * + * @author TheElk801 + */ +public class RepeatingBarrage extends CardImpl { + + public RepeatingBarrage(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{R}{R}"); + + // Repeating Barrage deals 3 damage to target creature or player. + this.getSpellAbility().addEffect(new DamageTargetEffect(3)); + this.getSpellAbility().addTarget(new TargetCreatureOrPlayer()); + + // Raid — {3}{R}{R}: Return Repeating Barrage from your graveyard to your hand. Activate this ability only if you attacked with a creature this turn. + Ability ability = new ConditionalActivatedAbility(Zone.GRAVEYARD, + new ReturnSourceFromGraveyardToHandEffect(), + new ManaCostsImpl("{3}{R}{R}"), + RaidCondition.instance); + ability.setAbilityWord(AbilityWord.RAID); + this.addAbility(ability, new PlayerAttackedWatcher()); + } + + public RepeatingBarrage(final RepeatingBarrage card) { + super(card); + } + + @Override + public RepeatingBarrage copy() { + return new RepeatingBarrage(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Ixalan.java b/Mage.Sets/src/mage/sets/Ixalan.java index 6cdf8a3b5d2..a579435115c 100644 --- a/Mage.Sets/src/mage/sets/Ixalan.java +++ b/Mage.Sets/src/mage/sets/Ixalan.java @@ -157,6 +157,7 @@ public class Ixalan extends ExpansionSet { cards.add(new SetCardInfo("Raptor Hatchling", 155, Rarity.UNCOMMON, mage.cards.r.RaptorHatchling.class)); cards.add(new SetCardInfo("Ravenous Daggertooth", 202, Rarity.COMMON, mage.cards.r.RavenousDaggertooth.class)); cards.add(new SetCardInfo("Regisaur Alpha", 227, Rarity.RARE, mage.cards.r.RegisaurAlpha.class)); + cards.add(new SetCardInfo("Repeating Barrage", 156, Rarity.RARE, mage.cards.r.RepeatingBarrage.class)); cards.add(new SetCardInfo("Revel in Riches", 117, Rarity.RARE, mage.cards.r.RevelInRiches.class)); cards.add(new SetCardInfo("Rigging Runner", 157, Rarity.UNCOMMON, mage.cards.r.RiggingRunner.class)); cards.add(new SetCardInfo("Rile", 158, Rarity.COMMON, mage.cards.r.Rile.class)); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index d59d306d67c..973b339b5af 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -32416,6 +32416,7 @@ Makeshift Munitions|Ixalan|151|U|{1}{R}|Enchantment|||{1}, Sacrifice an artifact Otepec Huntmaster|Ixalan|153|U|{1}{R}|Creature - Human Shaman|1|2|Dinosaur spells you cast cost {1} less to cast.${T}: Target Dinosaur gains haste until end of turn.| Rampaging Ferocidon|Ixalan|154|R|{2}{R}|Creature - Dinosaur|3|3|Menace$Players can't gain life.$Whenever another creature enters the battlefield, Rampaging Ferocidon deals 1 damage to that creature's controller.| Raptor Hatchling|Ixalan|155|U|{1}{R}|Creature - Dinosaur|1|1|Enrage - Whenever Raptor Hatchling is dealt damage, create a 3/3 green Dinosaur creature token with trample.| +Repeating Barrage|Ixalan|156|R|{1}{R}{R}|Sorcery|||Repeating Barrage deals 3 damage to target creature or player.$Raid — {3}{R}{R}: Return Repeating Barrage from your graveyard to your hand. Activate this ability only if you attacked with a creature this turn.| Rigging Runner|Ixalan|157|U|{R}|Creature - Goblin Pirate|1|1|First strike$Raid/ — Rigging runner enters the battlefield with a +1/+1 counter on it if you attacked with a creature this turn.|Rile|Ixalan|158|C|{R}|Sorcery|||Rile deals 1 damage to target creature you control. That creature gains trample until end of turn.$Draw a card.| Rowdy Crew|Ixalan|159|M|{2}{R}{R}|Creature - Human Pirate|3|3|Trample$When Rowdy Crew enters the battlefield, draw three cards, then discard two cards at random. If two cards that share a card type are discarded this way, put two +1/+1 counters on Rowdy Crew.| Star of Extinction|Ixalan|161|M|{5}{R}{R}|Sorcery|||Destroy target land. Star of Extinction deals 20 damage to each creature and each planeswalker.| From c9f03612d9fe57ded4b14e65f5d3e3db9bf3b130 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 22:08:15 -0400 Subject: [PATCH 32/35] Implemented Mind Harness --- Mage.Sets/src/mage/cards/m/MindHarness.java | 89 +++++++++++++++++++++ Mage.Sets/src/mage/sets/Mirage.java | 1 + 2 files changed, 90 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/m/MindHarness.java diff --git a/Mage.Sets/src/mage/cards/m/MindHarness.java b/Mage.Sets/src/mage/cards/m/MindHarness.java new file mode 100644 index 00000000000..a0ef54b12ab --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MindHarness.java @@ -0,0 +1,89 @@ +/* + * 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.cards.m; + +import java.util.UUID; +import mage.ObjectColor; +import mage.constants.SubType; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.AttachEffect; +import mage.constants.Outcome; +import mage.target.TargetPermanent; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.ControlEnchantedEffect; +import mage.abilities.keyword.CumulativeUpkeepAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; + +/** + * + * @author TheElk801 + */ +public class MindHarness extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("red or green creature"); + + static { + filter.add(Predicates.or(new ColorPredicate(ObjectColor.RED), new ColorPredicate(ObjectColor.GREEN))); + } + + public MindHarness(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}"); + + this.subtype.add(SubType.AURA); + + // Enchant red or green creature + TargetPermanent auraTarget = new TargetPermanent(filter); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Cumulative upkeep {1} + this.addAbility(new CumulativeUpkeepAbility(new ManaCostsImpl("{1}"))); + + // You control enchanted creature. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ControlEnchantedEffect())); + } + + public MindHarness(final MindHarness card) { + super(card); + } + + @Override + public MindHarness copy() { + return new MindHarness(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Mirage.java b/Mage.Sets/src/mage/sets/Mirage.java index 2bd04a2dd41..1106b3b3f1e 100644 --- a/Mage.Sets/src/mage/sets/Mirage.java +++ b/Mage.Sets/src/mage/sets/Mirage.java @@ -194,6 +194,7 @@ public class Mirage extends ExpansionSet { cards.add(new SetCardInfo("Memory Lapse", 74, Rarity.COMMON, mage.cards.m.MemoryLapse.class)); cards.add(new SetCardInfo("Merfolk Raiders", 75, Rarity.COMMON, mage.cards.m.MerfolkRaiders.class)); cards.add(new SetCardInfo("Merfolk Seer", 76, Rarity.COMMON, mage.cards.m.MerfolkSeer.class)); + cards.add(new SetCardInfo("Mind Harness", 78, Rarity.UNCOMMON, mage.cards.m.MindHarness.class)); cards.add(new SetCardInfo("Mist Dragon", 79, Rarity.RARE, mage.cards.m.MistDragon.class)); cards.add(new SetCardInfo("Moss Diamond", 277, Rarity.UNCOMMON, mage.cards.m.MossDiamond.class)); cards.add(new SetCardInfo("Mountain", 301, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); From 94b7c07b33a3cd606da49b86d6d9820222a86dca Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 22:11:45 -0400 Subject: [PATCH 33/35] Implemented Inner Sanctum --- Mage.Sets/src/mage/cards/i/InnerSanctum.java | 68 ++++++++++++++++++++ Mage.Sets/src/mage/sets/Weatherlight.java | 1 + 2 files changed, 69 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/i/InnerSanctum.java diff --git a/Mage.Sets/src/mage/cards/i/InnerSanctum.java b/Mage.Sets/src/mage/cards/i/InnerSanctum.java new file mode 100644 index 00000000000..4f9c90ffa69 --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/InnerSanctum.java @@ -0,0 +1,68 @@ +/* + * 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.cards.i; + +import java.util.UUID; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.PayLifeCost; +import mage.abilities.effects.common.PreventAllDamageToAllEffect; +import mage.abilities.keyword.CumulativeUpkeepAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreatureInPlay; + +/** + * + * @author TheElk801 + */ +public class InnerSanctum extends CardImpl { + + public InnerSanctum(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}{W}"); + + // Cumulative upkeep-Pay 2 life. + this.addAbility(new CumulativeUpkeepAbility(new PayLifeCost(2))); + + // Prevent all damage that would be dealt to creatures you control. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, + new PreventAllDamageToAllEffect(Duration.WhileOnBattlefield, new FilterControlledCreatureInPlay("creatures you control")) + )); + } + + public InnerSanctum(final InnerSanctum card) { + super(card); + } + + @Override + public InnerSanctum copy() { + return new InnerSanctum(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Weatherlight.java b/Mage.Sets/src/mage/sets/Weatherlight.java index 1db6ab52f35..b3a5344f6a6 100644 --- a/Mage.Sets/src/mage/sets/Weatherlight.java +++ b/Mage.Sets/src/mage/sets/Weatherlight.java @@ -125,6 +125,7 @@ public class Weatherlight extends ExpansionSet { cards.add(new SetCardInfo("Hidden Horror", 14, Rarity.UNCOMMON, mage.cards.h.HiddenHorror.class)); cards.add(new SetCardInfo("Hurloon Shaman", 108, Rarity.UNCOMMON, mage.cards.h.HurloonShaman.class)); cards.add(new SetCardInfo("Infernal Tribute", 15, Rarity.RARE, mage.cards.i.InfernalTribute.class)); + cards.add(new SetCardInfo("Inner Sanctum", 134, Rarity.RARE, mage.cards.i.InnerSanctum.class)); cards.add(new SetCardInfo("Jabari's Banner", 150, Rarity.UNCOMMON, mage.cards.j.JabarisBanner.class)); cards.add(new SetCardInfo("Lava Hounds", 109, Rarity.UNCOMMON, mage.cards.l.LavaHounds.class)); cards.add(new SetCardInfo("Llanowar Behemoth", 74, Rarity.UNCOMMON, mage.cards.l.LlanowarBehemoth.class)); From c611d71f30e8cc68b9653d3c27b999f6923943c8 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 22:23:01 -0400 Subject: [PATCH 34/35] Implemented Spiritual Asylum --- .../src/mage/cards/s/SpiritualAsylum.java | 70 +++++++++++++++++++ Mage.Sets/src/mage/sets/Nemesis.java | 1 + ...cksCreatureYouControlTriggeredAbility.java | 8 ++- 3 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/s/SpiritualAsylum.java diff --git a/Mage.Sets/src/mage/cards/s/SpiritualAsylum.java b/Mage.Sets/src/mage/cards/s/SpiritualAsylum.java new file mode 100644 index 00000000000..ade45e5deb1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SpiritualAsylum.java @@ -0,0 +1,70 @@ +/* + * 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.cards.s; + +import java.util.UUID; +import mage.abilities.common.AttacksCreatureYouControlTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.ShroudAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public class SpiritualAsylum extends CardImpl { + + public SpiritualAsylum(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); + + // Creatures and lands you control have shroud. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(ShroudAbility.getInstance(), + Duration.WhileOnBattlefield, new FilterCreaturePermanent()))); + + // When a creature you control attacks, sacrifice Spiritual Asylum. + AttacksCreatureYouControlTriggeredAbility ability = new AttacksCreatureYouControlTriggeredAbility(new SacrificeSourceEffect()); + ability.setOnce(true); + this.addAbility(ability); + } + + public SpiritualAsylum(final SpiritualAsylum card) { + super(card); + } + + @Override + public SpiritualAsylum copy() { + return new SpiritualAsylum(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Nemesis.java b/Mage.Sets/src/mage/sets/Nemesis.java index 34e3d6e6969..9d737ef767d 100644 --- a/Mage.Sets/src/mage/sets/Nemesis.java +++ b/Mage.Sets/src/mage/sets/Nemesis.java @@ -152,6 +152,7 @@ public class Nemesis extends ExpansionSet { cards.add(new SetCardInfo("Skyshroud Ridgeback", 120, Rarity.COMMON, mage.cards.s.SkyshroudRidgeback.class)); cards.add(new SetCardInfo("Sneaky Homunculus", 44, Rarity.COMMON, mage.cards.s.SneakyHomunculus.class)); cards.add(new SetCardInfo("Spineless Thug", 71, Rarity.COMMON, mage.cards.s.SpinelessThug.class)); + cards.add(new SetCardInfo("Spiritual Asylum", 23, Rarity.RARE, mage.cards.s.SpiritualAsylum.class)); cards.add(new SetCardInfo("Stampede Driver", 122, Rarity.UNCOMMON, mage.cards.s.StampedeDriver.class)); cards.add(new SetCardInfo("Stronghold Discipline", 73, Rarity.COMMON, mage.cards.s.StrongholdDiscipline.class)); cards.add(new SetCardInfo("Stronghold Gambit", 100, Rarity.RARE, mage.cards.s.StrongholdGambit.class)); diff --git a/Mage/src/main/java/mage/abilities/common/AttacksCreatureYouControlTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/AttacksCreatureYouControlTriggeredAbility.java index 1649cc3ab5e..9ec48797fd8 100644 --- a/Mage/src/main/java/mage/abilities/common/AttacksCreatureYouControlTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/AttacksCreatureYouControlTriggeredAbility.java @@ -44,6 +44,7 @@ public class AttacksCreatureYouControlTriggeredAbility extends TriggeredAbilityI protected FilterControlledCreaturePermanent filter; protected boolean setTargetPointer; + protected boolean once = false; public AttacksCreatureYouControlTriggeredAbility(Effect effect) { this(effect, false); @@ -73,6 +74,10 @@ public class AttacksCreatureYouControlTriggeredAbility extends TriggeredAbilityI this.setTargetPointer = ability.setTargetPointer; } + public void setOnce(boolean once) { + this.once = once; + } + @Override public boolean checkEventType(GameEvent event, Game game) { return event.getType() == GameEvent.EventType.ATTACKER_DECLARED; @@ -97,7 +102,6 @@ public class AttacksCreatureYouControlTriggeredAbility extends TriggeredAbilityI @Override public String getRule() { - return "Whenever a" + (filter.getMessage().startsWith("a") ? "n " : " ") + " attacks, " + super.getRule(); + return "When" + (once ? "" : "ever") + " a" + (filter.getMessage().startsWith("a") ? "n " : " ") + " attacks, " + super.getRule(); } - } From 4b4214ba0f79c641f5a9c986fa9e4e334184a557 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 22:29:33 -0400 Subject: [PATCH 35/35] Implemented Spiritual Asylum --- .../src/mage/cards/s/SpiritualAsylum.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/cards/s/SpiritualAsylum.java b/Mage.Sets/src/mage/cards/s/SpiritualAsylum.java index ade45e5deb1..927439e4939 100644 --- a/Mage.Sets/src/mage/cards/s/SpiritualAsylum.java +++ b/Mage.Sets/src/mage/cards/s/SpiritualAsylum.java @@ -37,8 +37,12 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; +import mage.constants.TargetController; import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.permanent.ControllerPredicate; /** * @@ -46,12 +50,22 @@ import mage.filter.common.FilterCreaturePermanent; */ public class SpiritualAsylum extends CardImpl { + private static final FilterPermanent filter = new FilterPermanent("Creatures and lands you control"); + + static { + filter.add(Predicates.or( + new CardTypePredicate(CardType.CREATURE), + new CardTypePredicate(CardType.LAND) + )); + filter.add(new ControllerPredicate(TargetController.YOU)); + } + public SpiritualAsylum(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); // Creatures and lands you control have shroud. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(ShroudAbility.getInstance(), - Duration.WhileOnBattlefield, new FilterCreaturePermanent()))); + Duration.WhileOnBattlefield, filter))); // When a creature you control attacks, sacrifice Spiritual Asylum. AttacksCreatureYouControlTriggeredAbility ability = new AttacksCreatureYouControlTriggeredAbility(new SacrificeSourceEffect());