{
return true;
} else if (mana.colorless > 0 && this.colorless > 0 && includeColorless) {
return true;
+ } else if (mana.any > 0 && this.count() > 0){
+ return true;
}
return false;
diff --git a/Mage/src/main/java/mage/ManaSymbol.java b/Mage/src/main/java/mage/ManaSymbol.java
index 4e0c0fe32b..35b692de7b 100644
--- a/Mage/src/main/java/mage/ManaSymbol.java
+++ b/Mage/src/main/java/mage/ManaSymbol.java
@@ -23,7 +23,7 @@ package mage;
*
* 107.4c. Numeral symbols (such as {1}) and variable symbols (such as {X}) can
* also represent colorless mana if they appear in the effect of a spell or
- * ability that reads "add [mana symbol] to your mana pool" or something similar.
+ * ability that reads "add [mana symbol]" or something similar.
* (See rule 107.3e.)
*
* 107.4d. The symbol {0} represents zero mana and is used as a placeholder for a
diff --git a/Mage/src/main/java/mage/abilities/AbilitiesImpl.java b/Mage/src/main/java/mage/abilities/AbilitiesImpl.java
index a7a10a3236..4b99d2d8ed 100644
--- a/Mage/src/main/java/mage/abilities/AbilitiesImpl.java
+++ b/Mage/src/main/java/mage/abilities/AbilitiesImpl.java
@@ -100,7 +100,7 @@ public class AbilitiesImpl extends ArrayList implements Ab
for (Cost cost : ability.getCosts()) {
if (cost.getText() != null && !cost.getText().isEmpty()) {
if (!cost.getText().startsWith("As an additional cost")) {
- sbRule.append("As an additional cost to cast {this}, ");
+ sbRule.append("As an additional cost to cast this spell, ");
}
sbRule.append(cost.getText()).append(".
");
}
diff --git a/Mage/src/main/java/mage/abilities/AbilityImpl.java b/Mage/src/main/java/mage/abilities/AbilityImpl.java
index 25528d242b..4f3ae196a2 100644
--- a/Mage/src/main/java/mage/abilities/AbilityImpl.java
+++ b/Mage/src/main/java/mage/abilities/AbilityImpl.java
@@ -50,6 +50,7 @@ import mage.cards.SplitCard;
import mage.constants.*;
import mage.game.Game;
import mage.game.command.Emblem;
+import mage.game.command.Plane;
import mage.game.events.GameEvent;
import mage.game.events.ManaEvent;
import mage.game.permanent.Permanent;
@@ -70,7 +71,6 @@ public abstract class AbilityImpl implements Ability {
private static final Logger logger = Logger.getLogger(AbilityImpl.class);
private static final ThreadLocalStringBuilder threadLocalBuilder = new ThreadLocalStringBuilder(100);
- private static final List emptyWatchers = new ArrayList<>();
private static final List emptyAbilities = new ArrayList<>();
protected UUID id;
@@ -95,7 +95,7 @@ public abstract class AbilityImpl implements Ability {
protected boolean worksFaceDown = false;
protected MageObject sourceObject;
protected int sourceObjectZoneChangeCounter;
- protected List watchers = null;
+ protected List watchers = new ArrayList<>();
protected List subAbilities = null;
protected boolean canFizzle = true;
protected TargetAdjustment targetAdjustment = TargetAdjustment.NONE;
@@ -125,12 +125,10 @@ public abstract class AbilityImpl implements Ability {
this.manaCostsToPay = ability.manaCostsToPay.copy();
this.costs = ability.costs.copy();
this.optionalCosts = ability.optionalCosts.copy();
- if (ability.watchers != null) {
- this.watchers = new ArrayList<>();
- for (Watcher watcher : ability.watchers) {
- watchers.add(watcher.copy());
- }
+ for (Watcher watcher : ability.watchers) {
+ watchers.add(watcher.copy());
}
+
if (ability.subAbilities != null) {
this.subAbilities = new ArrayList<>();
for (Ability subAbility : ability.subAbilities) {
@@ -180,51 +178,59 @@ public abstract class AbilityImpl implements Ability {
boolean result = true;
//20100716 - 117.12
if (checkIfClause(game)) {
+ if (this instanceof TriggeredAbility) {
+ for (UUID modeId : this.getModes().getSelectedModes()) {
+ this.getModes().setActiveMode(modeId);
+ result = resolveMode(game);
+ }
+ } else {
+ result = resolveMode(game);
+ }
+ }
+ return result;
+ }
- for (Effect effect : getEffects()) {
- if (effect instanceof OneShotEffect) {
- boolean effectResult = effect.apply(game, this);
- result &= effectResult;
- if (logger.isDebugEnabled()) {
- if (this.getAbilityType() != AbilityType.MANA) {
- if (!effectResult) {
- if (this.getSourceId() != null) {
- MageObject mageObject = game.getObject(this.getSourceId());
- if (mageObject != null) {
- logger.debug("AbilityImpl.resolve: object: " + mageObject.getName());
- }
+ private boolean resolveMode(Game game) {
+ boolean result = true;
+ for (Effect effect : getEffects()) {
+ if (effect instanceof OneShotEffect) {
+ boolean effectResult = effect.apply(game, this);
+ result &= effectResult;
+ if (logger.isDebugEnabled()) {
+ if (this.getAbilityType() != AbilityType.MANA) {
+ if (!effectResult) {
+ if (this.getSourceId() != null) {
+ MageObject mageObject = game.getObject(this.getSourceId());
+ if (mageObject != null) {
+ logger.debug("AbilityImpl.resolve: object: " + mageObject.getName());
}
- logger.debug("AbilityImpl.resolve: effect returned false -" + effect.getText(this.getModes().getMode()));
}
+ logger.debug("AbilityImpl.resolve: effect returned false -" + effect.getText(this.getModes().getMode()));
}
}
- } else {
- game.addEffect((ContinuousEffect) effect, this);
- }
- /**
- * All restrained trigger events are fired now. To restrain the
- * events is mainly neccessary because of the movement of
- * multiple object at once. If the event is fired directly as
- * one object moved, other objects are not already in the
- * correct zone to check for their effects. (e.g. Valakut, the
- * Molten Pinnacle)
- */
- game.getState().handleSimultaneousEvent(game);
- game.resetShortLivingLKI();
- /**
- * game.applyEffects() has to be done at least for every effect
- * that moves cards/permanent between zones, or changes control
- * of objects so Static effects work as intened if dependant
- * from the moved objects zone it is in Otherwise for example
- * were static abilities with replacement effects deactivated
- * too late Example:
- * {@link org.mage.test.cards.replacement.DryadMilitantTest#testDiesByDestroy testDiesByDestroy}
- */
- if (effect.applyEffectsAfter()) {
- game.applyEffects();
- game.getState().getTriggers().checkStateTriggers(game);
}
+ } else {
+ game.addEffect((ContinuousEffect) effect, this);
}
+ /**
+ * All restrained trigger events are fired now. To restrain the
+ * events is mainly neccessary because of the movement of multiple
+ * object at once. If the event is fired directly as one object
+ * moved, other objects are not already in the correct zone to check
+ * for their effects. (e.g. Valakut, the Molten Pinnacle)
+ */
+ game.getState().handleSimultaneousEvent(game);
+ game.resetShortLivingLKI();
+ /**
+ * game.applyEffects() has to be done at least for every effect that
+ * moves cards/permanent between zones, or changes control of
+ * objects so Static effects work as intened if dependant from the
+ * moved objects zone it is in Otherwise for example were static
+ * abilities with replacement effects deactivated too late Example:
+ * {@link org.mage.test.cards.replacement.DryadMilitantTest#testDiesByDestroy testDiesByDestroy}
+ */
+ game.applyEffects();
+ game.getState().getTriggers().checkStateTriggers(game);
}
return result;
}
@@ -254,7 +260,7 @@ public abstract class AbilityImpl implements Ability {
/* 20130201 - 601.2b
* If the player wishes to splice any cards onto the spell (see rule 702.45), he
- * or she reveals those cards in his or her hand.
+ * or she reveals those cards in their hand.
*/
if (this.abilityType == AbilityType.SPELL) {
game.getContinuousEffects().applySpliceEffects(this, game);
@@ -317,7 +323,7 @@ public abstract class AbilityImpl implements Ability {
for (UUID modeId : this.getModes().getSelectedModes()) {
this.getModes().setActiveMode(modeId);
//20121001 - 601.2c
- // 601.2c The player announces his or her choice of an appropriate player, object, or zone for
+ // 601.2c The player announces their choice of an appropriate player, object, or zone for
// each target the spell requires. A spell may require some targets only if an alternative or
// additional cost (such as a buyback or kicker cost), or a particular mode, was chosen for it;
// otherwise, the spell is cast as though it did not require those targets. If the spell has a
@@ -625,11 +631,10 @@ public abstract class AbilityImpl implements Ability {
@Override
public void setControllerId(UUID controllerId) {
this.controllerId = controllerId;
- if (watchers != null) {
- for (Watcher watcher : watchers) {
- watcher.setControllerId(controllerId);
- }
+ for (Watcher watcher : watchers) {
+ watcher.setControllerId(controllerId);
}
+
if (subAbilities != null) {
for (Ability subAbility : subAbilities) {
subAbility.setControllerId(controllerId);
@@ -654,11 +659,10 @@ public abstract class AbilityImpl implements Ability {
subAbility.setSourceId(sourceId);
}
}
- if (watchers != null) {
- for (Watcher watcher : watchers) {
- watcher.setSourceId(sourceId);
- }
+ for (Watcher watcher : watchers) {
+ watcher.setSourceId(sourceId);
}
+
}
@Override
@@ -720,18 +724,12 @@ public abstract class AbilityImpl implements Ability {
@Override
public List getWatchers() {
- if (watchers != null) {
- return watchers;
- } else {
- return emptyWatchers;
- }
+ return watchers;
}
@Override
public void addWatcher(Watcher watcher) {
- if (watchers == null) {
- watchers = new ArrayList<>();
- }
+
watcher.setSourceId(this.sourceId);
watcher.setControllerId(this.controllerId);
watchers.add(watcher);
@@ -935,8 +933,8 @@ public abstract class AbilityImpl implements Ability {
return true;
}
MageObject object = game.getObject(this.getSourceId());
- // emblem are always actual
- if (object != null && object instanceof Emblem) {
+ // emblem/planes are always actual
+ if (object != null && (object instanceof Emblem || object instanceof Plane)) {
return true;
}
}
diff --git a/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java b/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java
index 0c63d4595b..5ef80ab0f1 100644
--- a/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java
+++ b/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java
@@ -45,6 +45,7 @@ import mage.constants.TimingRule;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.command.Emblem;
+import mage.game.command.Plane;
import mage.game.permanent.Permanent;
import mage.util.CardUtil;
@@ -219,7 +220,7 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa
}
//20091005 - 602.5d/602.5e
if (timing == TimingRule.INSTANT || game.canPlaySorcery(playerId)
- || game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_AS_INSTANT, this, controllerId, game)) {
+ || null != game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_AS_INSTANT, this, controllerId, game)) {
if (costs.canPay(this, sourceId, playerId, game) && canChooseTarget(game)) {
this.activatorId = playerId;
return true;
@@ -240,10 +241,10 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa
MageObject mageObject = game.getObject(this.sourceId);
if (mageObject instanceof Emblem) {
return ((Emblem) mageObject).getControllerId().equals(playerId);
- } else {
- if (game.getState().getZone(this.sourceId) != Zone.BATTLEFIELD) {
- return ((Card) mageObject).getOwnerId().equals(playerId);
- }
+ } else if (mageObject instanceof Plane) {
+ return ((Plane) mageObject).getControllerId().equals(playerId);
+ } else if (game.getState().getZone(this.sourceId) != Zone.BATTLEFIELD) {
+ return ((Card) mageObject).getOwnerId().equals(playerId);
}
}
return false;
diff --git a/Mage/src/main/java/mage/abilities/Modes.java b/Mage/src/main/java/mage/abilities/Modes.java
index c942f58c36..40b2f3b6a1 100644
--- a/Mage/src/main/java/mage/abilities/Modes.java
+++ b/Mage/src/main/java/mage/abilities/Modes.java
@@ -51,13 +51,13 @@ import mage.target.common.TargetOpponent;
public class Modes extends LinkedHashMap {
private Mode currentMode; // the current mode of the selected modes
- private final ArrayList selectedModes = new ArrayList<>();
+ private final List selectedModes = new ArrayList<>();
private int minModes;
private int maxModes;
private TargetController modeChooser;
private boolean eachModeMoreThanOnce; // each mode can be selected multiple times during one choice
private boolean eachModeOnlyOnce; // state if each mode can be chosen only once as long as the source object exists
- private final LinkedHashMap duplicateModes = new LinkedHashMap<>();
+ private final Map duplicateModes = new LinkedHashMap<>();
private OptionalAdditionalModeSourceCosts optionalAdditionalModeSourceCosts = null; // only set if costs have to be paid
private Filter maxModesFilter = null; // calculates the max number of available modes
@@ -139,7 +139,7 @@ public class Modes extends LinkedHashMap {
return null;
}
- public ArrayList getSelectedModes() {
+ public List getSelectedModes() {
return selectedModes;
}
@@ -292,7 +292,7 @@ public class Modes extends LinkedHashMap {
* @param source
* @param game
*/
- private void setAlreadySelectedModes(ArrayList selectedModes, Ability source, Game game) {
+ private void setAlreadySelectedModes(List selectedModes, Ability source, Game game) {
for (UUID modeId : selectedModes) {
String key = getKey(source, game, modeId);
game.getState().setValue(key, true);
diff --git a/Mage/src/main/java/mage/abilities/PlayLandAbility.java b/Mage/src/main/java/mage/abilities/PlayLandAbility.java
index 31fd0702bc..5aa10fb6cd 100644
--- a/Mage/src/main/java/mage/abilities/PlayLandAbility.java
+++ b/Mage/src/main/java/mage/abilities/PlayLandAbility.java
@@ -52,7 +52,7 @@ public class PlayLandAbility extends ActivatedAbilityImpl {
@Override
public boolean canActivate(UUID playerId, Game game) {
if (!controlsAbility(playerId, game)
- && !game.getContinuousEffects().asThough(getSourceId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, playerId, game)) {
+ && null == game.getContinuousEffects().asThough(getSourceId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, playerId, game)) {
return false;
}
//20091005 - 114.2a
diff --git a/Mage/src/main/java/mage/abilities/SpecialActions.java b/Mage/src/main/java/mage/abilities/SpecialActions.java
index 72a5eb444c..66906d5948 100644
--- a/Mage/src/main/java/mage/abilities/SpecialActions.java
+++ b/Mage/src/main/java/mage/abilities/SpecialActions.java
@@ -28,7 +28,6 @@
package mage.abilities;
-import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.UUID;
diff --git a/Mage/src/main/java/mage/abilities/SpellAbility.java b/Mage/src/main/java/mage/abilities/SpellAbility.java
index 289fa05592..84491fb009 100644
--- a/Mage/src/main/java/mage/abilities/SpellAbility.java
+++ b/Mage/src/main/java/mage/abilities/SpellAbility.java
@@ -92,15 +92,15 @@ public class SpellAbility extends ActivatedAbilityImpl {
@Override
public boolean canActivate(UUID playerId, Game game) {
- if (game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.CAST_AS_INSTANT, this, playerId, game) // check this first to allow Offering in main phase
+ if (null != game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.CAST_AS_INSTANT, this, playerId, game) // check this first to allow Offering in main phase
|| this.spellCanBeActivatedRegularlyNow(playerId, game)) {
if (spellAbilityType == SpellAbilityType.SPLIT || spellAbilityType == SpellAbilityType.SPLIT_AFTERMATH) {
return false;
}
// fix for Gitaxian Probe and casting opponent's spells
- if (!game.getContinuousEffects().asThough(getSourceId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, playerId, game)) {
+ if (null == game.getContinuousEffects().asThough(getSourceId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, playerId, game)) {
Card card = game.getCard(sourceId);
- if (!(card != null && card.getOwnerId() == playerId)) {
+ if (!(card != null && card.getOwnerId().equals(playerId))) {
return false;
}
}
diff --git a/Mage/src/main/java/mage/abilities/TriggeredAbilities.java b/Mage/src/main/java/mage/abilities/TriggeredAbilities.java
index 5feca7f7af..c04367f557 100644
--- a/Mage/src/main/java/mage/abilities/TriggeredAbilities.java
+++ b/Mage/src/main/java/mage/abilities/TriggeredAbilities.java
@@ -28,6 +28,8 @@
*/
package mage.abilities;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
import mage.MageObject;
import mage.constants.Zone;
import mage.game.Game;
@@ -36,15 +38,12 @@ import mage.game.events.NumberOfTriggersEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-
/**
* @author BetaSteward_at_googlemail.com
- *
- * This class uses ConcurrentHashMap to avoid ConcurrentModificationExceptions.
- * See ticket https://github.com/magefree/mage/issues/966 and
- * https://github.com/magefree/mage/issues/473
+ *
+ * This class uses ConcurrentHashMap to avoid ConcurrentModificationExceptions.
+ * See ticket https://github.com/magefree/mage/issues/966 and
+ * https://github.com/magefree/mage/issues/473
*/
public class TriggeredAbilities extends ConcurrentHashMap {
@@ -63,7 +62,7 @@ public class TriggeredAbilities extends ConcurrentHashMap it = this.values().iterator(); it.hasNext(); ) {
+ for (Iterator it = this.values().iterator(); it.hasNext();) {
TriggeredAbility ability = it.next();
if (ability instanceof StateTriggeredAbility && ((StateTriggeredAbility) ability).canTrigger(game)) {
checkTrigger(ability, null, game);
@@ -72,7 +71,7 @@ public class TriggeredAbilities extends ConcurrentHashMap it = this.values().iterator(); it.hasNext(); ) {
+ for (Iterator it = this.values().iterator(); it.hasNext();) {
TriggeredAbility ability = it.next();
if (ability.checkEventType(event, game)) {
checkTrigger(ability, event, game);
@@ -98,7 +97,10 @@ public class TriggeredAbilities extends ConcurrentHashMap so it should work
+ && !ability.getWorksFaceDown()) { // the ability is declared to work also face down
+ // Not all triggered abilities of face down creatures work if they are faced down
return;
}
controllerSet = true;
@@ -130,8 +132,8 @@ public class TriggeredAbilities extends ConcurrentHashMap key.endsWith(sourceId.toString()));
}
@@ -171,6 +172,10 @@ public class TriggeredAbilities extends ConcurrentHashMap= minAttackers;
}
- return attackerCount >= minAttackers && game.getCombat().getAttackingPlayerId().equals(getControllerId());
+ return false;
}
@Override
public String getRule() {
- StringBuilder sb = new StringBuilder("Whenever you attack with " + minAttackers + " or more ");
+ StringBuilder sb = new StringBuilder("Whenever you attack with " + CardUtil.numberToText(minAttackers) + " or more ");
sb.append(filter.getMessage());
sb.append(", ");
sb.append(super.getRule());
diff --git a/Mage/src/main/java/mage/abilities/common/BeginningOfEndStepTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/BeginningOfEndStepTriggeredAbility.java
index 748ac55fd5..a0c07ba769 100644
--- a/Mage/src/main/java/mage/abilities/common/BeginningOfEndStepTriggeredAbility.java
+++ b/Mage/src/main/java/mage/abilities/common/BeginningOfEndStepTriggeredAbility.java
@@ -27,6 +27,7 @@
*/
package mage.abilities.common;
+import java.util.Locale;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.condition.Condition;
import mage.abilities.effects.Effect;
@@ -129,9 +130,9 @@ public class BeginningOfEndStepTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
StringBuilder sb = new StringBuilder(getEffects().getText(modes.getMode()));
if (this.optional) {
- if (sb.substring(0, 6).toLowerCase().equals("target")) {
+ if (sb.substring(0, 6).toLowerCase(Locale.ENGLISH).equals("target")) {
sb.insert(0, "you may have ");
- } else if (!sb.substring(0, 4).toLowerCase().equals("you ")) {
+ } else if (!sb.substring(0, 4).toLowerCase(Locale.ENGLISH).equals("you ")) {
sb.insert(0, "you may ");
}
}
diff --git a/Mage/src/main/java/mage/abilities/common/BeginningOfUpkeepTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/BeginningOfUpkeepTriggeredAbility.java
index 51a6c378ef..47ad9fbf81 100644
--- a/Mage/src/main/java/mage/abilities/common/BeginningOfUpkeepTriggeredAbility.java
+++ b/Mage/src/main/java/mage/abilities/common/BeginningOfUpkeepTriggeredAbility.java
@@ -27,6 +27,7 @@
*/
package mage.abilities.common;
+import java.util.Locale;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.constants.TargetController;
@@ -141,9 +142,9 @@ public class BeginningOfUpkeepTriggeredAbility extends TriggeredAbilityImpl {
switch (targetController) {
case YOU:
if (this.optional) {
- if (sb.substring(0, 6).toLowerCase().equals("target")) {
+ if (sb.substring(0, 6).toLowerCase(Locale.ENGLISH).equals("target")) {
sb.insert(0, "you may have ");
- } else if (!sb.substring(0, 4).toLowerCase().equals("you ")) {
+ } else if (!sb.substring(0, 4).toLowerCase(Locale.ENGLISH).equals("you ")) {
sb.insert(0, "you may ");
}
}
@@ -151,7 +152,7 @@ public class BeginningOfUpkeepTriggeredAbility extends TriggeredAbilityImpl {
case OPPONENT:
return sb.insert(0, generateZoneString()).insert(0, "At the beginning of each opponent's upkeep, ").toString();
case ANY:
- return sb.insert(0, generateZoneString()).insert(0, "At the beginning of each player's upkeep, ").toString();
+ return sb.insert(0, generateZoneString()).insert(0, "At the beginning of each upkeep, ").toString();
case CONTROLLER_ATTACHED_TO:
return sb.insert(0, generateZoneString()).insert(0, "At the beginning of the upkeep of enchanted creature's controller, ").toString();
}
diff --git a/Mage/src/main/java/mage/abilities/common/BlocksOrBecomesBlockedTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/BlocksOrBecomesBlockedTriggeredAbility.java
index dc0262bab6..24606307cd 100644
--- a/Mage/src/main/java/mage/abilities/common/BlocksOrBecomesBlockedTriggeredAbility.java
+++ b/Mage/src/main/java/mage/abilities/common/BlocksOrBecomesBlockedTriggeredAbility.java
@@ -48,7 +48,7 @@ public class BlocksOrBecomesBlockedTriggeredAbility extends TriggeredAbilityImpl
protected boolean setTargetPointer;
public BlocksOrBecomesBlockedTriggeredAbility(Effect effect, boolean optional) {
- this(effect, StaticFilters.FILTER_PERMANENT_CREATURE, optional, null, false);
+ this(effect, StaticFilters.FILTER_PERMANENT_CREATURE, optional, null, true);
}
public BlocksOrBecomesBlockedTriggeredAbility(Effect effect, FilterPermanent filter, boolean optional) {
@@ -85,7 +85,7 @@ public class BlocksOrBecomesBlockedTriggeredAbility extends TriggeredAbilityImpl
Permanent blocked = game.getPermanent(event.getTargetId());
if (blocked != null && filter.match(blocked, game)) {
if (setTargetPointer) {
- this.getEffects().setTargetPointer(new FixedTarget(event.getTargetId()));
+ this.getEffects().setTargetPointer(new FixedTarget(blocked, game));
}
return true;
}
@@ -94,7 +94,7 @@ public class BlocksOrBecomesBlockedTriggeredAbility extends TriggeredAbilityImpl
Permanent blocker = game.getPermanent(event.getSourceId());
if (blocker != null && filter.match(blocker, game)) {
if (setTargetPointer) {
- this.getEffects().setTargetPointer(new FixedTarget(event.getSourceId()));
+ this.getEffects().setTargetPointer(new FixedTarget(blocker, game));
}
return true;
}
diff --git a/Mage/src/main/java/mage/abilities/common/DealsDamageGainLifeSourceTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/DealsDamageGainLifeSourceTriggeredAbility.java
index 246445e312..a44b2b1b04 100644
--- a/Mage/src/main/java/mage/abilities/common/DealsDamageGainLifeSourceTriggeredAbility.java
+++ b/Mage/src/main/java/mage/abilities/common/DealsDamageGainLifeSourceTriggeredAbility.java
@@ -103,7 +103,7 @@ class GainThatMuchLifeEffect extends OneShotEffect {
if (controller != null) {
int amount = (Integer) getValue("damage");
if (amount > 0) {
- controller.gainLife(amount, game);
+ controller.gainLife(amount, game, source);
}
return true;
diff --git a/Mage/src/main/java/mage/abilities/common/DealsDamageToAPlayerAllTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/DealsDamageToAPlayerAllTriggeredAbility.java
index 4dcca733cd..aa57b85dc1 100644
--- a/Mage/src/main/java/mage/abilities/common/DealsDamageToAPlayerAllTriggeredAbility.java
+++ b/Mage/src/main/java/mage/abilities/common/DealsDamageToAPlayerAllTriggeredAbility.java
@@ -47,12 +47,18 @@ public class DealsDamageToAPlayerAllTriggeredAbility extends TriggeredAbilityImp
private final FilterPermanent filter;
private final SetTargetPointer setTargetPointer;
private final boolean onlyCombat;
+ private final boolean affectsDefendingPlayer;
public DealsDamageToAPlayerAllTriggeredAbility(Effect effect, FilterPermanent filter, boolean optional, SetTargetPointer setTargetPointer, boolean onlyCombat) {
+ this(effect, filter, optional, setTargetPointer, onlyCombat, false);
+ }
+
+ public DealsDamageToAPlayerAllTriggeredAbility(Effect effect, FilterPermanent filter, boolean optional, SetTargetPointer setTargetPointer, boolean onlyCombat, boolean affectsDefendingPlayer) {
super(Zone.BATTLEFIELD, effect, optional);
this.setTargetPointer = setTargetPointer;
this.filter = filter;
this.onlyCombat = onlyCombat;
+ this.affectsDefendingPlayer = affectsDefendingPlayer;
}
public DealsDamageToAPlayerAllTriggeredAbility(final DealsDamageToAPlayerAllTriggeredAbility ability) {
@@ -60,6 +66,7 @@ public class DealsDamageToAPlayerAllTriggeredAbility extends TriggeredAbilityImp
this.setTargetPointer = ability.setTargetPointer;
this.filter = ability.filter;
this.onlyCombat = ability.onlyCombat;
+ this.affectsDefendingPlayer = ability.affectsDefendingPlayer;
}
@Override
@@ -81,6 +88,10 @@ public class DealsDamageToAPlayerAllTriggeredAbility extends TriggeredAbilityImp
for (Effect effect : this.getEffects()) {
effect.setValue("damage", event.getAmount());
effect.setValue("sourceId", event.getSourceId());
+ if (affectsDefendingPlayer) {
+ effect.setTargetPointer(new FixedTarget(event.getTargetId()));
+ continue;
+ }
switch (setTargetPointer) {
case PLAYER:
effect.setTargetPointer(new FixedTarget(permanent.getControllerId()));
diff --git a/Mage/src/main/java/mage/abilities/common/DealtDamageAndDiedTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/DealtDamageAndDiedTriggeredAbility.java
index bb080f081d..96684e01d3 100644
--- a/Mage/src/main/java/mage/abilities/common/DealtDamageAndDiedTriggeredAbility.java
+++ b/Mage/src/main/java/mage/abilities/common/DealtDamageAndDiedTriggeredAbility.java
@@ -3,7 +3,9 @@ package mage.abilities.common;
import mage.MageObjectReference;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
+import mage.constants.SetTargetPointer;
import mage.constants.Zone;
+import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
@@ -13,23 +15,30 @@ import mage.target.targetpointer.FixedTarget;
public class DealtDamageAndDiedTriggeredAbility extends TriggeredAbilityImpl {
private final FilterCreaturePermanent filter;
+ protected SetTargetPointer setTargetPointer;
public DealtDamageAndDiedTriggeredAbility(Effect effect) {
this(effect, false);
}
public DealtDamageAndDiedTriggeredAbility(Effect effect, boolean optional) {
- this(effect, optional, new FilterCreaturePermanent());
+ this(effect, optional, StaticFilters.FILTER_PERMANENT_CREATURE);
}
public DealtDamageAndDiedTriggeredAbility(Effect effect, boolean optional, FilterCreaturePermanent filter) {
+ this(effect, optional, filter, SetTargetPointer.PERMANENT);
+ }
+
+ public DealtDamageAndDiedTriggeredAbility(Effect effect, boolean optional, FilterCreaturePermanent filter, SetTargetPointer setTargetPointer) {
super(Zone.ALL, effect, optional);
this.filter = filter;
+ this.setTargetPointer = setTargetPointer;
}
public DealtDamageAndDiedTriggeredAbility(final DealtDamageAndDiedTriggeredAbility ability) {
super(ability);
this.filter = ability.filter;
+ this.setTargetPointer = ability.setTargetPointer;
}
@Override
@@ -55,8 +64,10 @@ public class DealtDamageAndDiedTriggeredAbility extends TriggeredAbilityImpl {
}
}
if (damageDealt) {
- for (Effect effect : getEffects()) {
- effect.setTargetPointer(new FixedTarget(event.getTargetId()));
+ if(this.setTargetPointer == SetTargetPointer.PERMANENT) {
+ for (Effect effect : getEffects()) {
+ effect.setTargetPointer(new FixedTarget(event.getTargetId()));
+ }
}
return true;
}
diff --git a/Mage/src/main/java/mage/abilities/common/DrawCardControllerTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/DrawCardControllerTriggeredAbility.java
index 0fdc859092..149623280f 100644
--- a/Mage/src/main/java/mage/abilities/common/DrawCardControllerTriggeredAbility.java
+++ b/Mage/src/main/java/mage/abilities/common/DrawCardControllerTriggeredAbility.java
@@ -27,9 +27,9 @@
*/
package mage.abilities.common;
-import mage.constants.Zone;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
+import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
@@ -37,10 +37,14 @@ import mage.game.events.GameEvent;
*
* @author North
*/
-public class DrawCardControllerTriggeredAbility extends TriggeredAbilityImpl {
+public class DrawCardControllerTriggeredAbility extends TriggeredAbilityImpl {
public DrawCardControllerTriggeredAbility(Effect effect, boolean optional) {
- super(Zone.BATTLEFIELD, effect, optional);
+ this(Zone.BATTLEFIELD, effect, optional);
+ }
+
+ public DrawCardControllerTriggeredAbility(Zone zone, Effect effect, boolean optional) {
+ super(zone, effect, optional);
}
public DrawCardControllerTriggeredAbility(final DrawCardControllerTriggeredAbility ability) {
@@ -66,4 +70,4 @@ public class DrawCardControllerTriggeredAbility extends TriggeredAbilityImpl {
public DrawCardControllerTriggeredAbility copy() {
return new DrawCardControllerTriggeredAbility(this);
}
-}
\ No newline at end of file
+}
diff --git a/Mage/src/main/java/mage/abilities/common/EnchantedCreatureBlockedTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/EnchantedCreatureBlockedTriggeredAbility.java
new file mode 100644
index 0000000000..135ad0111e
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/common/EnchantedCreatureBlockedTriggeredAbility.java
@@ -0,0 +1,79 @@
+/*
+ * 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.abilities.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;
+import mage.target.targetpointer.FixedTarget;
+
+/**
+ *
+ * @author L_J
+ */
+public class EnchantedCreatureBlockedTriggeredAbility extends TriggeredAbilityImpl {
+
+ public EnchantedCreatureBlockedTriggeredAbility(Effect effect, boolean optional) {
+ super(Zone.BATTLEFIELD, effect, optional);
+ }
+
+ public EnchantedCreatureBlockedTriggeredAbility(final EnchantedCreatureBlockedTriggeredAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public boolean checkEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.CREATURE_BLOCKED;
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ Permanent equipment = game.getPermanent(sourceId);
+ if (equipment != null && equipment.getAttachedTo() != null) {
+ Permanent equipped = game.getPermanent(equipment.getAttachedTo());
+ if (equipped.getId().equals(event.getTargetId())) {
+ getEffects().get(1).setTargetPointer(new FixedTarget(equipped, game));
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getRule() {
+ return "Whenever enchanted creature becomes blocked by a creature, " + super.getRule();
+ }
+
+ @Override
+ public EnchantedCreatureBlockedTriggeredAbility copy() {
+ return new EnchantedCreatureBlockedTriggeredAbility(this);
+ }
+}
diff --git a/Mage/src/main/java/mage/abilities/common/LandfallAbility.java b/Mage/src/main/java/mage/abilities/common/LandfallAbility.java
index d976c24845..59be3d43d8 100644
--- a/Mage/src/main/java/mage/abilities/common/LandfallAbility.java
+++ b/Mage/src/main/java/mage/abilities/common/LandfallAbility.java
@@ -29,7 +29,6 @@ package mage.abilities.common;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
-import mage.constants.CardType;
import mage.constants.SetTargetPointer;
import mage.constants.Zone;
import mage.game.Game;
diff --git a/Mage/src/main/java/mage/abilities/common/LegendarySpellAbility.java b/Mage/src/main/java/mage/abilities/common/LegendarySpellAbility.java
new file mode 100644
index 0000000000..ca0604d846
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/common/LegendarySpellAbility.java
@@ -0,0 +1,26 @@
+package mage.abilities.common;
+
+import mage.abilities.condition.common.LegendaryCondition;
+import mage.constants.Zone;
+
+/**
+ * @author JRHerlehy
+ * Created on 4/8/18.
+ */
+public class LegendarySpellAbility extends SimpleStaticAbility {
+
+ public LegendarySpellAbility() {
+ super(Zone.ALL, new CastOnlyIfConditionIsTrueEffect(LegendaryCondition.instance));
+ this.setRuleAtTheTop(true);
+ this.getEffects().get(0).setText("(You may cast a legendary sorcery only if you control a legendary creature or planeswalker.)");
+ }
+
+ private LegendarySpellAbility(final LegendarySpellAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public LegendarySpellAbility copy() {
+ return new LegendarySpellAbility(this);
+ }
+}
diff --git a/Mage/src/main/java/mage/abilities/common/OpponentSacrificesNonTokenPermanentTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/OpponentSacrificesNonTokenPermanentTriggeredAbility.java
index 80388d591e..271cc11bd1 100644
--- a/Mage/src/main/java/mage/abilities/common/OpponentSacrificesNonTokenPermanentTriggeredAbility.java
+++ b/Mage/src/main/java/mage/abilities/common/OpponentSacrificesNonTokenPermanentTriggeredAbility.java
@@ -1,16 +1,16 @@
/*
* Copyright 2011 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.
@@ -53,12 +53,10 @@ public class OpponentSacrificesNonTokenPermanentTriggeredAbility extends Trigger
@Override
public boolean checkTrigger(GameEvent event, Game game) {
- if (game.getPlayer(getControllerId()).hasOpponent(event.getPlayerId(), game)) {
+ if (game.getPlayer(getControllerId()).hasOpponent(event.getPlayerId(), game)) {
Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD);
- if (permanent != null && !(permanent instanceof PermanentToken) ) {
- for (Effect effect : getEffects()) {
- effect.setTargetPointer(new FixedTarget(event.getTargetId()));
- }
+ if (permanent != null && !(permanent instanceof PermanentToken)) {
+ getEffects().setTargetPointer(new FixedTarget(event.getTargetId(), game.getState().getZoneChangeCounter(event.getTargetId())));
return true;
}
}
@@ -75,4 +73,4 @@ public class OpponentSacrificesNonTokenPermanentTriggeredAbility extends Trigger
return new OpponentSacrificesNonTokenPermanentTriggeredAbility(this);
}
-}
\ No newline at end of file
+}
diff --git a/Mage/src/main/java/mage/abilities/common/SagaAbility.java b/Mage/src/main/java/mage/abilities/common/SagaAbility.java
new file mode 100644
index 0000000000..6a37d2cdad
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/common/SagaAbility.java
@@ -0,0 +1,217 @@
+/*
+ * 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.abilities.common;
+
+import mage.abilities.Ability;
+import mage.abilities.TriggeredAbilityImpl;
+import mage.abilities.effects.Effect;
+import mage.abilities.effects.common.counter.AddCountersSourceEffect;
+import mage.cards.Card;
+import mage.cards.CardImpl;
+import mage.constants.SagaChapter;
+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;
+import mage.game.stack.StackAbility;
+import mage.game.stack.StackObject;
+
+/**
+ *
+ * @author LevelX2
+ */
+public class SagaAbility extends TriggeredAbilityImpl {
+
+ private SagaChapter maxChapter;
+
+ public SagaAbility(Card card, SagaChapter maxChapter) {
+ super(Zone.ALL, new AddCountersSourceEffect(CounterType.LORE.createInstance()), false);
+ this.usesStack = false;
+ this.maxChapter = maxChapter;
+ this.setRuleVisible(false);
+ ((CardImpl) card).addAbility(new SagaAddCounterAbility(maxChapter));
+
+ }
+
+ public SagaAbility(final SagaAbility ability) {
+ super(ability);
+ this.maxChapter = ability.maxChapter;
+ }
+
+ @Override
+ public boolean checkEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD;
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ return event.getTargetId().equals(getSourceId());
+ }
+
+ @Override
+ public String getRule() {
+ return "When {this} enters the battlefield, " + super.getRule();
+ }
+
+ public Ability addChapterEffect(Card card, SagaChapter chapter, Effect effect) {
+ return addChapterEffect(card, chapter, chapter, effect);
+ }
+
+ public Ability addChapterEffect(Card card, SagaChapter fromChapter, SagaChapter toChapter, Effect effect) {
+ ChapterTriggeredAbility ability = new ChapterTriggeredAbility(effect, fromChapter, toChapter);
+ ((CardImpl) card).addAbility(ability);
+ if (maxChapter == null || toChapter.getNumber() > maxChapter.getNumber()) {
+ maxChapter = toChapter;
+ }
+ return ability;
+ }
+
+ public SagaChapter getMaxChapter() {
+ return maxChapter;
+ }
+
+ @Override
+ public SagaAbility copy() {
+ return new SagaAbility(this);
+ }
+
+ public static boolean isChapterAbility(StackObject stackObject) {
+ if (stackObject instanceof StackAbility) {
+ return ((StackAbility) stackObject).getStackAbility() instanceof ChapterTriggeredAbility;
+ }
+ return false;
+ }
+}
+
+class ChapterTriggeredAbility extends TriggeredAbilityImpl {
+
+ SagaChapter chapterFrom, chapterTo;
+
+ public ChapterTriggeredAbility(Effect effect, SagaChapter chapterFrom, SagaChapter chapterTo) {
+ super(Zone.BATTLEFIELD, effect, false);
+ this.chapterFrom = chapterFrom;
+ this.chapterTo = chapterTo;
+ }
+
+ public ChapterTriggeredAbility(final ChapterTriggeredAbility ability) {
+ super(ability);
+ this.chapterFrom = ability.chapterFrom;
+ this.chapterTo = ability.chapterTo;
+ }
+
+ @Override
+ public boolean checkEventType(GameEvent event, Game game) {
+ return event.getType() == EventType.COUNTER_ADDED;
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ if (event.getTargetId().equals(getSourceId()) && event.getData().equals(CounterType.LORE.getName())) {
+ Permanent sourceSaga = game.getPermanentOrLKIBattlefield(getSourceId());
+ if (sourceSaga != null) {
+ int loreCounters = sourceSaga.getCounters(game).getCount(CounterType.LORE);
+ return chapterFrom.getNumber() <= loreCounters
+ && chapterTo.getNumber() >= loreCounters;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public ChapterTriggeredAbility copy() {
+ return new ChapterTriggeredAbility(this);
+ }
+
+ public String getChapterRule() {
+ String rule = super.getRule();
+ return Character.toUpperCase(rule.charAt(0)) + rule.substring(1);
+ }
+
+ public SagaChapter getChapterFrom() {
+ return chapterFrom;
+ }
+
+ public SagaChapter getChapterTo() {
+ return chapterTo;
+ }
+
+ @Override
+ public String getRule() {
+ StringBuilder sb = new StringBuilder();
+ for (SagaChapter chapter : SagaChapter.values()) {
+ if (chapter.getNumber() >= getChapterFrom().getNumber()
+ && chapter.getNumber() < getChapterTo().getNumber()) {
+ sb.append(chapter.toString()).append(", ");
+ } else if (chapter.equals(getChapterTo())) {
+ sb.append(chapter.toString());
+ }
+ }
+ String text = super.getRule();
+ sb.append(": ").append(Character.toUpperCase(text.charAt(0))).append(text.substring(1));
+ return sb.toString();
+ }
+}
+
+class SagaAddCounterAbility extends TriggeredAbilityImpl {
+
+ SagaChapter maxChapter;
+
+ SagaAddCounterAbility(SagaChapter maxChapter) {
+ super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.LORE.createInstance()), false);
+ this.usesStack = false;
+ this.maxChapter = maxChapter;
+ }
+
+ SagaAddCounterAbility(final SagaAddCounterAbility ability) {
+ super(ability);
+ this.maxChapter = ability.maxChapter;
+ }
+
+ @Override
+ public SagaAddCounterAbility copy() {
+ return new SagaAddCounterAbility(this);
+ }
+
+ @Override
+ public boolean checkEventType(GameEvent event, Game game) {
+ return event.getType() == EventType.PRECOMBAT_MAIN_PHASE_PRE;
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ return event.getPlayerId().equals(this.controllerId);
+ }
+
+ @Override
+ public String getRule() {
+ return "(As this Saga enters and after your draw step, add a lore counter. Sacrifice after " + maxChapter.toString() + ".) ";
+ }
+
+}
diff --git a/Mage/src/main/java/mage/abilities/common/TapLandForManaAllTriggeredManaAbility.java b/Mage/src/main/java/mage/abilities/common/TapLandForManaAllTriggeredManaAbility.java
index 6de0cf8a90..eda1c525ba 100644
--- a/Mage/src/main/java/mage/abilities/common/TapLandForManaAllTriggeredManaAbility.java
+++ b/Mage/src/main/java/mage/abilities/common/TapLandForManaAllTriggeredManaAbility.java
@@ -30,7 +30,6 @@ package mage.abilities.common;
import mage.abilities.effects.common.ManaEffect;
import mage.abilities.mana.TriggeredManaAbility;
-import mage.constants.CardType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
diff --git a/Mage/src/main/java/mage/abilities/condition/common/AnyPlayerControlsCondition.java b/Mage/src/main/java/mage/abilities/condition/common/AnyPlayerControlsCondition.java
new file mode 100644
index 0000000000..5a7434da34
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/condition/common/AnyPlayerControlsCondition.java
@@ -0,0 +1,50 @@
+/*
+ * 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.abilities.condition.common;
+
+import mage.abilities.Ability;
+import mage.abilities.condition.Condition;
+import mage.filter.FilterPermanent;
+import mage.game.Game;
+
+/**
+ * @author North
+ */
+public class AnyPlayerControlsCondition implements Condition {
+
+ private final FilterPermanent filter;
+
+ public AnyPlayerControlsCondition(FilterPermanent filter) {
+ this.filter = filter;
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ return game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game) > 0;
+ }
+}
diff --git a/Mage/src/main/java/mage/abilities/condition/common/CardsInControllerGraveCondition.java b/Mage/src/main/java/mage/abilities/condition/common/CardsInControllerGraveCondition.java
index d85f78d39b..94500ee918 100644
--- a/Mage/src/main/java/mage/abilities/condition/common/CardsInControllerGraveCondition.java
+++ b/Mage/src/main/java/mage/abilities/condition/common/CardsInControllerGraveCondition.java
@@ -8,7 +8,7 @@ import mage.players.Player;
import mage.util.CardUtil;
/**
- * Condition for - Controller has X or more cards in his or her graveyard
+ * Condition for - Controller has X or more cards in their graveyard
*
* @author LevelX2
*/
diff --git a/Mage/src/main/java/mage/abilities/condition/common/CardsInOpponentGraveCondition.java b/Mage/src/main/java/mage/abilities/condition/common/CardsInOpponentGraveCondition.java
index 1c2d203d2c..5a683073b8 100644
--- a/Mage/src/main/java/mage/abilities/condition/common/CardsInOpponentGraveCondition.java
+++ b/Mage/src/main/java/mage/abilities/condition/common/CardsInOpponentGraveCondition.java
@@ -9,7 +9,7 @@ import java.util.UUID;
/**
* Condition for -
- * Any opponent has X or more cards in his or her graveyard
+ * Any opponent has X or more cards in their graveyard
* @author Loki
*/
public class CardsInOpponentGraveCondition implements Condition {
diff --git a/Mage/src/main/java/mage/abilities/condition/common/DeliriumCondition.java b/Mage/src/main/java/mage/abilities/condition/common/DeliriumCondition.java
index 1c53500544..260e43e4f5 100644
--- a/Mage/src/main/java/mage/abilities/condition/common/DeliriumCondition.java
+++ b/Mage/src/main/java/mage/abilities/condition/common/DeliriumCondition.java
@@ -28,7 +28,6 @@
package mage.abilities.condition.common;
import java.util.EnumSet;
-import java.util.HashSet;
import mage.abilities.Ability;
import mage.abilities.condition.Condition;
import mage.cards.Card;
diff --git a/Mage/src/main/java/mage/abilities/condition/common/EnchantedSourceCondition.java b/Mage/src/main/java/mage/abilities/condition/common/EnchantedSourceCondition.java
index e405cb7b06..8e78b1c546 100644
--- a/Mage/src/main/java/mage/abilities/condition/common/EnchantedSourceCondition.java
+++ b/Mage/src/main/java/mage/abilities/condition/common/EnchantedSourceCondition.java
@@ -30,7 +30,6 @@ package mage.abilities.condition.common;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.condition.Condition;
-import mage.constants.CardType;
import mage.game.Game;
import mage.game.permanent.Permanent;
diff --git a/Mage/src/main/java/mage/abilities/condition/common/EnchantedTargetCondition.java b/Mage/src/main/java/mage/abilities/condition/common/EnchantedTargetCondition.java
index 663160ea4f..8eff5fb51d 100644
--- a/Mage/src/main/java/mage/abilities/condition/common/EnchantedTargetCondition.java
+++ b/Mage/src/main/java/mage/abilities/condition/common/EnchantedTargetCondition.java
@@ -4,7 +4,6 @@ import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.condition.Condition;
-import mage.constants.CardType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.Target;
diff --git a/Mage/src/main/java/mage/abilities/condition/common/IsStillOnPlaneCondition.java b/Mage/src/main/java/mage/abilities/condition/common/IsStillOnPlaneCondition.java
new file mode 100644
index 0000000000..8c811de610
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/condition/common/IsStillOnPlaneCondition.java
@@ -0,0 +1,61 @@
+/*
+ * 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.abilities.condition.common;
+
+import mage.abilities.Ability;
+import mage.abilities.condition.Condition;
+import mage.game.Game;
+import mage.game.command.Plane;
+
+/**
+ * @author spjspj
+ */
+public class IsStillOnPlaneCondition implements Condition {
+
+ private String planeName;
+
+ public IsStillOnPlaneCondition(String planeName) {
+ this.planeName = planeName;
+ }
+
+ public IsStillOnPlaneCondition(IsStillOnPlaneCondition condition) {
+ this.planeName = condition.planeName;
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+
+ Plane plane = game.getState().getCurrentPlane();
+ if (plane != null) {
+ if (plane.getName().equalsIgnoreCase(planeName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/Mage/src/main/java/mage/abilities/condition/common/LegendaryCondition.java b/Mage/src/main/java/mage/abilities/condition/common/LegendaryCondition.java
new file mode 100644
index 0000000000..1dc607643d
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/condition/common/LegendaryCondition.java
@@ -0,0 +1,46 @@
+package mage.abilities.condition.common;
+
+import mage.abilities.Ability;
+import mage.abilities.condition.Condition;
+import mage.constants.CardType;
+import mage.constants.SuperType;
+import mage.filter.FilterPermanent;
+import mage.filter.predicate.Predicates;
+import mage.filter.predicate.mageobject.CardTypePredicate;
+import mage.filter.predicate.mageobject.SupertypePredicate;
+import mage.game.Game;
+
+/**
+ * @author JRHerlehy
+ * Created on 4/7/18.
+ */
+public enum LegendaryCondition implements Condition {
+
+ instance;
+
+ private static final FilterPermanent filter = new FilterPermanent("legendary creature or planeswalker");
+
+ static {
+ filter.add(
+ Predicates.and(
+ new SupertypePredicate(SuperType.LEGENDARY),
+ Predicates.or(
+ new CardTypePredicate(CardType.CREATURE),
+ new CardTypePredicate(CardType.PLANESWALKER)
+ )
+ )
+ );
+ }
+
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ return game.getBattlefield().contains(filter, source.getControllerId(), 1, game);
+ }
+
+
+ @Override
+ public String toString() {
+ return super.toString();
+ }
+}
diff --git a/Mage/src/main/java/mage/abilities/condition/common/MainPhaseStackEmptyCondition.java b/Mage/src/main/java/mage/abilities/condition/common/MainPhaseStackEmptyCondition.java
new file mode 100644
index 0000000000..7f8922c7e3
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/condition/common/MainPhaseStackEmptyCondition.java
@@ -0,0 +1,56 @@
+/*
+ * 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.abilities.condition.common;
+
+import java.util.EnumSet;
+import java.util.Set;
+
+import mage.constants.TurnPhase;
+import mage.abilities.Ability;
+import mage.abilities.condition.Condition;
+import mage.game.Game;
+
+/**
+ * @author spjspj
+ */
+public enum MainPhaseStackEmptyCondition implements Condition {
+
+ instance;
+ private static final Set turnPhases = EnumSet.of(TurnPhase.PRECOMBAT_MAIN, TurnPhase.POSTCOMBAT_MAIN);
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ return game.getStack().isEmpty()
+ && turnPhases.contains(game.getTurn().getPhase().getType());
+ }
+
+ @Override
+ public String toString() {
+ return "during your main phase when the stack is empty";
+ }
+}
diff --git a/Mage/src/main/java/mage/abilities/condition/common/MyMainPhaseCondition.java b/Mage/src/main/java/mage/abilities/condition/common/MyMainPhaseCondition.java
index f09a6d7795..20e4ae7db8 100644
--- a/Mage/src/main/java/mage/abilities/condition/common/MyMainPhaseCondition.java
+++ b/Mage/src/main/java/mage/abilities/condition/common/MyMainPhaseCondition.java
@@ -28,7 +28,6 @@
package mage.abilities.condition.common;
import java.util.EnumSet;
-import java.util.HashSet;
import java.util.Set;
import mage.constants.TurnPhase;
diff --git a/Mage/src/main/java/mage/abilities/condition/common/SourceIsSpellCondition.java b/Mage/src/main/java/mage/abilities/condition/common/SourceIsSpellCondition.java
index 51a31399db..b3242cec95 100644
--- a/Mage/src/main/java/mage/abilities/condition/common/SourceIsSpellCondition.java
+++ b/Mage/src/main/java/mage/abilities/condition/common/SourceIsSpellCondition.java
@@ -30,7 +30,6 @@ package mage.abilities.condition.common;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.condition.Condition;
-import mage.constants.CardType;
import mage.game.Game;
/**
diff --git a/Mage/src/main/java/mage/abilities/condition/common/TargetHasSuperTypeCondition.java b/Mage/src/main/java/mage/abilities/condition/common/TargetHasSuperTypeCondition.java
new file mode 100644
index 0000000000..af12e5cf83
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/condition/common/TargetHasSuperTypeCondition.java
@@ -0,0 +1,36 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package mage.abilities.condition.common;
+
+import mage.MageObject;
+import mage.abilities.Ability;
+import mage.abilities.condition.Condition;
+import mage.constants.SuperType;
+import mage.game.Game;
+
+/**
+ *
+ * @author LevelX2
+ */
+public class TargetHasSuperTypeCondition implements Condition {
+
+ private final SuperType superType;
+
+ public TargetHasSuperTypeCondition(SuperType superType) {
+ this.superType = superType;
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ if (!source.getTargets().isEmpty()) {
+ MageObject mageObject = game.getObject(source.getFirstTarget());
+ if (mageObject != null) {
+ return mageObject.getSuperType().contains(superType);
+ }
+ }
+ return false;
+ }
+}
diff --git a/Mage/src/main/java/mage/abilities/costs/AlternativeCostSourceAbility.java b/Mage/src/main/java/mage/abilities/costs/AlternativeCostSourceAbility.java
index 81ccc47d8f..88e76bd140 100644
--- a/Mage/src/main/java/mage/abilities/costs/AlternativeCostSourceAbility.java
+++ b/Mage/src/main/java/mage/abilities/costs/AlternativeCostSourceAbility.java
@@ -121,7 +121,7 @@ public class AlternativeCostSourceAbility extends StaticAbility implements Alter
private AlternativeCost2 convertToAlternativeCost(Cost cost) {
//return cost != null ? new AlternativeCost2Impl(null, cost.getText(), cost) : null;
- return cost != null ? new AlternativeCost2Impl(null, "", cost) : null;
+ return cost != null ? new AlternativeCost2Impl(null, "", "", cost) : null;
}
@Override
@@ -228,7 +228,7 @@ public class AlternativeCostSourceAbility extends StaticAbility implements Alter
if (condition != null) {
sb.append(condition.toString());
if (alternateCosts.size() > 1) {
- sb.append(", rather than pay {source}'s mana cost, ");
+ sb.append(", rather than pay this spell's mana cost, ");
} else {
sb.append(", you may ");
}
@@ -254,7 +254,7 @@ public class AlternativeCostSourceAbility extends StaticAbility implements Alter
++numberCosts;
}
if (condition == null || alternateCosts.size() == 1) {
- sb.append(" rather than pay {source}'s mana cost");
+ sb.append(" rather than pay this spell's mana cost");
} else if (alternateCosts.isEmpty()) {
sb.append("cast {this} without paying its mana cost");
}
diff --git a/Mage/src/main/java/mage/abilities/costs/OptionalAdditionalCostImpl.java b/Mage/src/main/java/mage/abilities/costs/OptionalAdditionalCostImpl.java
index 6b7b7e320f..e64b8873e0 100644
--- a/Mage/src/main/java/mage/abilities/costs/OptionalAdditionalCostImpl.java
+++ b/Mage/src/main/java/mage/abilities/costs/OptionalAdditionalCostImpl.java
@@ -30,9 +30,8 @@ package mage.abilities.costs;
/**
*
* @author LevelX2
- * @param
*/
-public class OptionalAdditionalCostImpl extends CostsImpl implements OptionalAdditionalCost {
+public class OptionalAdditionalCostImpl extends CostsImpl implements OptionalAdditionalCost {
protected String name;
protected String reminderText;
diff --git a/Mage/src/main/java/mage/abilities/costs/common/DiscardXTargetCost.java b/Mage/src/main/java/mage/abilities/costs/common/DiscardXTargetCost.java
index e41df6c899..474b8bb1cc 100644
--- a/Mage/src/main/java/mage/abilities/costs/common/DiscardXTargetCost.java
+++ b/Mage/src/main/java/mage/abilities/costs/common/DiscardXTargetCost.java
@@ -49,7 +49,7 @@ public class DiscardXTargetCost extends VariableCostImpl {
public DiscardXTargetCost(FilterCard filter, boolean additionalCostText) {
super(filter.getMessage() + " to discard");
- this.text = (additionalCostText ? "As an additional cost to cast {source}, discard " : "Discard ") + xText + ' ' + filter.getMessage();
+ this.text = (additionalCostText ? "as an additional cost to cast this spell, discard " : "Discard ") + xText + ' ' + filter.getMessage();
this.filter = filter;
}
diff --git a/Mage/src/main/java/mage/abilities/costs/common/ExileTopCreatureCardOfGraveyardCost.java b/Mage/src/main/java/mage/abilities/costs/common/ExileTopCreatureCardOfGraveyardCost.java
index 2af8d31efc..7d2087ab50 100644
--- a/Mage/src/main/java/mage/abilities/costs/common/ExileTopCreatureCardOfGraveyardCost.java
+++ b/Mage/src/main/java/mage/abilities/costs/common/ExileTopCreatureCardOfGraveyardCost.java
@@ -10,7 +10,6 @@ import mage.abilities.Ability;
import mage.abilities.costs.Cost;
import mage.abilities.costs.CostImpl;
import mage.cards.Card;
-import mage.constants.CardType;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
diff --git a/Mage/src/main/java/mage/abilities/costs/common/ExileXFromYourGraveCost.java b/Mage/src/main/java/mage/abilities/costs/common/ExileXFromYourGraveCost.java
index 317b5e45ac..e6d107840a 100644
--- a/Mage/src/main/java/mage/abilities/costs/common/ExileXFromYourGraveCost.java
+++ b/Mage/src/main/java/mage/abilities/costs/common/ExileXFromYourGraveCost.java
@@ -50,7 +50,7 @@ public class ExileXFromYourGraveCost extends VariableCostImpl {
public ExileXFromYourGraveCost(FilterCard filter, boolean additionalCostText) {
super(filter.getMessage() + " to exile");
this.filter = filter;
- this.text = (additionalCostText ? "As an additional cost to cast {source}, exile " : "Exile ") + xText + ' ' + filter.getMessage();
+ this.text = (additionalCostText ? "as an additional cost to cast this spell, exile " : "Exile ") + xText + ' ' + filter.getMessage();
}
public ExileXFromYourGraveCost(final ExileXFromYourGraveCost cost) {
diff --git a/Mage/src/main/java/mage/abilities/costs/common/GainLifeOpponentCost.java b/Mage/src/main/java/mage/abilities/costs/common/GainLifeOpponentCost.java
index 7bc216aab5..2ff1e0a962 100644
--- a/Mage/src/main/java/mage/abilities/costs/common/GainLifeOpponentCost.java
+++ b/Mage/src/main/java/mage/abilities/costs/common/GainLifeOpponentCost.java
@@ -67,7 +67,7 @@ public class GainLifeOpponentCost extends CostImpl {
if (controller.chooseTarget(Outcome.Detriment, target, ability, game)) {
Player opponent = game.getPlayer(target.getFirstTarget());
if (opponent != null) {
- opponent.gainLife(amount, game);
+ opponent.gainLife(amount, game, sourceId);
paid = true;
}
diff --git a/Mage/src/main/java/mage/abilities/costs/common/GainLifePlayersCost.java b/Mage/src/main/java/mage/abilities/costs/common/GainLifePlayersCost.java
index d09e5d6057..5399765b0f 100644
--- a/Mage/src/main/java/mage/abilities/costs/common/GainLifePlayersCost.java
+++ b/Mage/src/main/java/mage/abilities/costs/common/GainLifePlayersCost.java
@@ -78,7 +78,7 @@ public class GainLifePlayersCost extends CostImpl {
if (!playerId.equals(controllerId)) {
Player player = game.getPlayer(playerId);
if (player != null) {
- player.gainLife(amount, game);
+ player.gainLife(amount, game, sourceId);
}
}
}
diff --git a/Mage/src/main/java/mage/abilities/costs/common/PayLifeCost.java b/Mage/src/main/java/mage/abilities/costs/common/PayLifeCost.java
index bdc1a6c45d..ff38779e73 100644
--- a/Mage/src/main/java/mage/abilities/costs/common/PayLifeCost.java
+++ b/Mage/src/main/java/mage/abilities/costs/common/PayLifeCost.java
@@ -63,7 +63,7 @@ public class PayLifeCost extends CostImpl {
@Override
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
//118.4. If a cost or effect allows a player to pay an amount of life greater than 0,
- //the player may do so only if his or her life total is greater than or equal to the
+ //the player may do so only if their life total is greater than or equal to the
//amount of the payment. If a player pays life, the payment is subtracted from his or
//her life total; in other words, the player loses that much life. (Players can always pay 0 life.)
int lifeToPayAmount = amount.calculate(game, ability, null);
diff --git a/Mage/src/main/java/mage/abilities/costs/common/PayLoyaltyCost.java b/Mage/src/main/java/mage/abilities/costs/common/PayLoyaltyCost.java
index 24a40a8f3b..20b7f4d212 100644
--- a/Mage/src/main/java/mage/abilities/costs/common/PayLoyaltyCost.java
+++ b/Mage/src/main/java/mage/abilities/costs/common/PayLoyaltyCost.java
@@ -47,7 +47,7 @@ public class PayLoyaltyCost extends CostImpl {
public PayLoyaltyCost(int amount) {
this.amount = amount;
this.text = Integer.toString(amount);
- if (amount >= 0) {
+ if (amount > 0) {
this.text = '+' + this.text;
}
}
diff --git a/Mage/src/main/java/mage/abilities/costs/common/PayVariableLifeCost.java b/Mage/src/main/java/mage/abilities/costs/common/PayVariableLifeCost.java
index 5577627230..f6a90a48d7 100644
--- a/Mage/src/main/java/mage/abilities/costs/common/PayVariableLifeCost.java
+++ b/Mage/src/main/java/mage/abilities/costs/common/PayVariableLifeCost.java
@@ -47,7 +47,7 @@ public class PayVariableLifeCost extends VariableCostImpl {
public PayVariableLifeCost(boolean additionalCostText) {
super("life to pay");
- this.text = new StringBuilder(additionalCostText ? "As an additional cost to cast {source}, pay ":"Pay ")
+ this.text = new StringBuilder(additionalCostText ? "as an additional cost to cast this spell, pay ":"Pay ")
.append(xText).append(' ').append("life").toString();
}
diff --git a/Mage/src/main/java/mage/abilities/costs/common/PutTopCardOfYourLibraryToGraveyardCost.java b/Mage/src/main/java/mage/abilities/costs/common/PutTopCardOfYourLibraryToGraveyardCost.java
index 6da0f046e9..61316d0d74 100644
--- a/Mage/src/main/java/mage/abilities/costs/common/PutTopCardOfYourLibraryToGraveyardCost.java
+++ b/Mage/src/main/java/mage/abilities/costs/common/PutTopCardOfYourLibraryToGraveyardCost.java
@@ -27,10 +27,13 @@
*/
package mage.abilities.costs.common;
+import java.util.LinkedHashSet;
+import java.util.Set;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.Cost;
import mage.abilities.costs.CostImpl;
+import mage.cards.Card;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
@@ -38,7 +41,8 @@ import mage.util.CardUtil;
public class PutTopCardOfYourLibraryToGraveyardCost extends CostImpl {
- int numberOfCards;
+ private final int numberOfCards;
+ private final Set cardsMovedToGraveyard = new LinkedHashSet<>();
public PutTopCardOfYourLibraryToGraveyardCost() {
this(1);
@@ -52,6 +56,7 @@ public class PutTopCardOfYourLibraryToGraveyardCost extends CostImpl {
public PutTopCardOfYourLibraryToGraveyardCost(PutTopCardOfYourLibraryToGraveyardCost cost) {
super(cost);
this.numberOfCards = cost.numberOfCards;
+ this.cardsMovedToGraveyard.addAll(cost.getCardsMovedToGraveyard());
}
@Override
@@ -59,6 +64,7 @@ public class PutTopCardOfYourLibraryToGraveyardCost extends CostImpl {
Player player = game.getPlayer(controllerId);
if (player != null && player.getLibrary().size() >= numberOfCards) {
paid = true;
+ this.cardsMovedToGraveyard.addAll(player.getLibrary().getTopCards(game, numberOfCards));
player.moveCards(player.getLibrary().getTopCards(game, numberOfCards), Zone.GRAVEYARD, ability, game);
}
return paid;
@@ -75,6 +81,10 @@ public class PutTopCardOfYourLibraryToGraveyardCost extends CostImpl {
return new PutTopCardOfYourLibraryToGraveyardCost(this);
}
+ public Set getCardsMovedToGraveyard() {
+ return cardsMovedToGraveyard;
+ }
+
private String setText() {
StringBuilder sb = new StringBuilder("Put the top ");
if (numberOfCards == 1) {
diff --git a/Mage/src/main/java/mage/abilities/costs/common/ReturnToHandChosenControlledPermanentCost.java b/Mage/src/main/java/mage/abilities/costs/common/ReturnToHandChosenControlledPermanentCost.java
index df84b8d1f4..fe8a1d269d 100644
--- a/Mage/src/main/java/mage/abilities/costs/common/ReturnToHandChosenControlledPermanentCost.java
+++ b/Mage/src/main/java/mage/abilities/costs/common/ReturnToHandChosenControlledPermanentCost.java
@@ -52,9 +52,14 @@ public class ReturnToHandChosenControlledPermanentCost extends CostImpl {
target.setNotTarget(true);
this.addTarget(target);
if (target.getMaxNumberOfTargets() > 1 && target.getMaxNumberOfTargets() == target.getNumberOfTargets()) {
- this.text = "return " + CardUtil.numberToText(target.getMaxNumberOfTargets()) + ' ' + target.getTargetName() + " you control to their owner's hand";
+ this.text = "return " + CardUtil.numberToText(target.getMaxNumberOfTargets()) + ' '
+ + target.getTargetName()
+ + (target.getTargetName().endsWith(" you control") ? "" : " you control")
+ + " to their owner's hand";
} else {
- this.text = "return " + target.getTargetName() + " you control to its owner's hand";
+ this.text = "return " + target.getTargetName()
+ + (target.getTargetName().endsWith(" you control") ? "" : " you control")
+ + " to its owner's hand";
}
}
diff --git a/Mage/src/main/java/mage/abilities/costs/common/SacrificeXTargetCost.java b/Mage/src/main/java/mage/abilities/costs/common/SacrificeXTargetCost.java
index e83014b796..1551b90823 100644
--- a/Mage/src/main/java/mage/abilities/costs/common/SacrificeXTargetCost.java
+++ b/Mage/src/main/java/mage/abilities/costs/common/SacrificeXTargetCost.java
@@ -48,7 +48,7 @@ public class SacrificeXTargetCost extends VariableCostImpl {
public SacrificeXTargetCost(FilterControlledPermanent filter, boolean additionalCostText) {
super(filter.getMessage() + " to sacrifice");
- this.text = (additionalCostText ? "As an additional cost to cast {source}, sacrifice " : "Sacrifice ") + xText + ' ' + filter.getMessage();
+ this.text = (additionalCostText ? "as an additional cost to cast this spell, sacrifice " : "Sacrifice ") + xText + ' ' + filter.getMessage();
this.filter = filter;
}
diff --git a/Mage/src/main/java/mage/abilities/costs/common/TapSourceCost.java b/Mage/src/main/java/mage/abilities/costs/common/TapSourceCost.java
index e53a75282b..d127b66491 100644
--- a/Mage/src/main/java/mage/abilities/costs/common/TapSourceCost.java
+++ b/Mage/src/main/java/mage/abilities/costs/common/TapSourceCost.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.costs.common;
import java.util.UUID;
@@ -63,8 +62,8 @@ public class TapSourceCost extends CostImpl {
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
Permanent permanent = game.getPermanent(sourceId);
if (permanent != null) {
- return !permanent.isTapped() &&
- (permanent.canTap() || game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_HASTE, controllerId, game));
+ return !permanent.isTapped()
+ && (permanent.canTap() || null != game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_HASTE, controllerId, game));
}
return false;
}
diff --git a/Mage/src/main/java/mage/abilities/costs/common/TapVariableTargetCost.java b/Mage/src/main/java/mage/abilities/costs/common/TapVariableTargetCost.java
index 5f2bc10650..bb4f0d5a9a 100644
--- a/Mage/src/main/java/mage/abilities/costs/common/TapVariableTargetCost.java
+++ b/Mage/src/main/java/mage/abilities/costs/common/TapVariableTargetCost.java
@@ -50,7 +50,7 @@ public class TapVariableTargetCost extends VariableCostImpl {
public TapVariableTargetCost(FilterControlledPermanent filter, boolean additionalCostText, String xText) {
super(xText, new StringBuilder(filter.getMessage()).append(" to tap").toString());
this.filter = filter;
- this.text = new StringBuilder(additionalCostText ? "As an additional cost to cast {source}, tap ":"Tap ")
+ this.text = new StringBuilder(additionalCostText ? "as an additional cost to cast this spell, tap ":"Tap ")
.append(this.xText).append(' ').append(filter.getMessage()).toString();
}
diff --git a/Mage/src/main/java/mage/abilities/costs/common/UntapSourceCost.java b/Mage/src/main/java/mage/abilities/costs/common/UntapSourceCost.java
index 9781fdece4..15af412080 100644
--- a/Mage/src/main/java/mage/abilities/costs/common/UntapSourceCost.java
+++ b/Mage/src/main/java/mage/abilities/costs/common/UntapSourceCost.java
@@ -62,7 +62,7 @@ public class UntapSourceCost extends CostImpl {
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
Permanent permanent = game.getPermanent(sourceId);
if (permanent != null) {
- return permanent.isTapped() && (permanent.canTap() || game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_HASTE, controllerId, game));
+ return permanent.isTapped() && (permanent.canTap() || null != game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_HASTE, controllerId, game));
}
return false;
}
diff --git a/Mage/src/main/java/mage/abilities/costs/mana/MonoHybridManaCost.java b/Mage/src/main/java/mage/abilities/costs/mana/MonoHybridManaCost.java
index 99432210b4..cb62642f08 100644
--- a/Mage/src/main/java/mage/abilities/costs/mana/MonoHybridManaCost.java
+++ b/Mage/src/main/java/mage/abilities/costs/mana/MonoHybridManaCost.java
@@ -122,6 +122,10 @@ public class MonoHybridManaCost extends ManaCostImpl {
return mana == coloredManaSymbol;
}
+ public ColoredManaSymbol getManaColor() {
+ return mana;
+ }
+
@Override
public List getManaOptions() {
List manaList = new ArrayList<>();
diff --git a/Mage/src/main/java/mage/abilities/decorator/ConditionalContinuousEffect.java b/Mage/src/main/java/mage/abilities/decorator/ConditionalContinuousEffect.java
index 5a22141369..1ce5392da3 100644
--- a/Mage/src/main/java/mage/abilities/decorator/ConditionalContinuousEffect.java
+++ b/Mage/src/main/java/mage/abilities/decorator/ConditionalContinuousEffect.java
@@ -104,6 +104,9 @@ public class ConditionalContinuousEffect extends ContinuousEffectImpl {
@Override
public boolean apply(Game game, Ability source) {
+ if (condition == null && baseCondition != null) {
+ condition = baseCondition;
+ }
boolean conditionState = condition.apply(game, source);
if (conditionState) {
effect.setTargetPointer(this.targetPointer);
diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/AdditiveDynamicValue.java b/Mage/src/main/java/mage/abilities/dynamicvalue/AdditiveDynamicValue.java
new file mode 100644
index 0000000000..bd488c7cf5
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/dynamicvalue/AdditiveDynamicValue.java
@@ -0,0 +1,48 @@
+package mage.abilities.dynamicvalue;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import mage.abilities.Ability;
+import mage.abilities.effects.Effect;
+import mage.game.Game;
+
+public class AdditiveDynamicValue implements DynamicValue {
+
+ private final List dynamicValues;
+
+ /**
+ * Creates a {@link DynamicValue} from that adds together multiple
+ * {@link DynamicValue}s.
+ *
+ * @param dynamicValues The dynamic values to add together.
+ */
+ public AdditiveDynamicValue(DynamicValue... dynamicValues) {
+ this.dynamicValues = Arrays.asList(dynamicValues);
+ }
+
+ /**
+ * Creates a {@link DynamicValue} from that adds together multiple
+ * {@link DynamicValue}s.
+ *
+ * @param dynamicValues The dynamic values to add together.
+ */
+ public AdditiveDynamicValue(List dynamicValues) {
+ this.dynamicValues = dynamicValues;
+ }
+
+ @Override
+ public int calculate(Game game, Ability sourceAbility, Effect effect) {
+ return dynamicValues.stream().mapToInt(d -> d.calculate(game, sourceAbility, effect)).sum();
+ }
+
+ @Override
+ public DynamicValue copy() {
+ return new AdditiveDynamicValue(this.dynamicValues);
+ }
+
+ @Override
+ public String getMessage() {
+ return this.dynamicValues.stream().map(DynamicValue::getMessage).collect(Collectors.joining(" "));
+ }
+}
diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/ParleyCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/ParleyCount.java
index 4a40e33d6c..5a0850e282 100644
--- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/ParleyCount.java
+++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/ParleyCount.java
@@ -36,7 +36,6 @@ import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
import mage.cards.Card;
import mage.cards.CardsImpl;
-import mage.constants.CardType;
import mage.game.Game;
import mage.players.Player;
@@ -59,11 +58,11 @@ public class ParleyCount implements DynamicValue, MageSingleton {
@Override
public int calculate(Game game, Ability sourceAbility, Effect effect) {
- // Each player reveals the top card of his or her library. For each nonland card revealed this way
+ // Each player reveals the top card of their library. For each nonland card revealed this way
int parleyValue = 0;
MageObject sourceObject = game.getObject(sourceAbility.getSourceId());
if (sourceObject != null) {
- for (UUID playerId : game.getState().getPlayerList(sourceAbility.getControllerId())) {
+ for (UUID playerId : game.getState().getPlayersInRange(sourceAbility.getControllerId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
Card card = player.getLibrary().getFromTop(game);
diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/SweepNumber.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/SweepNumber.java
index 815988f784..6aebb054ed 100644
--- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/SweepNumber.java
+++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/SweepNumber.java
@@ -30,7 +30,6 @@ package mage.abilities.dynamicvalue.common;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
-import mage.cards.Card;
import mage.game.Game;
/**
@@ -39,37 +38,21 @@ import mage.game.Game;
*/
public class SweepNumber implements DynamicValue {
- private int zoneChangeCounter = 0;
private final String sweepSubtype;
- private final boolean previousZone;
- public SweepNumber(String sweepSubtype, boolean previousZone) {
+ public SweepNumber(String sweepSubtype) {
this.sweepSubtype = sweepSubtype;
- this.previousZone = previousZone;
}
@Override
public int calculate(Game game, Ability source, Effect effect) {
- if (zoneChangeCounter == 0) {
- Card card = game.getCard(source.getSourceId());
- if (card != null) {
- zoneChangeCounter = card.getZoneChangeCounter(game);
- if (previousZone) {
- zoneChangeCounter--;
- }
- }
- }
- int number = 0;
- Integer sweepNumber = (Integer) game.getState().getValue(new StringBuilder("sweep").append(source.getSourceId()).append(zoneChangeCounter).toString());
- if (sweepNumber != null) {
- number = sweepNumber;
- }
- return number;
+ Integer sweepNumber = (Integer) game.getState().getValue("sweep" + source.getSourceId() + game.getState().getZoneChangeCounter(source.getSourceId()));
+ return sweepNumber != null ? sweepNumber : 0;
}
@Override
public SweepNumber copy() {
- return new SweepNumber(sweepSubtype, previousZone);
+ return new SweepNumber(sweepSubtype);
}
@Override
@@ -79,6 +62,6 @@ public class SweepNumber implements DynamicValue {
@Override
public String getMessage() {
- return new StringBuilder("the number of ").append(sweepSubtype).append(sweepSubtype.endsWith("s") ? "":"s").append(" returned this way").toString();
+ return "the number of " + sweepSubtype + (sweepSubtype.endsWith("s") ? "" : "s") + " returned this way";
}
}
diff --git a/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java b/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java
index 6070e4693d..db908e4a28 100644
--- a/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java
+++ b/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java
@@ -79,7 +79,7 @@ public class ContinuousEffects implements Serializable {
private final Map> asThoughEffectsMap = new EnumMap<>(AsThoughEffectType.class);
public final List> allEffectsLists = new ArrayList<>();
private final ApplyCountersEffect applyCounters;
- private final PlaneswalkerRedirectionEffect planeswalkerRedirectionEffect;
+// private final PlaneswalkerRedirectionEffect planeswalkerRedirectionEffect;
private final AuraReplacementEffect auraReplacementEffect;
private final List previous = new ArrayList<>();
@@ -89,14 +89,14 @@ public class ContinuousEffects implements Serializable {
public ContinuousEffects() {
applyCounters = new ApplyCountersEffect();
- planeswalkerRedirectionEffect = new PlaneswalkerRedirectionEffect();
+// planeswalkerRedirectionEffect = new PlaneswalkerRedirectionEffect();
auraReplacementEffect = new AuraReplacementEffect();
collectAllEffects();
}
public ContinuousEffects(final ContinuousEffects effect) {
this.applyCounters = effect.applyCounters.copy();
- this.planeswalkerRedirectionEffect = effect.planeswalkerRedirectionEffect.copy();
+// this.planeswalkerRedirectionEffect = effect.planeswalkerRedirectionEffect.copy();
this.auraReplacementEffect = effect.auraReplacementEffect.copy();
layeredEffects = effect.layeredEffects.copy();
continuousRuleModifyingEffects = effect.continuousRuleModifyingEffects.copy();
@@ -339,9 +339,9 @@ public class ContinuousEffects implements Serializable {
*/
private Map> getApplicableReplacementEffects(GameEvent event, Game game) {
Map> replaceEffects = new HashMap<>();
- if (planeswalkerRedirectionEffect.checksEventType(event, game) && planeswalkerRedirectionEffect.applies(event, null, game)) {
- replaceEffects.put(planeswalkerRedirectionEffect, null);
- }
+// if (planeswalkerRedirectionEffect.checksEventType(event, game) && planeswalkerRedirectionEffect.applies(event, null, game)) {
+// replaceEffects.put(planeswalkerRedirectionEffect, null);
+// }
if (auraReplacementEffect.checksEventType(event, game) && auraReplacementEffect.applies(event, null, game)) {
replaceEffects.put(auraReplacementEffect, null);
}
@@ -500,25 +500,44 @@ public class ContinuousEffects implements Serializable {
return spliceEffects;
}
- public boolean asThough(UUID objectId, AsThoughEffectType type, UUID controllerId, Game game) {
+ /**
+ *
+ * @param objectId
+ * @param type
+ * @param controllerId
+ * @param game
+ * @return sourceId of the permitting effect if any exists otherwise returns
+ * null
+ */
+ public UUID asThough(UUID objectId, AsThoughEffectType type, UUID controllerId, Game game) {
return asThough(objectId, type, null, controllerId, game);
}
- public boolean asThough(UUID objectId, AsThoughEffectType type, Ability affectedAbility, UUID controllerId, Game game) {
+ /**
+ *
+ * @param objectId
+ * @param type
+ * @param affectedAbility
+ * @param controllerId
+ * @param game
+ * @return sourceId of the permitting effect if any exists otherwise returns
+ * null
+ */
+ public UUID asThough(UUID objectId, AsThoughEffectType type, Ability affectedAbility, UUID controllerId, Game game) {
List asThoughEffectsList = getApplicableAsThoughEffects(type, game);
for (AsThoughEffect effect : asThoughEffectsList) {
Set abilities = asThoughEffectsMap.get(type).getAbility(effect.getId());
for (Ability ability : abilities) {
if (affectedAbility == null) {
if (effect.applies(objectId, ability, controllerId, game)) {
- return true;
+ return ability.getSourceId();
}
} else if (effect.applies(objectId, affectedAbility, ability, game)) {
- return true;
+ return ability.getSourceId();
}
}
}
- return false;
+ return null;
}
@@ -754,7 +773,7 @@ public class ContinuousEffects implements Serializable {
// Remove all consumed effects (ability dependant)
for (Iterator it1 = rEffects.keySet().iterator(); it1.hasNext();) {
ReplacementEffect entry = it1.next();
- if (consumed.containsKey(entry.getId()) /*&& !(entry instanceof CommanderReplacementEffect) */) { // 903.9.
+ if (consumed.containsKey(entry.getId()) /*&& !(entry instanceof CommanderReplacementEffect) */) { // 903.9.
Set consumedAbilitiesIds = consumed.get(entry.getId());
if (rEffects.get(entry) == null || consumedAbilitiesIds.size() == rEffects.get(entry).size()) {
it1.remove();
@@ -1235,8 +1254,8 @@ public class ContinuousEffects implements Serializable {
}
}
} else {
- if (!(entry.getKey() instanceof AuraReplacementEffect)
- && !(entry.getKey() instanceof PlaneswalkerRedirectionEffect)) {
+ if (!(entry.getKey() instanceof AuraReplacementEffect)) {
+// && !(entry.getKey() instanceof PlaneswalkerRedirectionEffect)) {
logger.error("Replacement effect without ability: " + entry.getKey().toString());
}
}
diff --git a/Mage/src/main/java/mage/abilities/effects/Effect.java b/Mage/src/main/java/mage/abilities/effects/Effect.java
index cc7d51c7b3..2042446cf3 100644
--- a/Mage/src/main/java/mage/abilities/effects/Effect.java
+++ b/Mage/src/main/java/mage/abilities/effects/Effect.java
@@ -88,10 +88,6 @@ public interface Effect extends Serializable {
Object getValue(String key);
- void setApplyEffectsAfter();
-
- boolean applyEffectsAfter();
-
Effect copy();
}
diff --git a/Mage/src/main/java/mage/abilities/effects/EffectImpl.java b/Mage/src/main/java/mage/abilities/effects/EffectImpl.java
index ccc7f08f3d..873111014e 100644
--- a/Mage/src/main/java/mage/abilities/effects/EffectImpl.java
+++ b/Mage/src/main/java/mage/abilities/effects/EffectImpl.java
@@ -138,18 +138,4 @@ public abstract class EffectImpl implements Effect {
}
return values.get(key);
}
-
- /**
- * If set, the game.applyEffects() method will be called to apply the
- * effects before the next effect (of the same ability) will resolve.
- */
- @Override
- public void setApplyEffectsAfter() {
- applyEffectsAfter = true;
- }
-
- @Override
- public boolean applyEffectsAfter() {
- return applyEffectsAfter;
- }
}
diff --git a/Mage/src/main/java/mage/abilities/effects/GainAbilitySpellsEffect.java b/Mage/src/main/java/mage/abilities/effects/GainAbilitySpellsEffect.java
new file mode 100644
index 0000000000..6804ff9b86
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/effects/GainAbilitySpellsEffect.java
@@ -0,0 +1,77 @@
+package mage.abilities.effects;
+
+import mage.abilities.Ability;
+import mage.cards.Card;
+import mage.constants.Duration;
+import mage.constants.Layer;
+import mage.constants.Outcome;
+import mage.constants.SubLayer;
+import mage.filter.FilterObject;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.game.stack.StackObject;
+import mage.players.Player;
+
+public class GainAbilitySpellsEffect extends ContinuousEffectImpl {
+
+ private final Ability ability;
+ private final FilterObject filter;
+
+ public GainAbilitySpellsEffect(Ability ability, FilterObject filter) {
+ super(Duration.Custom, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
+ this.ability = ability;
+ this.filter = filter;
+ staticText = filter.getMessage() + " have " + ability.getRule();
+ }
+
+ public GainAbilitySpellsEffect(final GainAbilitySpellsEffect effect) {
+ super(effect);
+ this.ability = effect.ability;
+ this.filter = effect.filter;
+ }
+
+ @Override
+ public GainAbilitySpellsEffect copy() {
+ return new GainAbilitySpellsEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player player = game.getPlayer(source.getControllerId());
+ Permanent permanent = game.getPermanent(source.getSourceId());
+ if (player != null && permanent != null) {
+ for (Card card : game.getExile().getAllCards(game)) {
+ if (card.getOwnerId().equals(source.getControllerId()) && filter.match(card, game)) {
+ game.getState().addOtherAbility(card, ability);
+ }
+ }
+ for (Card card : player.getLibrary().getCards(game)) {
+ if (filter.match(card, game)) {
+ game.getState().addOtherAbility(card, ability);
+ }
+ }
+ for (Card card : player.getHand().getCards(game)) {
+ if (filter.match(card, game)) {
+ game.getState().addOtherAbility(card, ability);
+ }
+ }
+ for (Card card : player.getGraveyard().getCards(game)) {
+ if (filter.match(card, game)) {
+ game.getState().addOtherAbility(card, ability);
+ }
+ }
+ for (StackObject stackObject : game.getStack()) {
+ if (stackObject.getControllerId().equals(source.getControllerId())) {
+ Card card = game.getCard(stackObject.getSourceId());
+ if (card != null && filter.match(card, game)) {
+ if (!card.getAbilities().contains(ability)) {
+ game.getState().addOtherAbility(card, ability);
+ }
+ }
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/Mage/src/main/java/mage/abilities/effects/PlaneswalkerRedirectionEffect.java b/Mage/src/main/java/mage/abilities/effects/PlaneswalkerRedirectionEffect.java
index 0085719467..c4c8345042 100644
--- a/Mage/src/main/java/mage/abilities/effects/PlaneswalkerRedirectionEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/PlaneswalkerRedirectionEffect.java
@@ -43,9 +43,12 @@ import mage.players.Player;
import mage.target.TargetPermanent;
/**
+ * NOTE: This is no longer used, but I'm leaving it in because why not
+ * -TheElk801
*
* @author BetaSteward_at_googlemail.com
*/
+@Deprecated
public class PlaneswalkerRedirectionEffect extends RedirectionEffect {
public PlaneswalkerRedirectionEffect() {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/AddConditionalColorlessManaEffect.java b/Mage/src/main/java/mage/abilities/effects/common/AddConditionalColorlessManaEffect.java
index 26aa0228f3..596b447002 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/AddConditionalColorlessManaEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/AddConditionalColorlessManaEffect.java
@@ -26,7 +26,7 @@ public class AddConditionalColorlessManaEffect extends ManaEffect {
this.manaBuilder = manaBuilder;
staticText = "Add " + String.format(String.format("%%%ds", amount), " ").replace(" ", "{C}")
- + " to your mana pool. " + manaBuilder.getRule();
+ + ". " + manaBuilder.getRule();
}
public AddConditionalColorlessManaEffect(final AddConditionalColorlessManaEffect effect) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/AddConditionalManaEffect.java b/Mage/src/main/java/mage/abilities/effects/common/AddConditionalManaEffect.java
index 2e06e8f1bb..b3dedd8d6c 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/AddConditionalManaEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/AddConditionalManaEffect.java
@@ -24,7 +24,7 @@ public class AddConditionalManaEffect extends ManaEffect {
super();
this.mana = mana;
this.manaBuilder = manaBuilder;
- staticText = "Add " + this.mana.toString() + " to your mana pool. " + manaBuilder.getRule();
+ staticText = "Add " + this.mana.toString() + ". " + manaBuilder.getRule();
}
public AddConditionalManaEffect(final AddConditionalManaEffect effect) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/AddConditionalManaOfAnyColorEffect.java b/Mage/src/main/java/mage/abilities/effects/common/AddConditionalManaOfAnyColorEffect.java
index 2bf737ab41..3f683a25de 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/AddConditionalManaOfAnyColorEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/AddConditionalManaOfAnyColorEffect.java
@@ -66,7 +66,7 @@ public class AddConditionalManaOfAnyColorEffect extends ManaEffect {
+ (oneChoice ? "of any"
+ (amount instanceof StaticValue && (((StaticValue) amount).toString()).equals("1") ? "" : " one")
+ " color" : "in any combination of colors")
- + " to your mana pool. " + manaBuilder.getRule();
+ + ". " + manaBuilder.getRule();
}
public AddConditionalManaOfAnyColorEffect(final AddConditionalManaOfAnyColorEffect effect) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/AddManaAnyColorAttachedControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/AddManaAnyColorAttachedControllerEffect.java
index aac3866254..0e3e6d05d6 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/AddManaAnyColorAttachedControllerEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/AddManaAnyColorAttachedControllerEffect.java
@@ -42,7 +42,7 @@ public class AddManaAnyColorAttachedControllerEffect extends ManaEffect {
public AddManaAnyColorAttachedControllerEffect() {
super();
- staticText = "its controller adds one mana of any color to his or her mana pool";
+ staticText = "its controller adds one mana of any color to their mana pool";
}
public AddManaAnyColorAttachedControllerEffect(final AddManaAnyColorAttachedControllerEffect effect) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/AddManaInAnyCombinationEffect.java b/Mage/src/main/java/mage/abilities/effects/common/AddManaInAnyCombinationEffect.java
index 72fae649de..0bb378b1ed 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/AddManaInAnyCombinationEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/AddManaInAnyCombinationEffect.java
@@ -94,10 +94,12 @@ public class AddManaInAnyCombinationEffect extends ManaEffect {
if (player != null) {
Mana mana = new Mana();
int amountOfManaLeft = amount.calculate(game, source, this);
+ int maxAmount = amountOfManaLeft;
while (amountOfManaLeft > 0 && player.canRespond()) {
for (ColoredManaSymbol coloredManaSymbol : manaSymbols) {
- int number = player.getAmount(0, amountOfManaLeft, "How many " + coloredManaSymbol.getColorName() + " mana?", game);
+ int number = player.getAmount(0, amountOfManaLeft, "Distribute mana by color (done " + mana.count()
+ + " of " + maxAmount + "). How many mana add to " + coloredManaSymbol.getColorHtmlName() + " (enter 0 for pass to next color)?", game);
if (number > 0) {
for (int i = 0; i < number; i++) {
mana.add(new Mana(coloredManaSymbol));
@@ -137,7 +139,7 @@ public class AddManaInAnyCombinationEffect extends ManaEffect {
sb.append('{').append(coloredManaSymbol.toString()).append('}');
}
}
- sb.append(" to your mana pool");
+ sb.append("");
return sb.toString();
}
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/AddManaOfAnyColorEffect.java b/Mage/src/main/java/mage/abilities/effects/common/AddManaOfAnyColorEffect.java
index 84551cb93c..bf66ff3607 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/AddManaOfAnyColorEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/AddManaOfAnyColorEffect.java
@@ -52,7 +52,7 @@ public class AddManaOfAnyColorEffect extends BasicManaEffect {
.append(CardUtil.numberToText(amount))
.append(" mana of any ")
.append(amount > 1 ? "one " : "")
- .append("color to your mana pool").toString();
+ .append("color").toString();
}
public AddManaOfAnyColorEffect(final AddManaOfAnyColorEffect effect) {
@@ -69,7 +69,7 @@ public class AddManaOfAnyColorEffect extends BasicManaEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
- String mes = String.format("Select color of %d mana to add it to your mana pool", this.amount);
+ String mes = String.format("Select color of %d mana to add it", this.amount);
ChoiceColor choice = new ChoiceColor(true, mes, game.getObject(source.getSourceId()));
if (controller.choose(outcome, choice, game)) {
if (choice.getColor() == null) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/AddManaOfAnyColorToManaPoolTargetPlayerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/AddManaOfAnyColorToManaPoolTargetPlayerEffect.java
index b087354cfb..1f8c6c229b 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/AddManaOfAnyColorToManaPoolTargetPlayerEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/AddManaOfAnyColorToManaPoolTargetPlayerEffect.java
@@ -15,7 +15,7 @@ public class AddManaOfAnyColorToManaPoolTargetPlayerEffect extends ManaEffect {
public AddManaOfAnyColorToManaPoolTargetPlayerEffect(String textManaPoolOwner) {
super();
- this.staticText = (textManaPoolOwner.equals("his or her") ? "that player adds " : "add ") + "one mana of any color" + " to " + textManaPoolOwner + " mana pool";
+ this.staticText = (textManaPoolOwner.equals("their") ? "that player adds " : "add ") + "one mana of any color" + " to " + textManaPoolOwner + " mana pool";
}
public AddManaOfAnyColorToManaPoolTargetPlayerEffect(final AddManaOfAnyColorToManaPoolTargetPlayerEffect effect) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/AddManaOfAnyTypeProducedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/AddManaOfAnyTypeProducedEffect.java
index 28617232df..2d84bfff04 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/AddManaOfAnyTypeProducedEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/AddManaOfAnyTypeProducedEffect.java
@@ -43,7 +43,7 @@ public class AddManaOfAnyTypeProducedEffect extends ManaEffect {
public AddManaOfAnyTypeProducedEffect() {
super();
- staticText = "that player adds one mana to his or her mana pool of any type that land produced";
+ staticText = "that player adds one mana to their mana pool of any type that land produced";
}
public AddManaOfAnyTypeProducedEffect(final AddManaOfAnyTypeProducedEffect effect) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/AddManaToManaPoolSourceControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/AddManaToManaPoolSourceControllerEffect.java
index b8000cd423..fe3e3195f6 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/AddManaToManaPoolSourceControllerEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/AddManaToManaPoolSourceControllerEffect.java
@@ -24,7 +24,7 @@ public class AddManaToManaPoolSourceControllerEffect extends OneShotEffect {
public AddManaToManaPoolSourceControllerEffect(Mana mana) {
super(Outcome.PutManaInPool);
this.mana = mana;
- this.staticText = "Add " + mana.toString() + " to your mana pool";
+ this.staticText = "Add " + mana.toString() + "";
}
public AddManaToManaPoolSourceControllerEffect(final AddManaToManaPoolSourceControllerEffect effect) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/AddManaToManaPoolTargetControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/AddManaToManaPoolTargetControllerEffect.java
index 53cdaa155b..e7943c88b1 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/AddManaToManaPoolTargetControllerEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/AddManaToManaPoolTargetControllerEffect.java
@@ -36,7 +36,7 @@ public class AddManaToManaPoolTargetControllerEffect extends ManaEffect {
super();
this.mana = mana;
this.emptyOnlyOnTurnsEnd = emptyOnTurnsEnd;
- this.staticText = (textManaPoolOwner.equals("his or her")?"that player adds ":"add ") + mana.toString() + " to " + textManaPoolOwner + " mana pool";
+ this.staticText = (textManaPoolOwner.equals("their")?"that player adds ":"add ") + mana.toString() + " to " + textManaPoolOwner + " mana pool";
}
public AddManaToManaPoolTargetControllerEffect(final AddManaToManaPoolTargetControllerEffect effect) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/BasicManaEffect.java b/Mage/src/main/java/mage/abilities/effects/common/BasicManaEffect.java
index 95e7faa8ea..5bcd549778 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/BasicManaEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/BasicManaEffect.java
@@ -12,13 +12,13 @@ public class BasicManaEffect extends ManaEffect {
public BasicManaEffect(Mana mana) {
super();
this.mana = mana;
- staticText = "add " + mana.toString() + " to your mana pool";
+ staticText = "add " + mana.toString();
}
public BasicManaEffect(ConditionalMana conditionalMana) {
super();
this.mana = conditionalMana;
- staticText = "add " + mana.toString() + " to your mana pool. " + conditionalMana.getDescription();
+ staticText = "add " + mana.toString() + " " + conditionalMana.getDescription();
}
public BasicManaEffect(final BasicManaEffect effect) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/ChooseBasicLandTypeEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ChooseBasicLandTypeEffect.java
index b26560d8f2..ee84454831 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/ChooseBasicLandTypeEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/ChooseBasicLandTypeEffect.java
@@ -26,7 +26,7 @@ public class ChooseBasicLandTypeEffect extends OneShotEffect {
public ChooseBasicLandTypeEffect(Outcome outcome) {
super(outcome);
- this.staticText = "Choose a basic land type";
+ this.staticText = "choose a basic land type";
}
public ChooseBasicLandTypeEffect(final ChooseBasicLandTypeEffect effect) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/ChooseCreatureTypeEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ChooseCreatureTypeEffect.java
index a14e1fd635..58569eba48 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/ChooseCreatureTypeEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/ChooseCreatureTypeEffect.java
@@ -67,7 +67,7 @@ public class ChooseCreatureTypeEffect extends OneShotEffect {
if (!game.isSimulation()) {
game.informPlayers(mageObject.getName() + ": " + controller.getLogName() + " has chosen " + typeChoice.getChoice());
}
- game.getState().setValue(mageObject.getId() + "_type", SubType.byDescription(typeChoice.getChoice()));
+ game.getState().setValue(source.getSourceId() + "_type", SubType.byDescription(typeChoice.getChoice()));
if (mageObject instanceof Permanent) {
((Permanent) mageObject).addInfo("chosen type", CardUtil.addToolTipMarkTags("Chosen type: " + typeChoice.getChoice()), game);
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/ClashEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ClashEffect.java
index 2eb12ec5e1..f7239aa105 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/ClashEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/ClashEffect.java
@@ -49,9 +49,9 @@ import mage.target.common.TargetOpponent;
/**
* 1. The controller of the spell or ability chooses an opponent. (This doesn't
* target the opponent.) 2. Each player involved in the clash reveals the top
- * card of his or her library. 3. The converted mana costs of the revealed cards
+ * card of their library. 3. The converted mana costs of the revealed cards
* are noted. 4. In turn order, each player involved in the clash chooses to put
- * his or her revealed card on either the top or bottom of his or her library.
+ * their revealed card on either the top or bottom of their library.
* (Note that the player whose turn it is does this first, not necessarily the
* controller of the clash spell or ability.) When the second player makes this
* decision, he or she will know what the first player chose. Then all cards are
diff --git a/Mage/src/main/java/mage/abilities/effects/common/CopyTokenEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CopyTokenEffect.java
index 3207be060e..56463f3927 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/CopyTokenEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/CopyTokenEffect.java
@@ -5,6 +5,7 @@ import mage.abilities.effects.ContinuousEffectImpl;
import mage.constants.*;
import mage.game.Game;
import mage.game.permanent.Permanent;
+import mage.game.permanent.token.TokenImpl;
import mage.game.permanent.token.Token;
public class CopyTokenEffect extends ContinuousEffectImpl {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenEffect.java
index 05712cd92e..46b82048c0 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenEffect.java
@@ -37,6 +37,7 @@ import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
+import mage.game.permanent.token.TokenImpl;
import mage.game.permanent.token.Token;
import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
diff --git a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenTargetEffect.java
index 418b9e7593..2d37250007 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenTargetEffect.java
@@ -7,6 +7,7 @@ import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.game.Game;
+import mage.game.permanent.token.TokenImpl;
import mage.game.permanent.token.Token;
import mage.util.CardUtil;
diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageAllControlledTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageAllControlledTargetEffect.java
index 5a4622b6e2..25d81ab79d 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/DamageAllControlledTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/DamageAllControlledTargetEffect.java
@@ -25,15 +25,15 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
-
package mage.abilities.effects.common;
import mage.constants.Outcome;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
-import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.FilterPermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
+import mage.players.Player;
/**
*
@@ -41,10 +41,10 @@ import mage.game.permanent.Permanent;
*/
public class DamageAllControlledTargetEffect extends OneShotEffect {
- private FilterCreaturePermanent filter;
+ private FilterPermanent filter;
private int amount;
- public DamageAllControlledTargetEffect(int amount, FilterCreaturePermanent filter) {
+ public DamageAllControlledTargetEffect(int amount, FilterPermanent filter) {
super(Outcome.Damage);
this.amount = amount;
this.filter = filter;
@@ -64,7 +64,11 @@ public class DamageAllControlledTargetEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- for (Permanent permanent: game.getBattlefield().getAllActivePermanents(filter, source.getFirstTarget(), game)) {
+ Player player = game.getPlayerOrPlaneswalkerController(source.getFirstTarget());
+ if (player == null) {
+ return false;
+ }
+ for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, player.getId(), game)) {
permanent.damage(amount, source.getSourceId(), game, false, true);
}
return true;
diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageAttachedEffect.java
index 2cc1200ee2..064513a346 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/DamageAttachedEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/DamageAttachedEffect.java
@@ -36,7 +36,6 @@ import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.permanent.Permanent;
-import mage.players.Player;
/**
*
diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageEachOtherEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageEachOtherEffect.java
index da8a815b3a..505022199f 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/DamageEachOtherEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/DamageEachOtherEffect.java
@@ -30,7 +30,6 @@ package mage.abilities.effects.common;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.OneShotEffect;
-import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetEffect.java
index 2ba553547d..335fdc169f 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetEffect.java
@@ -187,7 +187,12 @@ public class DamageTargetEffect extends OneShotEffect {
if (!targetDescription.isEmpty()) {
sb.append(targetDescription);
} else {
- sb.append("target ").append(mode.getTargets().get(0).getTargetName());
+ String targetName = mode.getTargets().get(0).getTargetName();
+ if (targetName.contains("any")) {
+ sb.append(targetName);
+ } else {
+ sb.append("target ").append(targetName);
+ }
}
if (!message.isEmpty()) {
if (message.equals("1")) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/DestroyAllAttachedEquipmentEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DestroyAllAttachedEquipmentEffect.java
new file mode 100644
index 0000000000..bd3d34e65b
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/effects/common/DestroyAllAttachedEquipmentEffect.java
@@ -0,0 +1,55 @@
+package mage.abilities.effects.common;
+
+import mage.abilities.Ability;
+import mage.abilities.effects.OneShotEffect;
+import mage.constants.Outcome;
+import mage.constants.SubType;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ *
+ * @author Quercitron
+ */
+
+public class DestroyAllAttachedEquipmentEffect extends OneShotEffect {
+
+ public DestroyAllAttachedEquipmentEffect() {
+ super(Outcome.Benefit);
+ this.staticText = "Destroy all Equipment attached to that creature";
+ }
+
+ public DestroyAllAttachedEquipmentEffect(final DestroyAllAttachedEquipmentEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public DestroyAllAttachedEquipmentEffect copy() {
+ return new DestroyAllAttachedEquipmentEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player controller = game.getPlayer(source.getControllerId());
+ if (controller != null) {
+ Permanent target = game.getPermanent(source.getFirstTarget());
+ if (target != null) {
+ List attachments = new ArrayList<>(target.getAttachments());
+ for (UUID attachmentId : attachments) {
+ Permanent attachment = game.getPermanent(attachmentId);
+ if (attachment != null && attachment.hasSubtype(SubType.EQUIPMENT, game)) {
+ attachment.destroy(source.getSourceId(), game, false);
+ }
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/DoIfCostPaid.java b/Mage/src/main/java/mage/abilities/effects/common/DoIfCostPaid.java
index bba8baab7f..bb3c849662 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/DoIfCostPaid.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/DoIfCostPaid.java
@@ -1,5 +1,6 @@
package mage.abilities.effects.common;
+import java.util.Locale;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.Mode;
@@ -88,8 +89,7 @@ public class DoIfCostPaid extends OneShotEffect {
}
}
player.resetStoredBookmark(game); // otherwise you can e.g. undo card drawn with Mentor of the Meek
- }
- else if (!otherwiseEffects.isEmpty()) {
+ } else if (!otherwiseEffects.isEmpty()) {
for (Effect effect : otherwiseEffects) {
effect.setTargetPointer(this.targetPointer);
if (effect instanceof OneShotEffect) {
@@ -99,8 +99,7 @@ public class DoIfCostPaid extends OneShotEffect {
}
}
}
- }
- else if (!otherwiseEffects.isEmpty()) {
+ } else if (!otherwiseEffects.isEmpty()) {
for (Effect effect : otherwiseEffects) {
effect.setTargetPointer(this.targetPointer);
if (effect instanceof OneShotEffect) {
@@ -135,12 +134,12 @@ public class DoIfCostPaid extends OneShotEffect {
StringBuilder sb = new StringBuilder();
String costText = cost.getText();
if (costText != null
- && !costText.toLowerCase().startsWith("put")
- && !costText.toLowerCase().startsWith("exile")
- && !costText.toLowerCase().startsWith("discard")
- && !costText.toLowerCase().startsWith("sacrifice")
- && !costText.toLowerCase().startsWith("remove")
- && !costText.toLowerCase().startsWith("pay")) {
+ && !costText.toLowerCase(Locale.ENGLISH).startsWith("put")
+ && !costText.toLowerCase(Locale.ENGLISH).startsWith("exile")
+ && !costText.toLowerCase(Locale.ENGLISH).startsWith("discard")
+ && !costText.toLowerCase(Locale.ENGLISH).startsWith("sacrifice")
+ && !costText.toLowerCase(Locale.ENGLISH).startsWith("remove")
+ && !costText.toLowerCase(Locale.ENGLISH).startsWith("pay")) {
sb.append("pay ");
}
return sb.append(costText).toString();
diff --git a/Mage/src/main/java/mage/abilities/effects/common/DontUntapInPlayersNextUntapStepAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DontUntapInPlayersNextUntapStepAllEffect.java
index 37f3e8119c..37586a0c52 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/DontUntapInPlayersNextUntapStepAllEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/DontUntapInPlayersNextUntapStepAllEffect.java
@@ -141,6 +141,6 @@ public class DontUntapInPlayersNextUntapStepAllEffect extends ContinuousRuleModi
if (!staticText.isEmpty()) {
return staticText;
}
- return filter.getMessage() + " target opponent controls don't untap during his or her next untap step.";
+ return filter.getMessage() + " target opponent controls don't untap during their next untap step.";
}
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/EnterBattlefieldPayCostOrPutGraveyardEffect.java b/Mage/src/main/java/mage/abilities/effects/common/EnterBattlefieldPayCostOrPutGraveyardEffect.java
index 838f4a18fa..5ca029d50e 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/EnterBattlefieldPayCostOrPutGraveyardEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/EnterBattlefieldPayCostOrPutGraveyardEffect.java
@@ -27,6 +27,7 @@
*/
package mage.abilities.effects.common;
+import java.util.Locale;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.costs.Cost;
@@ -77,7 +78,7 @@ public class EnterBattlefieldPayCostOrPutGraveyardEffect extends ReplacementEffe
boolean replace = true;
if (cost.canPay(source, source.getSourceId(), player.getId(), game)) {
if (player.chooseUse(outcome,
- cost.getText().substring(0, 1).toUpperCase() + cost.getText().substring(1)
+ cost.getText().substring(0, 1).toUpperCase(Locale.ENGLISH) + cost.getText().substring(1)
+ "? (otherwise " + sourceObject.getLogName() + " is put into graveyard)", source, game)) {
cost.clearPaid();
replace = !cost.pay(source, game, source.getSourceId(), source.getControllerId(), false, null);
diff --git a/Mage/src/main/java/mage/abilities/effects/common/ExchangeLifeTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ExchangeLifeTargetEffect.java
index 5342c01cc5..a9a8d15105 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/ExchangeLifeTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/ExchangeLifeTargetEffect.java
@@ -77,8 +77,8 @@ public class ExchangeLifeTargetEffect extends OneShotEffect {
return false;
}
- controller.setLife(lifePlayer, game);
- player.setLife(lifeController, game);
+ controller.setLife(lifePlayer, game, source);
+ player.setLife(lifeController, game, source);
return true;
}
return false;
diff --git a/Mage/src/main/java/mage/abilities/effects/common/ExileAndGainLifeEqualPowerTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ExileAndGainLifeEqualPowerTargetEffect.java
index 4194b261cf..ab2ff09733 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/ExileAndGainLifeEqualPowerTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/ExileAndGainLifeEqualPowerTargetEffect.java
@@ -62,7 +62,7 @@ public class ExileAndGainLifeEqualPowerTargetEffect extends OneShotEffect {
int creaturePower = permanent.getPower().getValue();
permanent.moveToExile(null, null, source.getSourceId(), game);
game.applyEffects();
- player.gainLife(creaturePower, game);
+ player.gainLife(creaturePower, game, source);
}
return true;
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/ExileCardYouChooseTargetOpponentEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ExileCardYouChooseTargetOpponentEffect.java
index dc0d697844..9b82b75c37 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/ExileCardYouChooseTargetOpponentEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/ExileCardYouChooseTargetOpponentEffect.java
@@ -51,7 +51,7 @@ public class ExileCardYouChooseTargetOpponentEffect extends OneShotEffect {
public ExileCardYouChooseTargetOpponentEffect(FilterCard filter) {
super(Outcome.Discard);
- staticText = new StringBuilder("Target opponent reveals his or her hand. You choose ")
+ staticText = new StringBuilder("Target opponent reveals their hand. You choose ")
.append(filter.getMessage()).append(" from it and exile that card").toString();
this.filter = filter;
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/ExileCardsFromTopOfLibraryTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ExileCardsFromTopOfLibraryTargetEffect.java
index 9ca03c05f0..d51a986955 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/ExileCardsFromTopOfLibraryTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/ExileCardsFromTopOfLibraryTargetEffect.java
@@ -33,7 +33,7 @@ public class ExileCardsFromTopOfLibraryTargetEffect extends OneShotEffect {
this.amount = amount;
this.staticText = (targetName == null ? "that player" : targetName) + " exiles the top "
+ CardUtil.numberToText(amount, "")
- + (amount == 1 ? "card" : " cards") + " of his or her library";
+ + (amount == 1 ? "card" : " cards") + " of their library";
}
public ExileCardsFromTopOfLibraryTargetEffect(final ExileCardsFromTopOfLibraryTargetEffect effect) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/ExileFromZoneTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ExileFromZoneTargetEffect.java
index 4ff7097f65..f9bf188b29 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/ExileFromZoneTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/ExileFromZoneTargetEffect.java
@@ -27,6 +27,7 @@
*/
package mage.abilities.effects.common;
+import java.util.Locale;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
@@ -106,6 +107,6 @@ public class ExileFromZoneTargetEffect extends OneShotEffect {
}
private void setText() {
- staticText = "target player exiles " + CardUtil.numberToText(amount, "a") + ' ' + filter.getMessage() + " from his or her " + zone.toString().toLowerCase();
+ staticText = "target player exiles " + CardUtil.numberToText(amount, "a") + ' ' + filter.getMessage() + " from their " + zone.toString().toLowerCase(Locale.ENGLISH);
}
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/ExileGraveyardAllPlayersEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ExileGraveyardAllPlayersEffect.java
index cc909ce53f..be28efaa8c 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/ExileGraveyardAllPlayersEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/ExileGraveyardAllPlayersEffect.java
@@ -30,10 +30,13 @@ package mage.abilities.effects.common;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
+import mage.cards.Cards;
+import mage.cards.CardsImpl;
import mage.constants.Outcome;
+import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.FilterCard;
+import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
@@ -44,15 +47,29 @@ import mage.players.Player;
public class ExileGraveyardAllPlayersEffect extends OneShotEffect {
private final FilterCard filter;
+ private final TargetController targetController;
public ExileGraveyardAllPlayersEffect() {
- this(new FilterCard("cards"));
+ this(StaticFilters.FILTER_CARD_CARDS);
}
public ExileGraveyardAllPlayersEffect(FilterCard filter) {
- super(Outcome.Detriment);
- staticText = "exile all " + filter.getMessage() + " from all graveyards";
+ this(filter, TargetController.ANY);
+ }
+
+ public ExileGraveyardAllPlayersEffect(FilterCard filter, TargetController targetController) {
+ super(Outcome.Exile);
this.filter = filter;
+ this.targetController = targetController;
+ staticText = "exile all " + filter.getMessage() + " from all "
+ + (targetController.equals(TargetController.OPPONENT) ? "opponents' " : "")
+ + "graveyards";
+ }
+
+ public ExileGraveyardAllPlayersEffect(final ExileGraveyardAllPlayersEffect effect) {
+ super(effect);
+ this.filter = effect.filter;
+ this.targetController = effect.targetController;
}
@Override
@@ -66,18 +83,17 @@ public class ExileGraveyardAllPlayersEffect extends OneShotEffect {
if (controller == null) {
return false;
}
-
+ Cards toExile = new CardsImpl();
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
+ if (TargetController.OPPONENT.equals(targetController) && playerId.equals(source.getControllerId())) {
+ continue;
+ }
Player player = game.getPlayer(playerId);
if (player != null) {
- for (UUID cid : player.getGraveyard().copy()) {
- Card card = game.getCard(cid);
- if (card != null && filter.match(card, game)) {
- controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, Zone.GRAVEYARD, true);
- }
- }
+ toExile.addAll(player.getGraveyard());
}
}
+ controller.moveCards(toExile, Zone.EXILED, source, game);
return true;
}
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/ExileSourceUnlessPaysEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ExileSourceUnlessPaysEffect.java
index 1b10a2c554..3993002f4f 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/ExileSourceUnlessPaysEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/ExileSourceUnlessPaysEffect.java
@@ -27,6 +27,7 @@
*/
package mage.abilities.effects.common;
+import java.util.Locale;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.costs.Cost;
@@ -38,7 +39,7 @@ import mage.players.Player;
import mage.util.CardUtil;
/**
- *
+ *
* @author fireshoes
*/
public class ExileSourceUnlessPaysEffect extends OneShotEffect {
@@ -61,7 +62,7 @@ public class ExileSourceUnlessPaysEffect extends OneShotEffect {
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (controller != null && sourcePermanent != null) {
StringBuilder sb = new StringBuilder(cost.getText()).append('?');
- if (!sb.toString().toLowerCase().startsWith("exile ") && !sb.toString().toLowerCase().startsWith("return ")) {
+ if (!sb.toString().toLowerCase(Locale.ENGLISH).startsWith("exile ") && !sb.toString().toLowerCase(Locale.ENGLISH).startsWith("return ")) {
sb.insert(0, "Pay ");
}
String message = CardUtil.replaceSourceName(sb.toString(), sourcePermanent.getLogName());
@@ -91,12 +92,12 @@ public class ExileSourceUnlessPaysEffect extends OneShotEffect {
StringBuilder sb = new StringBuilder("exile {this} unless you ");
String costText = cost.getText();
- if (costText.toLowerCase().startsWith("discard")
- || costText.toLowerCase().startsWith("remove")
- || costText.toLowerCase().startsWith("return")
- || costText.toLowerCase().startsWith("exile")
- || costText.toLowerCase().startsWith("sacrifice")) {
- sb.append(costText.substring(0, 1).toLowerCase());
+ if (costText.toLowerCase(Locale.ENGLISH).startsWith("discard")
+ || costText.toLowerCase(Locale.ENGLISH).startsWith("remove")
+ || costText.toLowerCase(Locale.ENGLISH).startsWith("return")
+ || costText.toLowerCase(Locale.ENGLISH).startsWith("exile")
+ || costText.toLowerCase(Locale.ENGLISH).startsWith("sacrifice")) {
+ sb.append(costText.substring(0, 1).toLowerCase(Locale.ENGLISH));
sb.append(costText.substring(1));
} else {
sb.append("pay ").append(costText);
diff --git a/Mage/src/main/java/mage/abilities/effects/common/ExileTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ExileTargetEffect.java
index cff17c7be8..4a3c19865c 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/ExileTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/ExileTargetEffect.java
@@ -30,6 +30,7 @@ package mage.abilities.effects.common;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.UUID;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.OneShotEffect;
@@ -56,6 +57,7 @@ public class ExileTargetEffect extends OneShotEffect {
private String exileZone = null;
private UUID exileId = null;
protected boolean multitargetHandling;
+ private boolean toSourceExileZone = false; // exile the targets to a source object specific exile zone (takes care of zone change counter)
public ExileTargetEffect(String effectText) {
this(effectText, false);
@@ -93,6 +95,7 @@ public class ExileTargetEffect extends OneShotEffect {
this.exileId = effect.exileId;
this.onlyFromZone = effect.onlyFromZone;
this.multitargetHandling = effect.multitargetHandling;
+ this.toSourceExileZone = effect.toSourceExileZone;
}
@Override
@@ -100,6 +103,11 @@ public class ExileTargetEffect extends OneShotEffect {
return new ExileTargetEffect(this);
}
+ public ExileTargetEffect setToSourceExileZone(boolean toSourceExileZone) {
+ this.toSourceExileZone = toSourceExileZone;
+ return this;
+ }
+
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
@@ -156,6 +164,13 @@ public class ExileTargetEffect extends OneShotEffect {
}
}
}
+ if (toSourceExileZone) {
+ MageObject sourceObject = source.getSourceObject(game);
+ exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
+ if (sourceObject != null) {
+ exileZone = sourceObject.getIdName();
+ }
+ }
controller.moveCardsToExile(toExile, source, game, true, exileId, exileZone);
return true;
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/FightTargetsEffect.java b/Mage/src/main/java/mage/abilities/effects/common/FightTargetsEffect.java
index 1cf4b86d38..dc5a3034c2 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/FightTargetsEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/FightTargetsEffect.java
@@ -31,7 +31,6 @@ import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
-import mage.constants.CardType;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.permanent.Permanent;
diff --git a/Mage/src/main/java/mage/abilities/effects/common/FlipSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/FlipSourceEffect.java
index 2ed186cd42..aaa4679372 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/FlipSourceEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/FlipSourceEffect.java
@@ -8,6 +8,7 @@ import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.permanent.Permanent;
+import mage.game.permanent.token.TokenImpl;
import mage.game.permanent.token.Token;
import mage.players.Player;
diff --git a/Mage/src/main/java/mage/abilities/effects/common/GainLifeEffect.java b/Mage/src/main/java/mage/abilities/effects/common/GainLifeEffect.java
index fc30f8ad1d..30e18a80b5 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/GainLifeEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/GainLifeEffect.java
@@ -74,7 +74,7 @@ public class GainLifeEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
- player.gainLife(life.calculate(game, source, this), game);
+ player.gainLife(life.calculate(game, source, this), game, source);
}
return true;
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/GainLifeTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/GainLifeTargetEffect.java
index b9c694dd7c..1b1da3f009 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/GainLifeTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/GainLifeTargetEffect.java
@@ -71,7 +71,7 @@ public class GainLifeTargetEffect extends OneShotEffect {
for (UUID playerId: targetPointer.getTargets(game, source)) {
Player player = game.getPlayer(playerId);
if (player != null) {
- player.gainLife(life.calculate(game, source, this), game);
+ player.gainLife(life.calculate(game, source, this), game, source);
}
}
return true;
diff --git a/Mage/src/main/java/mage/abilities/effects/common/HideawayPlayEffect.java b/Mage/src/main/java/mage/abilities/effects/common/HideawayPlayEffect.java
index 986711813a..8fed10126d 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/HideawayPlayEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/HideawayPlayEffect.java
@@ -30,7 +30,6 @@ package mage.abilities.effects.common;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
-import mage.constants.CardType;
import mage.constants.Outcome;
import mage.game.ExileZone;
import mage.game.Game;
diff --git a/Mage/src/main/java/mage/abilities/effects/common/LookLibraryAndPickControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/LookLibraryAndPickControllerEffect.java
index 359666cd8d..9ab2ff079a 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/LookLibraryAndPickControllerEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/LookLibraryAndPickControllerEffect.java
@@ -30,6 +30,7 @@
package mage.abilities.effects.common;
import static java.lang.Integer.min;
+import java.util.Locale;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.dynamicvalue.DynamicValue;
@@ -59,22 +60,35 @@ public class LookLibraryAndPickControllerEffect extends LookLibraryControllerEff
protected boolean optional;
private boolean upTo;
private boolean putOnTopSelected;
+ private boolean anyOrder;
- public LookLibraryAndPickControllerEffect(DynamicValue numberOfCards, boolean mayShuffleAfter, DynamicValue numberToPick, FilterCard pickFilter, boolean putOnTop) {
- this(numberOfCards, mayShuffleAfter, numberToPick, pickFilter, putOnTop, true);
+ public LookLibraryAndPickControllerEffect(DynamicValue numberOfCards,
+ boolean mayShuffleAfter, DynamicValue numberToPick,
+ FilterCard pickFilter, boolean putOnTop) {
+ this(numberOfCards, mayShuffleAfter, numberToPick, pickFilter,
+ putOnTop, true);
}
- public LookLibraryAndPickControllerEffect(DynamicValue numberOfCards, boolean mayShuffleAfter, DynamicValue numberToPick, FilterCard pickFilter, boolean putOnTop, boolean reveal) {
- this(numberOfCards, mayShuffleAfter, numberToPick, pickFilter, Zone.LIBRARY, putOnTop, reveal);
+ public LookLibraryAndPickControllerEffect(DynamicValue numberOfCards,
+ boolean mayShuffleAfter, DynamicValue numberToPick,
+ FilterCard pickFilter, boolean putOnTop, boolean reveal) {
+ this(numberOfCards, mayShuffleAfter, numberToPick, pickFilter,
+ Zone.LIBRARY, putOnTop, reveal);
}
- public LookLibraryAndPickControllerEffect(DynamicValue numberOfCards, boolean mayShuffleAfter, DynamicValue numberToPick,
- FilterCard pickFilter, Zone targetZoneLookedCards, boolean putOnTop, boolean reveal) {
- this(numberOfCards, mayShuffleAfter, numberToPick, pickFilter, targetZoneLookedCards, putOnTop, reveal, false);
+ public LookLibraryAndPickControllerEffect(DynamicValue numberOfCards,
+ boolean mayShuffleAfter, DynamicValue numberToPick,
+ FilterCard pickFilter, Zone targetZoneLookedCards,
+ boolean putOnTop, boolean reveal) {
+ this(numberOfCards, mayShuffleAfter, numberToPick, pickFilter,
+ targetZoneLookedCards, putOnTop, reveal, false);
}
- public LookLibraryAndPickControllerEffect(int numberOfCards, int numberToPick, FilterCard pickFilter, boolean upTo) {
- this(new StaticValue(numberOfCards), false, new StaticValue(numberToPick), pickFilter, Zone.LIBRARY, false, true, upTo);
+ public LookLibraryAndPickControllerEffect(int numberOfCards,
+ int numberToPick, FilterCard pickFilter, boolean upTo) {
+ this(new StaticValue(numberOfCards), false,
+ new StaticValue(numberToPick), pickFilter, Zone.LIBRARY, false,
+ true, upTo);
}
/**
@@ -87,9 +101,12 @@ public class LookLibraryAndPickControllerEffect extends LookLibraryControllerEff
* @param targetZonePickedCards
* @param optional
*/
- public LookLibraryAndPickControllerEffect(int numberOfCards, int numberToPick, FilterCard pickFilter, boolean reveal, boolean upTo,
- Zone targetZonePickedCards, boolean optional) {
- this(new StaticValue(numberOfCards), false, new StaticValue(numberToPick), pickFilter, Zone.LIBRARY, false, reveal, upTo, targetZonePickedCards, optional);
+ public LookLibraryAndPickControllerEffect(int numberOfCards,
+ int numberToPick, FilterCard pickFilter, boolean reveal,
+ boolean upTo, Zone targetZonePickedCards, boolean optional) {
+ this(new StaticValue(numberOfCards), false,
+ new StaticValue(numberToPick), pickFilter, Zone.LIBRARY, false,
+ reveal, upTo, targetZonePickedCards, optional, true, true);
}
@@ -101,13 +118,17 @@ public class LookLibraryAndPickControllerEffect extends LookLibraryControllerEff
* @param pickFilter
* @param targetZoneLookedCards
* @param putOnTop if zone for the rest is library decide if cards go to top
- * or butoom
+ * or bottom
* @param reveal
* @param upTo
*/
- public LookLibraryAndPickControllerEffect(DynamicValue numberOfCards, boolean mayShuffleAfter, DynamicValue numberToPick,
- FilterCard pickFilter, Zone targetZoneLookedCards, boolean putOnTop, boolean reveal, boolean upTo) {
- this(numberOfCards, mayShuffleAfter, numberToPick, pickFilter, targetZoneLookedCards, putOnTop, reveal, upTo, Zone.HAND, false);
+ public LookLibraryAndPickControllerEffect(DynamicValue numberOfCards,
+ boolean mayShuffleAfter, DynamicValue numberToPick,
+ FilterCard pickFilter, Zone targetZoneLookedCards,
+ boolean putOnTop, boolean reveal, boolean upTo) {
+ this(numberOfCards, mayShuffleAfter, numberToPick, pickFilter,
+ targetZoneLookedCards, putOnTop, reveal, upTo, Zone.HAND,
+ false, true, true);
}
/**
@@ -118,15 +139,20 @@ public class LookLibraryAndPickControllerEffect extends LookLibraryControllerEff
* @param pickFilter
* @param targetZoneLookedCards
* @param putOnTop if zone for the rest is library decide if cards go to top
- * or butoom
+ * or bottom
* @param reveal
* @param upTo
* @param targetZonePickedCards
* @param optional
*/
- public LookLibraryAndPickControllerEffect(DynamicValue numberOfCards, boolean mayShuffleAfter, DynamicValue numberToPick,
- FilterCard pickFilter, Zone targetZoneLookedCards, boolean putOnTop, boolean reveal, boolean upTo, Zone targetZonePickedCards, boolean optional) {
- this(numberOfCards, mayShuffleAfter, numberToPick, pickFilter, targetZoneLookedCards, putOnTop, reveal, upTo, targetZonePickedCards, optional, true);
+ public LookLibraryAndPickControllerEffect(DynamicValue numberOfCards,
+ boolean mayShuffleAfter, DynamicValue numberToPick,
+ FilterCard pickFilter, Zone targetZoneLookedCards, boolean putOnTop,
+ boolean reveal, boolean upTo, Zone targetZonePickedCards,
+ boolean optional) {
+ this(numberOfCards, mayShuffleAfter, numberToPick, pickFilter,
+ targetZoneLookedCards, putOnTop, reveal, upTo,
+ targetZonePickedCards, optional, true, true);
}
/**
@@ -137,16 +163,21 @@ public class LookLibraryAndPickControllerEffect extends LookLibraryControllerEff
* @param pickFilter
* @param targetZoneLookedCards
* @param putOnTop if zone for the rest is library decide if cards go to top
- * or butoom
+ * or bottom
* @param reveal
* @param upTo
* @param targetZonePickedCards
* @param optional
* @param putOnTopSelected
+ * @param anyOrder
*/
- public LookLibraryAndPickControllerEffect(DynamicValue numberOfCards, boolean mayShuffleAfter, DynamicValue numberToPick,
- FilterCard pickFilter, Zone targetZoneLookedCards, boolean putOnTop, boolean reveal, boolean upTo, Zone targetZonePickedCards, boolean optional, boolean putOnTopSelected) {
- super(Outcome.DrawCard, numberOfCards, mayShuffleAfter, targetZoneLookedCards, putOnTop);
+ public LookLibraryAndPickControllerEffect(DynamicValue numberOfCards,
+ boolean mayShuffleAfter, DynamicValue numberToPick,
+ FilterCard pickFilter, Zone targetZoneLookedCards, boolean putOnTop,
+ boolean reveal, boolean upTo, Zone targetZonePickedCards,
+ boolean optional, boolean putOnTopSelected, boolean anyOrder) {
+ super(Outcome.DrawCard, numberOfCards, mayShuffleAfter,
+ targetZoneLookedCards, putOnTop);
this.numberToPick = numberToPick;
this.filter = pickFilter;
this.revealPickedCards = reveal;
@@ -154,6 +185,7 @@ public class LookLibraryAndPickControllerEffect extends LookLibraryControllerEff
this.upTo = upTo;
this.optional = optional;
this.putOnTopSelected = putOnTopSelected;
+ this.anyOrder = anyOrder;
}
public LookLibraryAndPickControllerEffect(final LookLibraryAndPickControllerEffect effect) {
@@ -165,6 +197,7 @@ public class LookLibraryAndPickControllerEffect extends LookLibraryControllerEff
this.upTo = effect.upTo;
this.optional = effect.optional;
this.putOnTopSelected = effect.putOnTopSelected;
+ this.anyOrder = effect.anyOrder;
}
@Override
@@ -193,7 +226,7 @@ public class LookLibraryAndPickControllerEffect extends LookLibraryControllerEff
Cards pickedCards = new CardsImpl(target.getTargets());
cards.removeAll(pickedCards);
if (targetPickedCards == Zone.LIBRARY && !putOnTopSelected) {
- player.putCardsOnBottomOfLibrary(pickedCards, game, source, true);
+ player.putCardsOnBottomOfLibrary(pickedCards, game, source, anyOrder);
} else {
player.moveCards(pickedCards.getCards(game), targetPickedCards, source, game);
}
@@ -234,7 +267,12 @@ public class LookLibraryAndPickControllerEffect extends LookLibraryControllerEff
if (putOnTopSelected) {
sb.append("put on the top of your library");
} else {
- sb.append("put on the buttom of your library");
+ sb.append("put on the bottom of your library");
+ }
+ if (anyOrder) {
+ sb.append(" in any order");
+ } else {
+ sb.append(" in random order");
}
break;
case HAND:
@@ -291,7 +329,7 @@ public class LookLibraryAndPickControllerEffect extends LookLibraryControllerEff
sb.append(" of them into your ");
}
- sb.append(targetPickedCards.toString().toLowerCase());
+ sb.append(targetPickedCards.toString().toLowerCase(Locale.ENGLISH));
if (targetZoneLookedCards == Zone.LIBRARY) {
sb.append(". Put the rest ");
@@ -300,7 +338,13 @@ public class LookLibraryAndPickControllerEffect extends LookLibraryControllerEff
} else {
sb.append("on the bottom");
}
- sb.append(" of your library in any order");
+ sb.append(" of your library in ");
+ if (anyOrder) {
+ sb.append("any");
+ } else {
+ sb.append("random");
+ }
+ sb.append(" order");
} else if (targetZoneLookedCards == Zone.GRAVEYARD) {
sb.append(" and the other into your graveyard");
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/LookLibraryControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/LookLibraryControllerEffect.java
index 35f764ccf8..93f260874f 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/LookLibraryControllerEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/LookLibraryControllerEffect.java
@@ -86,7 +86,6 @@ public class LookLibraryControllerEffect extends OneShotEffect {
this.mayShuffleAfter = mayShuffleAfter;
this.targetZoneLookedCards = targetZoneLookedCards;
this.putOnTop = putOnTop;
-
}
public LookLibraryControllerEffect(final LookLibraryControllerEffect effect) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/LoseHalfLifeTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/LoseHalfLifeTargetEffect.java
index 0ec7b872ab..295f765d48 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/LoseHalfLifeTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/LoseHalfLifeTargetEffect.java
@@ -41,7 +41,7 @@ public class LoseHalfLifeTargetEffect extends OneShotEffect {
public LoseHalfLifeTargetEffect() {
super(Outcome.Damage);
- staticText = "that player loses half his or her life, rounded up";
+ staticText = "that player loses half their life, rounded up";
}
public LoseHalfLifeTargetEffect(final LoseHalfLifeTargetEffect effect) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/PreventDamageByTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PreventDamageByTargetEffect.java
index 081cd81b8c..7bffd0719a 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/PreventDamageByTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/PreventDamageByTargetEffect.java
@@ -31,7 +31,6 @@ import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.PreventionEffectImpl;
-import mage.constants.CardType;
import mage.constants.Duration;
import mage.game.Game;
import mage.game.events.GameEvent;
diff --git a/Mage/src/main/java/mage/abilities/effects/common/PreventAllDamageToAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PreventDamageToAttachedEffect.java
similarity index 61%
rename from Mage/src/main/java/mage/abilities/effects/common/PreventAllDamageToAttachedEffect.java
rename to Mage/src/main/java/mage/abilities/effects/common/PreventDamageToAttachedEffect.java
index 289a5f0e13..2d94f7d493 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/PreventAllDamageToAttachedEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/PreventDamageToAttachedEffect.java
@@ -25,11 +25,11 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
-
package mage.abilities.effects.common;
import mage.abilities.Ability;
import mage.abilities.effects.PreventionEffectImpl;
+import mage.constants.AttachmentType;
import mage.constants.Duration;
import mage.game.Game;
import mage.game.events.DamageEvent;
@@ -40,49 +40,65 @@ import mage.game.permanent.Permanent;
*
* @author LevelX2
*/
-public class PreventAllDamageToAttachedEffect extends PreventionEffectImpl {
+public class PreventDamageToAttachedEffect extends PreventionEffectImpl {
- private final String attachedDescription;
+ protected AttachmentType attachmentType;
- public PreventAllDamageToAttachedEffect(Duration duration, String attachedDescription, boolean combatOnly) {
- super(duration, Integer.MAX_VALUE, false);
- this.attachedDescription = attachedDescription;
+ public PreventDamageToAttachedEffect(Duration duration, AttachmentType attachmentType, boolean combatOnly) {
+ this(duration, attachmentType, Integer.MAX_VALUE, combatOnly);
+ }
+
+ public PreventDamageToAttachedEffect(Duration duration, AttachmentType attachmentType, int amountToPrevent, boolean combatOnly) {
+ super(duration, amountToPrevent, combatOnly, false);
+ this.attachmentType = attachmentType;
staticText = setText();
}
- public PreventAllDamageToAttachedEffect(final PreventAllDamageToAttachedEffect effect) {
+ public PreventDamageToAttachedEffect(final PreventDamageToAttachedEffect effect) {
super(effect);
- this.attachedDescription = effect.attachedDescription;
+ this.attachmentType = effect.attachmentType;
}
@Override
- public PreventAllDamageToAttachedEffect copy() {
- return new PreventAllDamageToAttachedEffect(this);
+ public PreventDamageToAttachedEffect copy() {
+ return new PreventDamageToAttachedEffect(this);
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (super.applies(event, source, game)) {
- if (!onlyCombat || ((DamageEvent)event).isCombatDamage()) {
+ if (!onlyCombat || ((DamageEvent) event).isCombatDamage()) {
Permanent attachment = game.getPermanent(source.getSourceId());
- if (attachment != null
+ if (attachment != null
&& attachment.getAttachedTo() != null) {
if (event.getTargetId().equals(attachment.getAttachedTo())) {
return true;
}
- }
+ }
}
}
return false;
}
private String setText() {
- StringBuilder sb = new StringBuilder("Prevent all ");
- if (onlyCombat) {
- sb.append("combat ");
+ StringBuilder sb = new StringBuilder();
+ if (amountToPrevent == Integer.MAX_VALUE) {
+ sb.append("prevent all ");
+ if (onlyCombat) {
+ sb.append("combat ");
+ }
+ sb.append("damage that would be dealt to ");
+ sb.append(attachmentType.verb()).append(" creature");
+ } else {
+ sb.append("If a source would deal ");
+ if (onlyCombat) {
+ sb.append("combat ");
+ }
+ sb.append("damage to ");
+ sb.append(attachmentType.verb());
+ sb.append("creature, prevent ").append(amountToPrevent);;
+ sb.append("of that damage");
}
- sb.append("damage that would be dealt to ");
- sb.append(attachedDescription);
return sb.toString();
}
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/PreventDamageToTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PreventDamageToTargetEffect.java
index aa07e5bdd0..af82bbf0a8 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/PreventDamageToTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/PreventDamageToTargetEffect.java
@@ -82,11 +82,16 @@ public class PreventDamageToTargetEffect extends PreventionEffectImpl {
}
StringBuilder sb = new StringBuilder();
if (amountToPrevent == Integer.MAX_VALUE) {
- sb.append("prevent all damage that would be dealt to target ");
+ sb.append("prevent all damage that would be dealt to ");
} else {
- sb.append("prevent the next ").append(amountToPrevent).append(" damage that would be dealt to target ");
+ sb.append("prevent the next ").append(amountToPrevent).append(" damage that would be dealt to ");
+ }
+ String targetName = mode.getTargets().get(0).getTargetName();
+ if (targetName.contains("any")) {
+ sb.append(targetName);
+ } else {
+ sb.append("target ").append(targetName);
}
- sb.append(mode.getTargets().get(0).getTargetName());
if (!duration.toString().isEmpty()) {
sb.append(' ');
if (duration == Duration.EndOfTurn) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/PutLibraryIntoGraveTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PutLibraryIntoGraveTargetEffect.java
index 08eafb24e7..c38f45161e 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/PutLibraryIntoGraveTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/PutLibraryIntoGraveTargetEffect.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,21 +20,20 @@
* 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.abilities.effects.common;
-import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.OneShotEffect;
+import mage.constants.Outcome;
+import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.util.CardUtil;
@@ -88,7 +87,7 @@ public class PutLibraryIntoGraveTargetEffect extends OneShotEffect {
StringBuilder sb = new StringBuilder();
String message = amount.getMessage();
- sb.append("Target ").append(mode.getTargets().get(0).getTargetName());
+ sb.append("target ").append(mode.getTargets().get(0).getTargetName());
sb.append(" puts the top ");
if (message.isEmpty()) {
if (amount.toString().equals("1")) {
@@ -99,7 +98,7 @@ public class PutLibraryIntoGraveTargetEffect extends OneShotEffect {
} else {
sb.append(" X cards ");
}
- sb.append("of his or her library into his or her graveyard");
+ sb.append("of their library into their graveyard");
if (!message.isEmpty()) {
sb.append(", where X is the number of ");
diff --git a/Mage/src/main/java/mage/abilities/effects/common/PutPermanentOnBattlefieldEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PutPermanentOnBattlefieldEffect.java
index fbde03f3d6..c6f2461b5a 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/PutPermanentOnBattlefieldEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/PutPermanentOnBattlefieldEffect.java
@@ -75,7 +75,7 @@ public class PutPermanentOnBattlefieldEffect extends OneShotEffect {
}
if (useTargetController) {
- return "that player may put " + filter.getMessage() + " from his or her hand onto the battlefield";
+ return "that player may put " + filter.getMessage() + " from their hand onto the battlefield";
} else {
return "you may put " + filter.getMessage() + " from your hand onto the battlefield";
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveEachPlayerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveEachPlayerEffect.java
index 0a378703ab..ee596c1d49 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveEachPlayerEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveEachPlayerEffect.java
@@ -129,7 +129,7 @@ public class PutTopCardOfLibraryIntoGraveEachPlayerEffect extends OneShotEffect
sb.append(CardUtil.numberToText(numberCards.toString()));
sb.append(" cards");
}
- sb.append(" of his or her library into his or her graveyard");
+ sb.append(" of their library into their graveyard");
return sb.toString();
}
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveTargetEffect.java
index 717a3426b5..46c3b42bd2 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveTargetEffect.java
@@ -82,7 +82,7 @@ public class PutTopCardOfLibraryIntoGraveTargetEffect extends OneShotEffect {
sb.append(CardUtil.numberToText(numberCards.toString()));
sb.append(" cards");
}
- sb.append(" of his or her library into his or her graveyard");
+ sb.append(" of their library into their graveyard");
return sb.toString();
}
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/RegenerateAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/RegenerateAttachedEffect.java
index 2bf62a4b5b..332ab81228 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/RegenerateAttachedEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/RegenerateAttachedEffect.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,21 +20,20 @@
* 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.abilities.effects.common;
+import java.util.Locale;
import java.util.UUID;
-
+import mage.abilities.Ability;
+import mage.abilities.effects.ReplacementEffectImpl;
import mage.constants.AttachmentType;
import mage.constants.Duration;
import mage.constants.Outcome;
-import mage.abilities.Ability;
-import mage.abilities.effects.ReplacementEffectImpl;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
@@ -103,6 +102,6 @@ public class RegenerateAttachedEffect extends ReplacementEffectImpl {
}
private void setText() {
- staticText = "Regenerate " + attachmentType.verb().toLowerCase() + " creature";
+ staticText = "Regenerate " + attachmentType.verb().toLowerCase(Locale.ENGLISH) + " creature";
}
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/RegenerateTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/RegenerateTargetEffect.java
index c5a7b20e6b..296efa7fa8 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/RegenerateTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/RegenerateTargetEffect.java
@@ -25,14 +25,14 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
-
package mage.abilities.effects.common;
-import mage.constants.Duration;
-import mage.constants.Outcome;
+import java.util.Locale;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.ReplacementEffectImpl;
+import mage.constants.Duration;
+import mage.constants.Outcome;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
@@ -43,9 +43,9 @@ import mage.target.Target;
*
* @author maurer.it_at_gmail.com
*/
-public class RegenerateTargetEffect extends ReplacementEffectImpl {
+public class RegenerateTargetEffect extends ReplacementEffectImpl {
- public RegenerateTargetEffect ( ) {
+ public RegenerateTargetEffect() {
super(Duration.EndOfTurn, Outcome.Regenerate);
}
@@ -82,7 +82,7 @@ public class RegenerateTargetEffect extends ReplacementEffectImpl {
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
//20110204 - 701.11c - event.getAmount() is used to signal if regeneration is allowed
-
+
return event.getAmount() == 0 && event.getTargetId().equals(targetPointer.getFirst(game, source)) && !this.used;
}
@@ -95,7 +95,7 @@ public class RegenerateTargetEffect extends ReplacementEffectImpl {
sb.append("Regenerate ");
Target target = mode.getTargets().get(0);
if (target != null) {
- if (!target.getTargetName().toLowerCase().startsWith("another")) {
+ if (!target.getTargetName().toLowerCase(Locale.ENGLISH).startsWith("another")) {
sb.append("target ");
}
sb.append(target.getTargetName());
diff --git a/Mage/src/main/java/mage/abilities/effects/common/ReplaceOpponentCardsInHandWithSelectedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ReplaceOpponentCardsInHandWithSelectedEffect.java
index 75dd688211..be82e747f1 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/ReplaceOpponentCardsInHandWithSelectedEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/ReplaceOpponentCardsInHandWithSelectedEffect.java
@@ -47,7 +47,7 @@ public class ReplaceOpponentCardsInHandWithSelectedEffect extends OneShotEffect
public ReplaceOpponentCardsInHandWithSelectedEffect() {
super(Outcome.Detriment);
- this.staticText = "Target opponent puts the cards from his or her hand on top of his or her library. Search that player's library for that many cards. The player puts those cards into his or her hand, then shuffles his or her library.";
+ this.staticText = "Target opponent puts the cards from their hand on top of their library. Search that player's library for that many cards. The player puts those cards into their hand, then shuffles their library.";
}
public ReplaceOpponentCardsInHandWithSelectedEffect(final ReplaceOpponentCardsInHandWithSelectedEffect effect) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/ReturnToBattlefieldUnderOwnerControlSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ReturnToBattlefieldUnderOwnerControlSourceEffect.java
index 568f47429d..1f5b793faf 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/ReturnToBattlefieldUnderOwnerControlSourceEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/ReturnToBattlefieldUnderOwnerControlSourceEffect.java
@@ -41,6 +41,7 @@ import mage.game.Game;
public class ReturnToBattlefieldUnderOwnerControlSourceEffect extends OneShotEffect {
private boolean tapped;
+ private boolean attacking;
private int zoneChangeCounter;
public ReturnToBattlefieldUnderOwnerControlSourceEffect() {
@@ -52,16 +53,25 @@ public class ReturnToBattlefieldUnderOwnerControlSourceEffect extends OneShotEff
}
public ReturnToBattlefieldUnderOwnerControlSourceEffect(boolean tapped, int zoneChangeCounter) {
+ this(tapped, false, zoneChangeCounter);
+ }
+
+ public ReturnToBattlefieldUnderOwnerControlSourceEffect(boolean tapped, boolean attacking, int zoneChangeCounter) {
super(Outcome.Benefit);
this.tapped = tapped;
+ this.attacking = attacking;
this.zoneChangeCounter = zoneChangeCounter;
- staticText = new StringBuilder("return that card to the battlefield").append(tapped ? " tapped" : "").append(" under its owner's control").toString();
+ staticText = "return that card to the battlefield"
+ + (tapped ? " tapped" : "")
+ + (attacking ? " attacking" : "")
+ + " under its owner's control";
}
public ReturnToBattlefieldUnderOwnerControlSourceEffect(final ReturnToBattlefieldUnderOwnerControlSourceEffect effect) {
super(effect);
this.tapped = effect.tapped;
this.zoneChangeCounter = effect.zoneChangeCounter;
+ this.attacking = effect.attacking;
}
@Override
@@ -80,7 +90,11 @@ public class ReturnToBattlefieldUnderOwnerControlSourceEffect extends OneShotEff
case GRAVEYARD:
if (zoneChangeCounter < 0 || game.getState().getZoneChangeCounter(card.getId()) == zoneChangeCounter) {
Zone currentZone = game.getState().getZone(card.getId());
- card.putOntoBattlefield(game, currentZone, source.getSourceId(), card.getOwnerId(), tapped);
+ if (card.putOntoBattlefield(game, currentZone, source.getSourceId(), card.getOwnerId(), tapped)) {
+ if (attacking) {
+ game.getCombat().addAttackingCreature(card.getId(), game);
+ }
+ }
}
break;
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/ReturnToHandFromGraveyardAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ReturnToHandFromGraveyardAllEffect.java
index 425d4b6ce0..71016ad060 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/ReturnToHandFromGraveyardAllEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/ReturnToHandFromGraveyardAllEffect.java
@@ -48,7 +48,7 @@ public class ReturnToHandFromGraveyardAllEffect extends OneShotEffect {
public ReturnToHandFromGraveyardAllEffect(FilterCard filter) {
super(Outcome.ReturnToHand);
this.filter = filter;
- staticText = "Each player returns all " + filter.getMessage() + " from his or her graveyard to his or her hand";
+ staticText = "Each player returns all " + filter.getMessage() + " from their graveyard to their hand";
}
public ReturnToHandFromGraveyardAllEffect(final ReturnToHandFromGraveyardAllEffect effect) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/RevealCardsFromLibraryUntilEffect.java b/Mage/src/main/java/mage/abilities/effects/common/RevealCardsFromLibraryUntilEffect.java
index 67adcc88a1..50d924df59 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/RevealCardsFromLibraryUntilEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/RevealCardsFromLibraryUntilEffect.java
@@ -152,13 +152,13 @@ public class RevealCardsFromLibraryUntilEffect extends OneShotEffect {
}
case LIBRARY: {
if (shuffleRestInto) {
- sb.append(", then shuffles the rest into his or her library.");
+ sb.append(", then shuffles the rest into their library.");
} else {
sb.append(" and the rest on the bottom of your library in ");
if (anyOrder) {
sb.append("any");
} else {
- sb.append("random");
+ sb.append("a random");
}
sb.append(" order.");
diff --git a/Mage/src/main/java/mage/abilities/effects/common/RevealHandTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/RevealHandTargetEffect.java
index 089e36ef35..8282707d0b 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/RevealHandTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/RevealHandTargetEffect.java
@@ -86,7 +86,7 @@ public class RevealHandTargetEffect extends OneShotEffect {
default:
break;
}
- sb.append(" reveals his or her hand");
+ sb.append(" reveals their hand");
return sb.toString();
}
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/RevealTopLandToBattlefieldElseHandEffect.java b/Mage/src/main/java/mage/abilities/effects/common/RevealTopLandToBattlefieldElseHandEffect.java
index ec06e46b05..62b7b68040 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/RevealTopLandToBattlefieldElseHandEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/RevealTopLandToBattlefieldElseHandEffect.java
@@ -5,7 +5,6 @@ import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardsImpl;
-import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
diff --git a/Mage/src/main/java/mage/abilities/effects/common/RollDiceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/RollDiceEffect.java
index 8b3dfc5e73..506d0f7bef 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/RollDiceEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/RollDiceEffect.java
@@ -30,7 +30,6 @@ package mage.abilities.effects.common;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.Mode;
-import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.Effect;
import mage.abilities.effects.Effects;
import mage.abilities.effects.OneShotEffect;
diff --git a/Mage/src/main/java/mage/abilities/effects/common/RollPlanarDieEffect.java b/Mage/src/main/java/mage/abilities/effects/common/RollPlanarDieEffect.java
new file mode 100644
index 0000000000..923075ef53
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/effects/common/RollPlanarDieEffect.java
@@ -0,0 +1,199 @@
+/*
+ * 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.abilities.effects.common;
+
+import java.util.List;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+import mage.MageObject;
+import mage.abilities.Ability;
+import mage.abilities.Mode;
+import mage.abilities.effects.ContinuousEffect;
+import mage.abilities.effects.Effect;
+import mage.abilities.effects.OneShotEffect;
+import mage.constants.Outcome;
+import mage.constants.PlanarDieRoll;
+import mage.constants.Planes;
+import mage.game.Game;
+import mage.game.command.CommandObject;
+import mage.game.command.Plane;
+import mage.players.Player;
+import mage.target.Target;
+import mage.target.targetpointer.FixedTarget;
+
+/**
+ *
+ * @author spjspj
+ */
+public class RollPlanarDieEffect extends OneShotEffect {
+
+ private static final Logger log = Logger.getLogger("Roll Planar Die");
+
+ protected List chaosEffects = null;
+ protected List chaosTargets = null;
+
+ public RollPlanarDieEffect(List chaosEffects, List chaosTargets) {
+ this(chaosEffects, chaosTargets, Outcome.Neutral);
+ }
+
+ public RollPlanarDieEffect(List chaosEffects, List chaosTargets, Outcome outcome) {
+ super(outcome);
+ addChaosEffects(chaosEffects);
+ addChaosTargets(chaosTargets);
+ }
+
+ public RollPlanarDieEffect(final RollPlanarDieEffect effect) {
+ super(effect);
+ this.chaosEffects = effect.chaosEffects.stream().collect(Collectors.toList());
+ this.chaosTargets = effect.chaosTargets.stream().collect(Collectors.toList());
+ }
+
+ public void addChaosEffects(List chaosEffects) {
+ if (chaosEffects != null) {
+ this.chaosEffects = chaosEffects;
+ }
+ }
+
+ public void addChaosTargets(List chaosTargets) {
+ if (chaosTargets != null) {
+ this.chaosTargets = chaosTargets;
+ }
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player controller = game.getPlayer(source.getControllerId());
+ MageObject mageObject = game.getObject(source.getSourceId());
+ if (controller != null && mageObject != null) {
+ PlanarDieRoll planarRoll = controller.rollPlanarDie(game);
+ if (planarRoll == PlanarDieRoll.CHAOS_ROLL && chaosEffects != null && chaosTargets != null) {
+ for (int i = 0; i < chaosTargets.size(); i++) {
+ Target target = chaosTargets.get(i);
+ if (target != null) {
+ target.clearChosen();
+ }
+ }
+
+ for (int i = 0; i < chaosEffects.size(); i++) {
+ Effect effect = chaosEffects.get(i);
+ Target target = null;
+ if (chaosTargets != null && chaosTargets.size() > i) {
+ target = chaosTargets.get(i);
+ }
+ boolean done = false;
+ while (controller.canRespond() && effect != null && !done) {
+ if (target != null && !target.isChosen() && target.canChoose(controller.getId(), game)) {
+ controller.chooseTarget(Outcome.Benefit, target, source, game);
+ source.addTarget(target);
+ }
+ if (target != null) {
+ effect.setTargetPointer(new FixedTarget(target.getFirstTarget()));
+ }
+ try {
+ effect.apply(game, source);
+ } catch (UnsupportedOperationException exception) {
+ }
+ if (effect instanceof ContinuousEffect) {
+ game.addEffect((ContinuousEffect) effect, source);
+ }
+ done = true;
+ }
+ }
+ } else if (planarRoll == PlanarDieRoll.PLANAR_ROLL) {
+ // Steps: 1) Remove the last plane and set its effects to discarded
+ for (CommandObject cobject : game.getState().getCommand()) {
+ if (cobject instanceof Plane) {
+ game.getState().addSeenPlane((Plane) cobject, game, id);
+ if (((Plane) cobject).getAbilities() != null) {
+ for (Ability ability : ((Plane) cobject).getAbilities()) {
+ for (Effect effect : ability.getEffects()) {
+ if (effect instanceof ContinuousEffect) {
+ ((ContinuousEffect) effect).discard();
+ }
+ }
+ }
+ }
+ game.getState().removeTriggersOfSourceId(((Plane) cobject).getId());
+ game.getState().getCommand().remove(cobject);
+ break;
+ }
+ }
+
+ // 2) Choose a new random plane we haven't been to, or reset if we've been everywhere
+ List planesVisited = game.getState().getSeenPlanes();
+ if (game.getState().getSeenPlanes() != null) {
+ if (planesVisited.size() == Planes.values().length) {
+ game.getState().resetSeenPlanes();
+ }
+ }
+
+ boolean foundNextPlane = false;
+ while (!foundNextPlane) {
+ Plane plane = Plane.getRandomPlane();
+ try {
+ if (plane != null && !planesVisited.contains(plane.getName())) {
+ foundNextPlane = true;
+ plane.setControllerId(controller.getId());
+ game.addPlane(plane, null, controller.getId());
+ }
+ } catch (Exception ex) {
+ }
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public String getText(Mode mode) {
+ if (!staticText.isEmpty()) {
+ return staticText;
+ }
+ StringBuilder sb = new StringBuilder("Roll the planar die. If you roll CHAOS, ");
+ for (int i = 0; i < chaosEffects.size(); i++) {
+ Effect effect = chaosEffects.get(i);
+ if (effect != null) {
+ try {
+ String emode = effect.getText(mode);
+ emode = emode.substring(0, 1).toLowerCase() + emode.substring(1);
+ sb.append(emode);
+ } catch (Exception e) {
+ sb.append("perform the CHAOS action");
+ }
+ }
+ }
+ sb.append(". If you roll PW, planeswalk to a new plane");
+ return sb.toString();
+ }
+
+ @Override
+ public RollPlanarDieEffect copy() {
+ return new RollPlanarDieEffect(this);
+ }
+}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/SacrificeOpponentsUnlessPayEffect.java b/Mage/src/main/java/mage/abilities/effects/common/SacrificeOpponentsUnlessPayEffect.java
index 5c891be7df..92d5021649 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/SacrificeOpponentsUnlessPayEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/SacrificeOpponentsUnlessPayEffect.java
@@ -182,7 +182,7 @@ public class SacrificeOpponentsUnlessPayEffect extends OneShotEffect{
private void setText() {
StringBuilder sb = new StringBuilder();
- sb.append("Each opponent sacrifices ");
+ sb.append("each opponent sacrifices ");
if (amount.toString().equals("X")) {
sb.append(amount.toString());
diff --git a/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceUnlessPaysEffect.java b/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceUnlessPaysEffect.java
index f407374713..75cb98bcbb 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceUnlessPaysEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceUnlessPaysEffect.java
@@ -1,5 +1,6 @@
package mage.abilities.effects.common;
+import java.util.Locale;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.costs.Cost;
@@ -34,7 +35,7 @@ public class SacrificeSourceUnlessPaysEffect extends OneShotEffect {
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (controller != null && sourcePermanent != null) {
StringBuilder sb = new StringBuilder(cost.getText()).append('?');
- if (!sb.toString().toLowerCase().startsWith("exile ") && !sb.toString().toLowerCase().startsWith("return ")) {
+ if (!sb.toString().toLowerCase(Locale.ENGLISH).startsWith("exile ") && !sb.toString().toLowerCase(Locale.ENGLISH).startsWith("return ")) {
sb.insert(0, "Pay ");
}
String message = CardUtil.replaceSourceName(sb.toString(), sourcePermanent.getLogName());
@@ -69,13 +70,13 @@ public class SacrificeSourceUnlessPaysEffect extends OneShotEffect {
StringBuilder sb = new StringBuilder("sacrifice {this} unless you ");
String costText = cost.getText();
- if (costText.toLowerCase().startsWith("discard")
- || costText.toLowerCase().startsWith("remove")
- || costText.toLowerCase().startsWith("return")
- || costText.toLowerCase().startsWith("put")
- || costText.toLowerCase().startsWith("exile")
- || costText.toLowerCase().startsWith("sacrifice")) {
- sb.append(costText.substring(0, 1).toLowerCase());
+ if (costText.toLowerCase(Locale.ENGLISH).startsWith("discard")
+ || costText.toLowerCase(Locale.ENGLISH).startsWith("remove")
+ || costText.toLowerCase(Locale.ENGLISH).startsWith("return")
+ || costText.toLowerCase(Locale.ENGLISH).startsWith("put")
+ || costText.toLowerCase(Locale.ENGLISH).startsWith("exile")
+ || costText.toLowerCase(Locale.ENGLISH).startsWith("sacrifice")) {
+ sb.append(costText.substring(0, 1).toLowerCase(Locale.ENGLISH));
sb.append(costText.substring(1));
} else {
sb.append("pay ").append(costText);
diff --git a/Mage/src/main/java/mage/abilities/effects/common/SetPlayerLifeAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/SetPlayerLifeAllEffect.java
index 4e6b4f8d33..fa7befc917 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/SetPlayerLifeAllEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/SetPlayerLifeAllEffect.java
@@ -62,7 +62,7 @@ public class SetPlayerLifeAllEffect extends OneShotEffect {
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
- player.setLife(amount.calculate(game, source, this), game);
+ player.setLife(amount.calculate(game, source, this), game, source);
}
}
break;
@@ -70,7 +70,7 @@ public class SetPlayerLifeAllEffect extends OneShotEffect {
for (UUID playerId : game.getOpponents(controller.getId())) {
Player player = game.getPlayer(playerId);
if (player != null) {
- player.setLife(amount.calculate(game, source, this), game);
+ player.setLife(amount.calculate(game, source, this), game, source);
}
}
break;
diff --git a/Mage/src/main/java/mage/abilities/effects/common/SetPlayerLifeSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/SetPlayerLifeSourceEffect.java
index ab15b8d853..54db0d0d56 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/SetPlayerLifeSourceEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/SetPlayerLifeSourceEffect.java
@@ -45,7 +45,7 @@ public class SetPlayerLifeSourceEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
- player.setLife(amount.calculate(game, source, this), game);
+ player.setLife(amount.calculate(game, source, this), game, source);
return true;
}
return false;
diff --git a/Mage/src/main/java/mage/abilities/effects/common/SetPlayerLifeTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/SetPlayerLifeTargetEffect.java
index f38181d11e..8f05f221f1 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/SetPlayerLifeTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/SetPlayerLifeTargetEffect.java
@@ -67,7 +67,7 @@ public class SetPlayerLifeTargetEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(targetPointer.getFirst(game, source));
if (player != null) {
- player.setLife(amount.calculate(game, source, this), game);
+ player.setLife(amount.calculate(game, source, this), game, source);
return true;
}
return false;
diff --git a/Mage/src/main/java/mage/abilities/effects/common/ShuffleIntoLibraryGraveOfSourceOwnerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ShuffleIntoLibraryGraveOfSourceOwnerEffect.java
index 563a3d4c47..08f76fd9fb 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/ShuffleIntoLibraryGraveOfSourceOwnerEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/ShuffleIntoLibraryGraveOfSourceOwnerEffect.java
@@ -43,7 +43,7 @@ public class ShuffleIntoLibraryGraveOfSourceOwnerEffect extends OneShotEffect {
public ShuffleIntoLibraryGraveOfSourceOwnerEffect() {
super(Outcome.Benefit);
- staticText = "its owner shuffles his or her graveyard into his or her library";
+ staticText = "its owner shuffles their graveyard into their library";
}
public ShuffleIntoLibraryGraveOfSourceOwnerEffect(final ShuffleIntoLibraryGraveOfSourceOwnerEffect effect) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/ShuffleIntoLibraryTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ShuffleIntoLibraryTargetEffect.java
index 542ad7497f..5166946dfa 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/ShuffleIntoLibraryTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/ShuffleIntoLibraryTargetEffect.java
@@ -56,7 +56,7 @@ public class ShuffleIntoLibraryTargetEffect extends OneShotEffect {
if (staticText != null && !staticText.isEmpty()) {
return staticText;
} else {
- return "choose target " + mode.getTargets().get(0).getTargetName() + ". Its owner shuffles it into his or her library";
+ return "choose target " + mode.getTargets().get(0).getTargetName() + ". Its owner shuffles it into their library";
}
}
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/ShuffleLibraryTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ShuffleLibraryTargetEffect.java
index ea96f30443..705829cd5c 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/ShuffleLibraryTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/ShuffleLibraryTargetEffect.java
@@ -42,7 +42,7 @@ public class ShuffleLibraryTargetEffect extends OneShotEffect {
public ShuffleLibraryTargetEffect() {
super(Outcome.Neutral);
- this.staticText = "Target player shuffles his or her library";
+ this.staticText = "Target player shuffles their library";
}
public ShuffleLibraryTargetEffect(final ShuffleLibraryTargetEffect effect) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/SkipNextCombatEffect.java b/Mage/src/main/java/mage/abilities/effects/common/SkipNextCombatEffect.java
index d324830c0b..20964c43aa 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/SkipNextCombatEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/SkipNextCombatEffect.java
@@ -21,7 +21,7 @@ public class SkipNextCombatEffect extends OneShotEffect {
public SkipNextCombatEffect() {
super(Outcome.Detriment);
- staticText = "target opponent skips his or her next combat phase";
+ staticText = "target opponent skips their next combat phase";
}
public SkipNextCombatEffect(SkipNextCombatEffect effect) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/SkipNextPlayerUntapStepEffect.java b/Mage/src/main/java/mage/abilities/effects/common/SkipNextPlayerUntapStepEffect.java
index 2aadf12f97..66c97e162f 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/SkipNextPlayerUntapStepEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/SkipNextPlayerUntapStepEffect.java
@@ -83,7 +83,7 @@ public class SkipNextPlayerUntapStepEffect extends OneShotEffect {
public String getText(Mode mode) {
StringBuilder sb = new StringBuilder();
if (!staticText.isEmpty()) {
- sb.append(staticText).append(" player skips his or her next untap step");
+ sb.append(staticText).append(" player skips their next untap step");
} else {
sb.append("You skip your next untap step");
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/UntapLandsEffect.java b/Mage/src/main/java/mage/abilities/effects/common/UntapLandsEffect.java
index 670c721933..502b70186b 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/UntapLandsEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/UntapLandsEffect.java
@@ -32,36 +32,45 @@ import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.filter.FilterPermanent;
+import mage.filter.StaticFilters;
import mage.filter.common.FilterLandPermanent;
import mage.filter.predicate.permanent.TappedPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetLandPermanent;
+import mage.util.CardUtil;
/**
- * "Untap up to X lands" effect
+ * "Untap (up to) X lands" effect
*/
public class UntapLandsEffect extends OneShotEffect {
private final int amount;
+ private final boolean upTo;
public UntapLandsEffect(int amount) {
+ this(amount, true);
+ }
+
+ public UntapLandsEffect(int amount, boolean upTo) {
super(Outcome.Untap);
this.amount = amount;
- staticText = "Untap up to " + amount + " lands";
+ this.upTo = upTo;
+ staticText = "untap " + (upTo ? "up to " : "") + CardUtil.numberToText(amount, staticText) + " lands";
}
public UntapLandsEffect(final UntapLandsEffect effect) {
super(effect);
this.amount = effect.amount;
+ this.upTo = effect.upTo;
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
- TargetLandPermanent target = new TargetLandPermanent(0, amount, new FilterLandPermanent(), true);
+ TargetLandPermanent target = new TargetLandPermanent(upTo ? 0 : amount, amount, StaticFilters.FILTER_LAND, true);
if (target.canChoose(source.getSourceId(), source.getControllerId(), game)) {
// UI Shortcut: Check if any lands are already tapped. If there are equal/fewer than amount, give the option to add those in to be untapped now.
diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByAllAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByAllAttachedEffect.java
index 24fa94d0b0..83743a1979 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByAllAttachedEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByAllAttachedEffect.java
@@ -25,15 +25,14 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
-
package mage.abilities.effects.common.combat;
+import java.util.Locale;
import java.util.UUID;
-
-import mage.constants.AttachmentType;
-import mage.constants.Duration;
import mage.abilities.Ability;
import mage.abilities.effects.RequirementEffect;
+import mage.constants.AttachmentType;
+import mage.constants.Duration;
import mage.game.Game;
import mage.game.permanent.Permanent;
@@ -51,7 +50,7 @@ public class MustBeBlockedByAllAttachedEffect extends RequirementEffect {
public MustBeBlockedByAllAttachedEffect(Duration duration, AttachmentType attachmentType) {
super(duration);
this.attachmentType = attachmentType;
- staticText = "All creatures able to block " + attachmentType.verb().toLowerCase() + " creature do so";
+ staticText = "All creatures able to block " + attachmentType.verb().toLowerCase(Locale.ENGLISH) + " creature do so";
}
public MustBeBlockedByAllAttachedEffect(final MustBeBlockedByAllAttachedEffect effect) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSuperTypeAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSuperTypeAttachedEffect.java
new file mode 100644
index 0000000000..ac3b838f2a
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSuperTypeAttachedEffect.java
@@ -0,0 +1,81 @@
+/*
+ * 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.abilities.effects.common.continuous;
+
+import java.util.Locale;
+import mage.abilities.Ability;
+import mage.abilities.effects.ContinuousEffectImpl;
+import mage.constants.*;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+
+/**
+ * @author nantuko
+ */
+public class AddCardSuperTypeAttachedEffect extends ContinuousEffectImpl {
+
+ private final SuperType addedSuperType;
+ private final AttachmentType attachmentType;
+
+ public AddCardSuperTypeAttachedEffect(SuperType addedSuperType, Duration duration, AttachmentType attachmentType) {
+ super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit);
+ this.addedSuperType = addedSuperType;
+ this.attachmentType = attachmentType;
+ setText();
+ }
+
+ public AddCardSuperTypeAttachedEffect(final AddCardSuperTypeAttachedEffect effect) {
+ super(effect);
+ this.addedSuperType = effect.addedSuperType;
+ this.attachmentType = effect.attachmentType;
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Permanent equipment = game.getPermanent(source.getSourceId());
+ if (equipment != null && equipment.getAttachedTo() != null) {
+ Permanent target = game.getPermanent(equipment.getAttachedTo());
+ if (target != null && !target.getSuperType().contains(addedSuperType)) {
+ target.addSuperType(addedSuperType);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public AddCardSuperTypeAttachedEffect copy() {
+ return new AddCardSuperTypeAttachedEffect(this);
+ }
+
+ private void setText() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(attachmentType.verb());
+ sb.append(" permanent is ").append(addedSuperType.toString().toLowerCase(Locale.ENGLISH)); //TODO add attacked card type detection
+ staticText = sb.toString();
+ }
+}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeSourceEffect.java
index 4858b6e169..5087109fa5 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeSourceEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeSourceEffect.java
@@ -28,6 +28,7 @@
package mage.abilities.effects.common.continuous;
import java.util.ArrayList;
+import java.util.Locale;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.Mode;
@@ -104,7 +105,7 @@ public class AddCardTypeSourceEffect extends ContinuousEffectImpl {
}
article = true;
}
- sb.append(cardType.toString().toLowerCase()).append(" ");
+ sb.append(cardType.toString().toLowerCase(Locale.ENGLISH)).append(" ");
}
sb.append(" in addition to its other types ").append(this.getDuration().toString());
return sb.toString();
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeTargetEffect.java
index 24fd3a05d4..822b264e64 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeTargetEffect.java
@@ -28,6 +28,7 @@
package mage.abilities.effects.common.continuous;
import java.util.ArrayList;
+import java.util.Locale;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.Mode;
@@ -110,7 +111,7 @@ public class AddCardTypeTargetEffect extends ContinuousEffectImpl {
}
article = true;
}
- sb.append(cardType.toString().toLowerCase()).append(" ");
+ sb.append(cardType.toString().toLowerCase(Locale.ENGLISH)).append(" ");
}
sb.append("in addition to its other types");
if (getDuration().equals(Duration.EndOfTurn)) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAllEffect.java
index ce9b5c41a4..9eb451177d 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAllEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAllEffect.java
@@ -39,6 +39,7 @@ import mage.constants.SubLayer;
import mage.filter.FilterPermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
+import mage.game.permanent.token.TokenImpl;
import mage.game.permanent.token.Token;
import java.util.HashSet;
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedEffect.java
index da2e7b4a5e..aca32daee2 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedEffect.java
@@ -40,8 +40,7 @@ import mage.game.permanent.token.Token;
public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl {
public enum LoseType {
-
- NONE, ALL, ALL_BUT_COLOR, ABILITIES, ABILITIES_SUBTYPE_AND_PT
+ NONE, ALL, ALL_BUT_COLOR, ABILITIES, ABILITIES_SUBTYPE_AND_PT, ABILITIES_AND_PT
}
protected Token token;
@@ -121,7 +120,7 @@ public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl {
permanent.getColor(game).setRed(false);
}
if (token.getColor(game).hasColor()) {
- permanent.getColor(game).setColor(token.getColor(game));
+ permanent.getColor(game).addColor(token.getColor(game));
}
}
break;
@@ -131,6 +130,7 @@ public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl {
case ALL:
case ALL_BUT_COLOR:
case ABILITIES:
+ case ABILITIES_AND_PT:
case ABILITIES_SUBTYPE_AND_PT:
permanent.removeAllAbilities(source.getSourceId(), game);
break;
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect.java
index 9b62e1e933..9d65371d2c 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect.java
@@ -33,6 +33,7 @@ import mage.abilities.effects.ContinuousEffectImpl;
import mage.constants.*;
import mage.game.Game;
import mage.game.permanent.Permanent;
+import mage.game.permanent.token.TokenImpl;
import mage.game.permanent.token.Token;
/**
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureSourceEffect.java
index 344b38bb32..72e0ccf17c 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureSourceEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureSourceEffect.java
@@ -34,6 +34,7 @@ import mage.abilities.effects.ContinuousEffectImpl;
import mage.constants.*;
import mage.game.Game;
import mage.game.permanent.Permanent;
+import mage.game.permanent.token.TokenImpl;
import mage.game.permanent.token.Token;
/**
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTargetEffect.java
index b95e5b79e5..abbaea4720 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTargetEffect.java
@@ -33,6 +33,7 @@ import mage.abilities.effects.ContinuousEffectImpl;
import mage.constants.*;
import mage.game.Game;
import mage.game.permanent.Permanent;
+import mage.game.permanent.token.TokenImpl;
import mage.game.permanent.token.Token;
import mage.target.Target;
import mage.util.CardUtil;
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostAllEffect.java
index e16c81de1f..caac0da6e0 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostAllEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostAllEffect.java
@@ -58,11 +58,11 @@ public class BoostAllEffect extends ContinuousEffectImpl {
}
public BoostAllEffect(DynamicValue power, DynamicValue toughness, Duration duration) {
- this(power, toughness, duration, new FilterCreaturePermanent("All creatures"), false);
+ this(power, toughness, duration, new FilterCreaturePermanent("all creatures"), false);
}
public BoostAllEffect(int power, int toughness, Duration duration, boolean excludeSource) {
- this(power, toughness, duration, new FilterCreaturePermanent("All creatures"), excludeSource);
+ this(power, toughness, duration, new FilterCreaturePermanent("all creatures"), excludeSource);
}
public BoostAllEffect(int power, int toughness, Duration duration, FilterCreaturePermanent filter, boolean excludeSource) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostControlledEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostControlledEffect.java
index 7a743e6f5e..f6059d89d8 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostControlledEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostControlledEffect.java
@@ -37,6 +37,7 @@ import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.SubLayer;
+import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
@@ -54,15 +55,15 @@ public class BoostControlledEffect extends ContinuousEffectImpl {
protected boolean lockedIn = false;
public BoostControlledEffect(int power, int toughness, Duration duration) {
- this(power, toughness, duration, new FilterCreaturePermanent("creatures"), false);
+ this(power, toughness, duration, StaticFilters.FILTER_PERMANENT_CREATURES, false);
}
public BoostControlledEffect(DynamicValue power, DynamicValue toughness, Duration duration) {
- this(power, toughness, duration, new FilterCreaturePermanent("creatures"), false);
+ this(power, toughness, duration, StaticFilters.FILTER_PERMANENT_CREATURES, false);
}
public BoostControlledEffect(int power, int toughness, Duration duration, boolean excludeSource) {
- this(power, toughness, duration, new FilterCreaturePermanent("creatures"), excludeSource);
+ this(power, toughness, duration, StaticFilters.FILTER_PERMANENT_CREATURES, excludeSource);
}
public BoostControlledEffect(int power, int toughness, Duration duration, FilterCreaturePermanent filter) {
@@ -91,7 +92,7 @@ public class BoostControlledEffect extends ContinuousEffectImpl {
super(duration, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature);
this.power = power;
this.toughness = toughness;
- this.filter = filter;
+ this.filter = (filter == null ? StaticFilters.FILTER_PERMANENT_CREATURES : filter);
this.excludeSource = excludeSource;
this.lockedIn = lockedIn;
setText();
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostTargetEffect.java
index f1a6aca4dd..51e1805ec9 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostTargetEffect.java
@@ -27,13 +27,13 @@
*/
package mage.abilities.effects.common.continuous;
+import java.util.Locale;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.ContinuousEffectImpl;
-import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
@@ -126,7 +126,7 @@ public class BoostTargetEffect extends ContinuousEffectImpl {
}
sb.append(CardUtil.numberToText(target.getMaxNumberOfTargets())).append(" target ").append(target.getTargetName()).append(" get ");
} else {
- if (!target.getTargetName().toUpperCase().startsWith("ANOTHER")) {
+ if (!target.getTargetName().toUpperCase(Locale.ENGLISH).startsWith("ANOTHER")) {
sb.append("target ");
}
sb.append(target.getTargetName()).append(" gets ");
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/CommanderReplacementEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/CommanderReplacementEffect.java
index adeb100ccd..879357d990 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/continuous/CommanderReplacementEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/CommanderReplacementEffect.java
@@ -143,7 +143,7 @@ public class CommanderReplacementEffect extends ReplacementEffectImpl {
if (player != null && player.chooseUse(Outcome.Benefit, "Move commander to command zone?", source, game)) {
((ZoneChangeEvent) event).setToZone(Zone.COMMAND);
if (!game.isSimulation()) {
- game.informPlayers(player.getLogName() + " has moved his or her commander to the command zone");
+ game.informPlayers(player.getLogName() + " has moved their commander to the command zone");
}
}
}
@@ -163,7 +163,7 @@ public class CommanderReplacementEffect extends ReplacementEffectImpl {
if (player != null && player.chooseUse(Outcome.Benefit, "Move commander to command zone?", source, game)) {
((ZoneChangeEvent) event).setToZone(Zone.COMMAND);
if (!game.isSimulation()) {
- game.informPlayers(player.getLogName() + " has moved his or her commander to the command zone");
+ game.informPlayers(player.getLogName() + " has moved their commander to the command zone");
}
}
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityAllEffect.java
index 962a782ead..0211176f39 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityAllEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityAllEffect.java
@@ -29,6 +29,7 @@ package mage.abilities.effects.common.continuous;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.Locale;
import java.util.UUID;
import mage.MageObject;
import mage.MageObjectReference;
@@ -37,6 +38,7 @@ import mage.abilities.Mode;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.effects.ContinuousEffectImpl;
+import mage.constants.DependencyType;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
@@ -79,6 +81,7 @@ public class GainAbilityAllEffect extends ContinuousEffectImpl {
this.ability.newId();
this.filter = filter;
this.excludeSource = excludeSource;
+ this.addDependencyType(DependencyType.AddingAbility);
}
public GainAbilityAllEffect(final GainAbilityAllEffect effect) {
@@ -180,12 +183,12 @@ public class GainAbilityAllEffect extends ContinuousEffectImpl {
}
sb.append(filter.getMessage());
if (duration == Duration.WhileOnBattlefield) {
- if (filter.getMessage().toLowerCase().startsWith("each")) {
+ if (filter.getMessage().toLowerCase(Locale.ENGLISH).startsWith("each")) {
sb.append(" has ");
} else {
sb.append(" have ");
}
- } else if (filter.getMessage().toLowerCase().startsWith("each")) {
+ } else if (filter.getMessage().toLowerCase(Locale.ENGLISH).startsWith("each")) {
sb.append(" gains ");
} else {
sb.append(" gain ");
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityAttachedEffect.java
index 543c49bab4..40c9572615 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityAttachedEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityAttachedEffect.java
@@ -30,6 +30,7 @@ package mage.abilities.effects.common.continuous;
import mage.abilities.Ability;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.constants.AttachmentType;
+import mage.constants.DependencyType;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
@@ -75,6 +76,7 @@ public class GainAbilityAttachedEffect extends ContinuousEffectImpl {
} else {
this.staticText = rule;
}
+ this.addDependencyType(DependencyType.AddingAbility);
}
public GainAbilityAttachedEffect(final GainAbilityAttachedEffect effect) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityControlledEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityControlledEffect.java
index 9018031b65..8812f967b1 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityControlledEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityControlledEffect.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,12 +20,11 @@
* 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.abilities.effects.common.continuous;
import java.util.HashMap;
@@ -36,6 +35,7 @@ import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.CompoundAbility;
import mage.abilities.effects.ContinuousEffectImpl;
+import mage.constants.DependencyType;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
@@ -79,6 +79,7 @@ public class GainAbilityControlledEffect extends ContinuousEffectImpl {
this.ability = ability;
this.filter = filter;
this.excludeSource = excludeSource;
+ this.addDependencyType(DependencyType.AddingAbility);
setText();
}
@@ -87,6 +88,7 @@ public class GainAbilityControlledEffect extends ContinuousEffectImpl {
this.ability = effect.ability.copy();
this.filter = effect.filter.copy();
this.excludeSource = effect.excludeSource;
+
}
@Override
@@ -113,7 +115,7 @@ public class GainAbilityControlledEffect extends ContinuousEffectImpl {
Permanent perm = it.next().getPermanentOrLKIBattlefield(game); //LKI is neccessary for "dies triggered abilities" to work given to permanets (e.g. Showstopper)
if (perm != null) {
for (Ability abilityToAdd : ability) {
- perm.addAbility(abilityToAdd, source.getSourceId(), game, false);
+ perm.addAbility(abilityToAdd, source.getSourceId(), game, false);
}
} else {
it.remove();
@@ -133,7 +135,7 @@ public class GainAbilityControlledEffect extends ContinuousEffectImpl {
// still as long as the prev. permanent is known to the LKI (e.g. Mikaeus, the Unhallowed) so gained dies triggered ability will trigger
HashMap LKIBattlefield = game.getLKI().get(Zone.BATTLEFIELD);
if (LKIBattlefield != null) {
- for (MageObject mageObject: LKIBattlefield.values()) {
+ for (MageObject mageObject : LKIBattlefield.values()) {
Permanent perm = (Permanent) mageObject;
if (!(excludeSource && perm.getId().equals(source.getSourceId()))) {
if (filter.match(perm, source.getSourceId(), source.getControllerId(), game)) {
@@ -168,13 +170,12 @@ public class GainAbilityControlledEffect extends ContinuousEffectImpl {
if (gainedAbility.startsWith("Whenever ") || gainedAbility.startsWith("{T}")) {
gainedAbility = '"' + gainedAbility + '"';
}
- }
- else {
+ } else {
sb.append("gain ");
}
sb.append(gainedAbility);
if (!duration.toString().isEmpty() && duration != Duration.EndOfGame) {
- sb.append(' ').append(duration.toString());
+ sb.append(' ').append(duration.toString());
}
staticText = sb.toString();
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilitySourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilitySourceEffect.java
index 3b4b491b5e..0583582141 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilitySourceEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilitySourceEffect.java
@@ -31,6 +31,7 @@ import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.cards.Card;
+import mage.constants.DependencyType;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
@@ -75,6 +76,7 @@ public class GainAbilitySourceEffect extends ContinuousEffectImpl implements Sou
if (noStaticText) {
staticText = null;
}
+ this.addDependencyType(DependencyType.AddingAbility);
}
public GainAbilitySourceEffect(final GainAbilitySourceEffect effect) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityTargetEffect.java
index 91f1d4af73..dcf23d4d1c 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityTargetEffect.java
@@ -33,6 +33,7 @@ import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.cards.Card;
+import mage.constants.DependencyType;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
@@ -75,6 +76,7 @@ public class GainAbilityTargetEffect extends ContinuousEffectImpl {
this.ability = ability;
staticText = rule;
this.onCard = onCard;
+ this.addDependencyType(DependencyType.AddingAbility);
}
public GainAbilityTargetEffect(final GainAbilityTargetEffect effect) {
@@ -170,7 +172,7 @@ public class GainAbilityTargetEffect extends ContinuousEffectImpl {
}
sb.append(target.getMaxNumberOfTargets()).append(" target ").append(target.getTargetName()).append(" gain ");
} else {
- if (!target.getTargetName().toUpperCase().startsWith("ANOTHER")) {
+ if (!target.getTargetName().toUpperCase(Locale.ENGLISH).startsWith("ANOTHER")) {
sb.append("target ");
}
sb.append(target.getTargetName()).append(" gains ");
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/PlayAdditionalLandsAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/PlayAdditionalLandsAllEffect.java
index a66f6245b6..e3dc924b3c 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/continuous/PlayAdditionalLandsAllEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/PlayAdditionalLandsAllEffect.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.effects.common.continuous;
import mage.abilities.Ability;
@@ -38,19 +37,34 @@ import mage.game.Game;
import mage.players.Player;
/**
- * Each player may play an additional land on each of his or her turns.
+ * Each player may play an additional land on each of their turns.
*
* @author nantuko
*/
public class PlayAdditionalLandsAllEffect extends ContinuousEffectImpl {
+ private int numExtraLands = 1;
+
public PlayAdditionalLandsAllEffect() {
super(Duration.WhileOnBattlefield, Layer.PlayerEffects, SubLayer.NA, Outcome.Benefit);
- staticText = "Each player may play an additional land on each of his or her turns";
+ staticText = "Each player may play an additional land on each of their turns";
+ numExtraLands = 1;
+ }
+
+ public PlayAdditionalLandsAllEffect(int numExtraLands) {
+ super(Duration.WhileOnBattlefield, Layer.PlayerEffects, SubLayer.NA, Outcome.Benefit);
+ this.numExtraLands = numExtraLands;
+ if (numExtraLands == Integer.MAX_VALUE) {
+ staticText = "Each player may play any number of additional lands on each of their turns";
+ } else {
+ staticText = "Each player may play an additional " + numExtraLands + " lands on each of their turns";
+ }
}
public PlayAdditionalLandsAllEffect(final PlayAdditionalLandsAllEffect effect) {
super(effect);
+ this.numExtraLands = effect.numExtraLands;
+ this.staticText = effect.staticText;
}
@Override
@@ -62,10 +76,13 @@ public class PlayAdditionalLandsAllEffect extends ContinuousEffectImpl {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(game.getActivePlayerId());
if (player != null) {
- player.setLandsPerTurn(player.getLandsPerTurn() + 1);
+ if (numExtraLands == Integer.MAX_VALUE) {
+ player.setLandsPerTurn(Integer.MAX_VALUE);
+ } else {
+ player.setLandsPerTurn(player.getLandsPerTurn() + numExtraLands);
+ }
return true;
}
return true;
}
-
-}
\ No newline at end of file
+}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/WUBRGInsteadEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/WUBRGInsteadEffect.java
new file mode 100644
index 0000000000..cd853bc24e
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/WUBRGInsteadEffect.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.abilities.effects.common.continuous;
+
+import mage.abilities.Ability;
+import mage.abilities.condition.common.SourceIsSpellCondition;
+import mage.abilities.costs.AlternativeCostSourceAbility;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.ContinuousEffectImpl;
+import mage.constants.Duration;
+import mage.constants.Layer;
+import mage.constants.Outcome;
+import mage.constants.SubLayer;
+import mage.game.Game;
+import mage.players.Player;
+
+/**
+ * @author JRHerlehy
+ * Created on 4/4/18.
+ */
+public class WUBRGInsteadEffect extends ContinuousEffectImpl {
+
+ static AlternativeCostSourceAbility alternativeCastingCostAbility = new AlternativeCostSourceAbility(new ManaCostsImpl("{W}{U}{B}{R}{G}"), SourceIsSpellCondition.instance);
+
+ public WUBRGInsteadEffect() {
+ super(Duration.WhileOnBattlefield, Outcome.Detriment);
+ staticText = "You may pay {W}{U}{B}{R}{G} rather than pay the mana cost for spells that you cast";
+ }
+
+ public WUBRGInsteadEffect(final WUBRGInsteadEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public WUBRGInsteadEffect copy() {
+ return new WUBRGInsteadEffect(this);
+ }
+
+ @Override
+ public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
+ Player controller = game.getPlayer(source.getControllerId());
+ if (controller != null) {
+ controller.getAlternativeSourceCosts().add(alternativeCastingCostAbility);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ return false;
+ }
+
+ @Override
+ public boolean hasLayer(Layer layer) {
+ return layer == Layer.RulesEffects;
+ }
+
+}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersAllEffect.java
index b896c2b950..0acebdda8a 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersAllEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersAllEffect.java
@@ -27,6 +27,7 @@
*/
package mage.abilities.effects.common.counter;
+import java.util.Locale;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
@@ -69,7 +70,7 @@ public class AddCountersAllEffect extends OneShotEffect {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
permanent.addCounters(counter.copy(), source, game);
if (!game.isSimulation()) {
- game.informPlayers(sourceObject.getLogName() + ": " + controller.getLogName() + " puts " + counter.getCount() + ' ' + counter.getName().toLowerCase()
+ game.informPlayers(sourceObject.getLogName() + ": " + controller.getLogName() + " puts " + counter.getCount() + ' ' + counter.getName().toLowerCase(Locale.ENGLISH)
+ " counter on " + permanent.getLogName());
}
}
@@ -83,9 +84,9 @@ public class AddCountersAllEffect extends OneShotEffect {
StringBuilder sb = new StringBuilder();
sb.append("put ");
if (counter.getCount() > 1) {
- sb.append(CardUtil.numberToText(counter.getCount(), "a")).append(' ').append(counter.getName().toLowerCase()).append(" counters on each ");
+ sb.append(CardUtil.numberToText(counter.getCount(), "a")).append(' ').append(counter.getName().toLowerCase(Locale.ENGLISH)).append(" counters on each ");
} else {
- sb.append("a ").append(counter.getName().toLowerCase()).append(" counter on each ");
+ sb.append("a ").append(counter.getName().toLowerCase(Locale.ENGLISH)).append(" counter on each ");
}
sb.append(filter.getMessage());
staticText = sb.toString();
diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersAttachedEffect.java
index 2824f7f5e7..ddf90f5bde 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersAttachedEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersAttachedEffect.java
@@ -27,6 +27,7 @@
*/
package mage.abilities.effects.common.counter;
+import java.util.Locale;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.StaticValue;
@@ -41,7 +42,6 @@ import mage.util.CardUtil;
*
* @author LevelX2
*/
-
public class AddCountersAttachedEffect extends OneShotEffect {
private Counter counter;
@@ -99,7 +99,7 @@ public class AddCountersAttachedEffect extends OneShotEffect {
} else {
sb.append("a ");
}
- sb.append(counter.getName().toLowerCase()).append(" counter on ");
+ sb.append(counter.getName().toLowerCase(Locale.ENGLISH)).append(" counter on ");
sb.append(textEnchanted);
if (!amount.getMessage().isEmpty()) {
sb.append(" for each ").append(amount.getMessage());
diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersSourceEffect.java
index 9376340acf..6d5062415a 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersSourceEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersSourceEffect.java
@@ -28,6 +28,7 @@
package mage.abilities.effects.common.counter;
import java.util.ArrayList;
+import java.util.Locale;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue;
@@ -110,7 +111,7 @@ public class AddCountersSourceEffect extends OneShotEffect {
if (informPlayers && !game.isSimulation()) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
- game.informPlayers(player.getLogName() + " puts " + newCounter.getCount() + ' ' + newCounter.getName().toLowerCase() + " counter on " + card.getLogName());
+ game.informPlayers(player.getLogName() + " puts " + newCounter.getCount() + ' ' + newCounter.getName().toLowerCase(Locale.ENGLISH) + " counter on " + card.getLogName());
}
}
}
@@ -137,7 +138,7 @@ public class AddCountersSourceEffect extends OneShotEffect {
int amountAdded = permanent.getCounters(game).getCount(newCounter.getName()) - before;
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
- game.informPlayers(player.getLogName() + " puts " + amountAdded + ' ' + newCounter.getName().toLowerCase() + " counter on " + permanent.getLogName());
+ game.informPlayers(player.getLogName() + " puts " + amountAdded + ' ' + newCounter.getName().toLowerCase(Locale.ENGLISH) + " counter on " + permanent.getLogName());
}
}
}
@@ -161,7 +162,7 @@ public class AddCountersSourceEffect extends OneShotEffect {
sb.append("a ");
plural = false;
}
- sb.append(counter.getName().toLowerCase()).append(" counter");
+ sb.append(counter.getName().toLowerCase(Locale.ENGLISH)).append(" counter");
if (plural) {
sb.append('s');
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersTargetEffect.java
index f61e9d73a0..14389b03c3 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersTargetEffect.java
@@ -27,6 +27,7 @@
*/
package mage.abilities.effects.common.counter;
+import java.util.Locale;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
@@ -102,7 +103,7 @@ public class AddCountersTargetEffect extends OneShotEffect {
affectedTargets++;
if (!game.isSimulation()) {
game.informPlayers(sourceObject.getLogName() + ": " + controller.getLogName() + " puts "
- + numberAdded + ' ' + counter.getName().toLowerCase() + " counter on " + permanent.getLogName());
+ + numberAdded + ' ' + counter.getName().toLowerCase(Locale.ENGLISH) + " counter on " + permanent.getLogName());
}
} else if (player != null) {
Counter newCounter = counter.copy();
@@ -111,7 +112,7 @@ public class AddCountersTargetEffect extends OneShotEffect {
affectedTargets++;
if (!game.isSimulation()) {
game.informPlayers(sourceObject.getLogName() + ": " + controller.getLogName() + " puts "
- + counter.getCount() + ' ' + counter.getName().toLowerCase() + " counter on " + player.getLogName());
+ + counter.getCount() + ' ' + counter.getName().toLowerCase(Locale.ENGLISH) + " counter on " + player.getLogName());
}
} else if (card != null) {
card.addCounters(counter, source, game);
@@ -140,7 +141,7 @@ public class AddCountersTargetEffect extends OneShotEffect {
} else {
sb.append("a ");
}
- sb.append(counter.getName().toLowerCase()).append(" counter");
+ sb.append(counter.getName().toLowerCase(Locale.ENGLISH)).append(" counter");
if (counter.getCount() > 1) {
sb.append('s');
}
@@ -153,7 +154,8 @@ public class AddCountersTargetEffect extends OneShotEffect {
}
if (target.getMaxNumberOfTargets() > 1 || target.getNumberOfTargets() == 0) {
- sb.append(target.getMaxNumberOfTargets()).append(" target ").append(target.getTargetName());
+ sb.append(CardUtil.numberToText(target.getMaxNumberOfTargets()))
+ .append(" target ").append(target.getTargetName());
} else {
if (!target.getTargetName().startsWith("another")) {
sb.append("target ");
diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/AddRemoveAllTimeSuspentCountersEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/AddRemoveAllTimeSuspentCountersEffect.java
index 0e59f9641e..7fd5815722 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/counter/AddRemoveAllTimeSuspentCountersEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/counter/AddRemoveAllTimeSuspentCountersEffect.java
@@ -29,6 +29,7 @@ package mage.abilities.effects.common.counter;
import java.util.ArrayList;
import java.util.List;
+import java.util.Locale;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
@@ -98,7 +99,7 @@ public class AddRemoveAllTimeSuspentCountersEffect extends OneShotEffect {
if (!game.isSimulation()) {
game.informPlayers(new StringBuilder(sourceObject.getName()).append(": ")
.append(controller.getLogName()).append(actionStr)
- .append(counter.getCount()).append(' ').append(counterName.toLowerCase())
+ .append(counter.getCount()).append(' ').append(counterName.toLowerCase(Locale.ENGLISH))
.append(" counter on ").append(card.getName()).toString());
}
}
@@ -110,9 +111,9 @@ public class AddRemoveAllTimeSuspentCountersEffect extends OneShotEffect {
final String actionsStr2 = removeCounter ? "remove " : " put ";
sb.append(actionsStr2);
if (counter.getCount() > 1) {
- sb.append(Integer.toString(counter.getCount())).append(' ').append(counter.getName().toLowerCase()).append(" counters on each ");
+ sb.append(Integer.toString(counter.getCount())).append(' ').append(counter.getName().toLowerCase(Locale.ENGLISH)).append(" counters on each ");
} else {
- sb.append("a ").append(counter.getName().toLowerCase()).append(" counter on each ");
+ sb.append("a ").append(counter.getName().toLowerCase(Locale.ENGLISH)).append(" counter on each ");
}
sb.append(filter.getMessage());
staticText = sb.toString();
diff --git a/Mage/src/main/java/mage/abilities/effects/common/discard/DiscardCardYouChooseTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/discard/DiscardCardYouChooseTargetEffect.java
index b527f9073f..7b2d7a7c02 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/discard/DiscardCardYouChooseTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/discard/DiscardCardYouChooseTargetEffect.java
@@ -194,14 +194,14 @@ public class DiscardCardYouChooseTargetEffect extends OneShotEffect {
throw new UnsupportedOperationException("target controller not supported");
}
if (revealAllCards) {
- sb.append(" reveals his or her hand");
+ sb.append(" reveals their hand");
} else {
if (numberCardsToReveal instanceof StaticValue) {
sb.append(" reveals ");
sb.append(numberCardsToReveal.getMessage());
- sb.append(" from his or her hand");
+ sb.append(" from their hand");
} else {
- sb.append(" reveals a number of cards from his or her hand equal to ");
+ sb.append(" reveals a number of cards from their hand equal to ");
sb.append(numberCardsToReveal.getMessage());
}
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/discard/DiscardHandAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/discard/DiscardHandAllEffect.java
index fca8199637..c190dde1a3 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/discard/DiscardHandAllEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/discard/DiscardHandAllEffect.java
@@ -43,7 +43,7 @@ public class DiscardHandAllEffect extends OneShotEffect {
public DiscardHandAllEffect() {
super(Outcome.Discard);
- this.staticText = "Each player discards his or her hand";
+ this.staticText = "Each player discards their hand";
}
public DiscardHandAllEffect(final DiscardHandAllEffect effect) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/discard/DiscardHandTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/discard/DiscardHandTargetEffect.java
index 22bee765e9..ee91492abb 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/discard/DiscardHandTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/discard/DiscardHandTargetEffect.java
@@ -89,7 +89,7 @@ public class DiscardHandTargetEffect extends OneShotEffect {
} else {
sb.append("target ").append(mode.getTargets().get(0).getTargetName());
}
- sb.append(" discards his or her hand");
+ sb.append(" discards their hand");
return sb.toString();
}
}
\ No newline at end of file
diff --git a/Mage/src/main/java/mage/abilities/effects/common/replacement/DealtDamageToCreatureBySourceDies.java b/Mage/src/main/java/mage/abilities/effects/common/replacement/DealtDamageToCreatureBySourceDies.java
index 6dbd12b997..145e2432da 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/replacement/DealtDamageToCreatureBySourceDies.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/replacement/DealtDamageToCreatureBySourceDies.java
@@ -30,7 +30,6 @@ package mage.abilities.effects.common.replacement;
import mage.abilities.Ability;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.cards.Card;
-import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
diff --git a/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutInPlayTargetPlayerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutInPlayTargetPlayerEffect.java
index 0d3c6776b0..507223d1f6 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutInPlayTargetPlayerEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutInPlayTargetPlayerEffect.java
@@ -89,7 +89,7 @@ public class SearchLibraryPutInPlayTargetPlayerEffect extends SearchEffect {
private void setText() {
StringBuilder sb = new StringBuilder();
- sb.append("target player searches his or her library for ");
+ sb.append("target player searches their library for ");
if (target.getNumberOfTargets() == 0 && target.getMaxNumberOfTargets() > 0) {
if (target.getMaxNumberOfTargets() == Integer.MAX_VALUE) {
sb.append("any number of ").append(' ');
@@ -104,9 +104,9 @@ public class SearchLibraryPutInPlayTargetPlayerEffect extends SearchEffect {
sb.append(" tapped");
}
if (forceShuffle) {
- sb.append(". Then that player shuffles his or her library");
+ sb.append(". Then that player shuffles their library");
} else {
- sb.append(". If that player does, he or she shuffles his or her library");
+ sb.append(". If that player does, he or she shuffles their library");
}
staticText = sb.toString();
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/search/SearchTargetGraveyardHandLibraryForCardNameAndExileEffect.java b/Mage/src/main/java/mage/abilities/effects/common/search/SearchTargetGraveyardHandLibraryForCardNameAndExileEffect.java
index 5be2bb16f2..3b478fa9a0 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/search/SearchTargetGraveyardHandLibraryForCardNameAndExileEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/search/SearchTargetGraveyardHandLibraryForCardNameAndExileEffect.java
@@ -132,7 +132,7 @@ public abstract class SearchTargetGraveyardHandLibraryForCardNameAndExileEffect
sb.append("search ").append(this.searchWhatText);
sb.append(" graveyard, hand, and library for ");
sb.append(this.searchForText);
- sb.append(" and exile them. Then that player shuffles his or her library");
+ sb.append(" and exile them. Then that player shuffles their library");
return sb.toString();
}
}
diff --git a/Mage/src/main/java/mage/abilities/effects/keyword/ManifestEffect.java b/Mage/src/main/java/mage/abilities/effects/keyword/ManifestEffect.java
index 21ac9b9875..056be1d72e 100644
--- a/Mage/src/main/java/mage/abilities/effects/keyword/ManifestEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/keyword/ManifestEffect.java
@@ -36,7 +36,6 @@ import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BecomesFaceDownCreatureEffect;
import mage.abilities.effects.common.continuous.BecomesFaceDownCreatureEffect.FaceDownType;
import mage.cards.Card;
-import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
diff --git a/Mage/src/main/java/mage/abilities/effects/keyword/ManifestTargetPlayerEffect.java b/Mage/src/main/java/mage/abilities/effects/keyword/ManifestTargetPlayerEffect.java
index 225a530f54..a1cb93bd9a 100644
--- a/Mage/src/main/java/mage/abilities/effects/keyword/ManifestTargetPlayerEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/keyword/ManifestTargetPlayerEffect.java
@@ -36,7 +36,6 @@ import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BecomesFaceDownCreatureEffect;
import mage.abilities.effects.common.continuous.BecomesFaceDownCreatureEffect.FaceDownType;
import mage.cards.Card;
-import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
@@ -113,11 +112,11 @@ public class ManifestTargetPlayerEffect extends OneShotEffect {
} else {
sb.append("card ");
}
- sb.append("of his or her library. ");
+ sb.append("of their library. ");
if (amount > 1) {
sb.append("(To manifest a card, put it onto the battlefield face down as a 2/2 creature. The controller may turn it face up at any time for its mana cost if it's a creature card.)");
} else {
- sb.append("(That player puts the top card of his or her library onto the battlefield face down as a 2/2 creature. If it's a creature card, it can be turned face up any time for its mana cost.)");
+ sb.append("(That player puts the top card of their library onto the battlefield face down as a 2/2 creature. If it's a creature card, it can be turned face up any time for its mana cost.)");
}
return sb.toString();
}
diff --git a/Mage/src/main/java/mage/abilities/effects/keyword/SupportEffect.java b/Mage/src/main/java/mage/abilities/effects/keyword/SupportEffect.java
index 32a979618b..8e4d35b21d 100644
--- a/Mage/src/main/java/mage/abilities/effects/keyword/SupportEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/keyword/SupportEffect.java
@@ -31,7 +31,6 @@ import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.cards.Card;
-import mage.constants.CardType;
import mage.counters.CounterType;
import mage.filter.common.FilterCreaturePermanent;
import mage.target.common.TargetCreaturePermanent;
diff --git a/Mage/src/main/java/mage/abilities/effects/keyword/SweepEffect.java b/Mage/src/main/java/mage/abilities/effects/keyword/SweepEffect.java
index ba0f02e42b..b70c589567 100644
--- a/Mage/src/main/java/mage/abilities/effects/keyword/SweepEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/keyword/SweepEffect.java
@@ -70,7 +70,7 @@ public class SweepEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
- FilterPermanent filter = new FilterControlledLandPermanent(new StringBuilder("any number of ").append(sweepSubtype).append("s you control").toString());
+ FilterPermanent filter = new FilterControlledLandPermanent("any number of " + sweepSubtype + "s you control");
filter.add(new SubtypePredicate(sweepSubtype));
Target target = new TargetPermanent(0, Integer.MAX_VALUE, filter, true);
if (controller.chooseTarget(outcome, target, source, game)) {
diff --git a/Mage/src/main/java/mage/abilities/keyword/AnnihilatorAbility.java b/Mage/src/main/java/mage/abilities/keyword/AnnihilatorAbility.java
index a16a527a63..69b360804d 100644
--- a/Mage/src/main/java/mage/abilities/keyword/AnnihilatorAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/AnnihilatorAbility.java
@@ -32,7 +32,6 @@ import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.constants.Zone;
-import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledPermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
diff --git a/Mage/src/main/java/mage/abilities/keyword/AwakenAbility.java b/Mage/src/main/java/mage/abilities/keyword/AwakenAbility.java
index 71bd01757f..cc7fae9726 100644
--- a/Mage/src/main/java/mage/abilities/keyword/AwakenAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/AwakenAbility.java
@@ -48,6 +48,7 @@ import mage.constants.Zone;
import mage.counters.CounterType;
import mage.filter.common.FilterControlledLandPermanent;
import mage.game.Game;
+import mage.game.permanent.token.TokenImpl;
import mage.game.permanent.token.Token;
import mage.target.Target;
import mage.target.common.TargetControlledPermanent;
@@ -158,7 +159,7 @@ public class AwakenAbility extends SpellAbility {
}
-class AwakenElementalToken extends Token {
+class AwakenElementalToken extends TokenImpl {
public AwakenElementalToken() {
super("", "0/0 Elemental creature with haste");
@@ -170,4 +171,12 @@ class AwakenElementalToken extends Token {
this.addAbility(HasteAbility.getInstance());
}
+
+ public AwakenElementalToken(final AwakenElementalToken token) {
+ super(token);
+ }
+
+ public AwakenElementalToken copy() {
+ return new AwakenElementalToken(this);
+ }
}
diff --git a/Mage/src/main/java/mage/abilities/keyword/ConvokeAbility.java b/Mage/src/main/java/mage/abilities/keyword/ConvokeAbility.java
index 70f7f53400..2f0b744d3a 100644
--- a/Mage/src/main/java/mage/abilities/keyword/ConvokeAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/ConvokeAbility.java
@@ -29,6 +29,7 @@ package mage.abilities.keyword;
import java.util.ArrayList;
import java.util.List;
+import java.util.Locale;
import java.util.UUID;
import mage.Mana;
import mage.ObjectColor;
@@ -242,7 +243,7 @@ class ConvokeEffect extends OneShotEffect {
manaPool.addMana(Mana.ColorlessMana(1), game, source);
manaPool.unlockManaType(ManaType.COLORLESS);
}
- manaName = chooseManaType.getChoice().toLowerCase();
+ manaName = chooseManaType.getChoice().toLowerCase(Locale.ENGLISH);
} else {
manaPool.addMana(Mana.ColorlessMana(1), game, source);
manaPool.unlockManaType(ManaType.COLORLESS);
diff --git a/Mage/src/main/java/mage/abilities/keyword/EchoAbility.java b/Mage/src/main/java/mage/abilities/keyword/EchoAbility.java
index e978cb9dc0..d7230c9b1e 100644
--- a/Mage/src/main/java/mage/abilities/keyword/EchoAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/EchoAbility.java
@@ -27,6 +27,7 @@
*/
package mage.abilities.keyword;
+import java.util.Locale;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.Mode;
@@ -209,8 +210,8 @@ class EchoEffect extends OneShotEffect {
public String getText(Mode mode) {
StringBuilder sb = new StringBuilder("sacrifice {this} unless you ");
String costText = cost.getText();
- if (costText.toLowerCase().startsWith("discard")) {
- sb.append(costText.substring(0, 1).toLowerCase());
+ if (costText.toLowerCase(Locale.ENGLISH).startsWith("discard")) {
+ sb.append(costText.substring(0, 1).toLowerCase(Locale.ENGLISH));
sb.append(costText.substring(1));
} else {
sb.append("pay ").append(costText);
diff --git a/Mage/src/main/java/mage/abilities/keyword/EquipLegendaryAbility.java b/Mage/src/main/java/mage/abilities/keyword/EquipLegendaryAbility.java
new file mode 100644
index 0000000000..585a357713
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/keyword/EquipLegendaryAbility.java
@@ -0,0 +1,96 @@
+/*
+ * 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.abilities.keyword;
+
+import mage.abilities.ActivatedAbilityImpl;
+import mage.abilities.costs.Cost;
+import mage.abilities.effects.common.AttachEffect;
+import mage.constants.Outcome;
+import mage.constants.SubType;
+import mage.constants.TimingRule;
+import mage.constants.Zone;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.target.Target;
+import mage.target.common.TargetControlledCreaturePermanent;
+
+import java.util.UUID;
+import mage.constants.SuperType;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterControlledCreaturePermanent;
+import mage.filter.predicate.mageobject.SupertypePredicate;
+
+/**
+ * @author Rystan
+ */
+public class EquipLegendaryAbility extends ActivatedAbilityImpl {
+
+ private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("legendary creature you control");
+
+ static {
+ filter.add(new SupertypePredicate(SuperType.LEGENDARY));
+ }
+
+ public EquipLegendaryAbility(Outcome outcome, Cost cost) {
+ this(outcome, cost, new TargetControlledCreaturePermanent(filter));
+ }
+
+ public EquipLegendaryAbility(Outcome outcome, Cost cost, Target target) {
+ super(Zone.BATTLEFIELD, new AttachEffect(outcome, "Equip"), cost);
+ this.addTarget(target);
+ this.timing = TimingRule.SORCERY;
+ }
+
+ @Override
+ public boolean canActivate(UUID playerId, Game game) {
+ if (super.canActivate(playerId, game)) {
+ Permanent permanent = game.getPermanent(sourceId);
+ if (permanent != null && permanent.hasSubtype(SubType.EQUIPMENT, game)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public EquipLegendaryAbility(final EquipLegendaryAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public EquipLegendaryAbility copy() {
+ return new EquipLegendaryAbility(this);
+ }
+
+ @Override
+ public String getRule() {
+ return "Equip legendary creature " + costs.getText() +
+ manaCosts.getText() + " (" + manaCosts.getText() +
+ ": Attach to target legendary creature you control. Equip only as a sorcery.)";
+ }
+
+}
diff --git a/Mage/src/main/java/mage/abilities/keyword/EvolveAbility.java b/Mage/src/main/java/mage/abilities/keyword/EvolveAbility.java
index 3dc4faac65..483424869b 100644
--- a/Mage/src/main/java/mage/abilities/keyword/EvolveAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/EvolveAbility.java
@@ -30,7 +30,6 @@ package mage.abilities.keyword;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.OneShotEffect;
-import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.counters.CounterType;
diff --git a/Mage/src/main/java/mage/abilities/keyword/ExertAbility.java b/Mage/src/main/java/mage/abilities/keyword/ExertAbility.java
index 690ea53e14..9a5432df92 100644
--- a/Mage/src/main/java/mage/abilities/keyword/ExertAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/ExertAbility.java
@@ -1,206 +1,205 @@
-/*
- * 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.abilities.keyword;
-
-import java.util.HashSet;
-import java.util.Set;
-import mage.MageObjectReference;
-import mage.abilities.Ability;
-import mage.abilities.Mode;
-import mage.abilities.common.BecomesExertSourceTriggeredAbility;
-import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.ContinuousEffect;
-import mage.abilities.effects.Effect;
-import mage.abilities.effects.ReplacementEffectImpl;
-import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect;
-import mage.constants.Duration;
-import mage.constants.Outcome;
-import mage.constants.WatcherScope;
-import mage.constants.Zone;
-import mage.game.Game;
-import mage.game.events.GameEvent;
-import mage.game.events.GameEvent.EventType;
-import mage.game.permanent.Permanent;
-import mage.players.Player;
-import mage.target.targetpointer.FixedTarget;
-import mage.watchers.Watcher;
-
-/**
- *
- * @author LevelX2
- */
-public class ExertAbility extends SimpleStaticAbility {
-
- private String ruleText;
-
- public ExertAbility(BecomesExertSourceTriggeredAbility ability) {
- this(ability, false);
- }
-
- public ExertAbility(BecomesExertSourceTriggeredAbility ability, boolean exertOnlyOncePerTurn) {
- super(Zone.BATTLEFIELD, new ExertReplacementEffect(exertOnlyOncePerTurn));
- ruleText = (exertOnlyOncePerTurn
- ? "If {this} hasn't been exerted this turn, you may exert it"
- : "You may exert {this}") + " as it attacks. ";
- if (ability != null) {
- this.addSubAbility(ability);
- ruleText += "When you do,";
- ability.getEffects().forEach(effect -> {
- ruleText += " " + effect.getText(ability.getModes().getMode());
- });
- ruleText += ". ";
- ability.setRuleVisible(false);
- }
- ruleText += "(An exerted creature won't untap during your next untap step.)";
- if (exertOnlyOncePerTurn) {
- getWatchers().add(new ExertedThisTurnWatcher());
- }
- }
-
- public ExertAbility(final ExertAbility ability) {
- super(ability);
- this.ruleText = ability.ruleText;
-
- }
-
- @Override
- public ExertAbility copy() {
- return new ExertAbility(this);
- }
-
- @Override
- public String getRule() {
- return ruleText;
- }
-}
-
-class ExertReplacementEffect extends ReplacementEffectImpl {
-
- final private boolean exertOnlyOncePerTurn;
-
- public ExertReplacementEffect(boolean exertOnlyOncePerTurn) {
- super(Duration.WhileOnBattlefield, Outcome.Detriment);
- staticText = "You may exert {this} as it attacks";
- this.exertOnlyOncePerTurn = exertOnlyOncePerTurn;
- }
-
- public ExertReplacementEffect(ExertReplacementEffect effect) {
- super(effect);
- this.exertOnlyOncePerTurn = effect.exertOnlyOncePerTurn;
- }
-
- @Override
- public boolean checksEventType(GameEvent event, Game game) {
- return event.getType() == EventType.ATTACKER_DECLARED;
- }
-
- @Override
- public boolean applies(GameEvent event, Ability source, Game game) {
- return event.getSourceId().equals(source.getSourceId());
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- return false;
- }
-
- @Override
- public boolean replaceEvent(GameEvent event, Ability source, Game game) {
- Permanent creature = game.getPermanent(event.getSourceId());
- Player controller = game.getPlayer(source.getControllerId());
- if (creature != null && controller != null) {
- if (exertOnlyOncePerTurn) {
- MageObjectReference creatureReference = new MageObjectReference(creature.getId(), creature.getZoneChangeCounter(game), game);
- ExertedThisTurnWatcher watcher = (ExertedThisTurnWatcher) game.getState().getWatchers().get(ExertedThisTurnWatcher.class.getSimpleName());
- if (watcher != null && watcher.getExertedThisTurnCreatures().contains(creatureReference)) {
- return false;
- }
- }
- if (controller.chooseUse(outcome, "Exert " + creature.getLogName() + '?',
- "An exerted creature won't untap during your next untap step.", "Yes", "No", source, game)) {
- if (!game.isSimulation()) {
- game.informPlayers(controller.getLogName() + " exerted " + creature.getName());
- }
- game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BECOMES_EXERTED, creature.getId(), creature.getId(), creature.getControllerId()));
- ContinuousEffect effect = new DontUntapInControllersNextUntapStepTargetEffect("", creature.getControllerId());
- effect.setTargetPointer(new FixedTarget(creature, game));
- game.addEffect(effect, source);
- }
- }
- return false;
- }
-
- @Override
- public String getText(Mode mode) {
- return staticText;
- }
-
- @Override
- public ExertReplacementEffect copy() {
- return new ExertReplacementEffect(this);
- }
-
-}
-
-class ExertedThisTurnWatcher extends Watcher {
-
- private final Set exertedThisTurnCreatures;
-
- public ExertedThisTurnWatcher() {
- super(ExertedThisTurnWatcher.class.getSimpleName(), WatcherScope.GAME);
- exertedThisTurnCreatures = new HashSet<>();
- }
-
- public ExertedThisTurnWatcher(final ExertedThisTurnWatcher watcher) {
- super(watcher);
- exertedThisTurnCreatures = new HashSet<>(watcher.exertedThisTurnCreatures);
- }
-
- @Override
- public Watcher copy() {
- return new ExertedThisTurnWatcher(this);
- }
-
- @Override
- public void watch(GameEvent event, Game game) {
- if (event.getType() == GameEvent.EventType.BECOMES_EXERTED) {
- this.exertedThisTurnCreatures.add(new MageObjectReference(event.getSourceId(), game));
- }
- }
-
- public Set getExertedThisTurnCreatures() {
- return this.exertedThisTurnCreatures;
- }
-
- @Override
- public void reset() {
- super.reset();
- exertedThisTurnCreatures.clear();
- }
-
-}
+/*
+ * 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.abilities.keyword;
+
+import java.util.HashSet;
+import java.util.Set;
+import mage.MageObjectReference;
+import mage.abilities.Ability;
+import mage.abilities.Mode;
+import mage.abilities.common.BecomesExertSourceTriggeredAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.ContinuousEffect;
+import mage.abilities.effects.ReplacementEffectImpl;
+import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.WatcherScope;
+import mage.constants.Zone;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.events.GameEvent.EventType;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+import mage.target.targetpointer.FixedTarget;
+import mage.watchers.Watcher;
+
+/**
+ *
+ * @author LevelX2
+ */
+public class ExertAbility extends SimpleStaticAbility {
+
+ private String ruleText;
+
+ public ExertAbility(BecomesExertSourceTriggeredAbility ability) {
+ this(ability, false);
+ }
+
+ public ExertAbility(BecomesExertSourceTriggeredAbility ability, boolean exertOnlyOncePerTurn) {
+ super(Zone.BATTLEFIELD, new ExertReplacementEffect(exertOnlyOncePerTurn));
+ ruleText = (exertOnlyOncePerTurn
+ ? "If {this} hasn't been exerted this turn, you may exert it"
+ : "You may exert {this}") + " as it attacks. ";
+ if (ability != null) {
+ this.addSubAbility(ability);
+ ruleText += "When you do,";
+ ability.getEffects().forEach(effect -> {
+ ruleText += " " + effect.getText(ability.getModes().getMode());
+ });
+ ruleText += ". ";
+ ability.setRuleVisible(false);
+ }
+ ruleText += "(An exerted creature won't untap during your next untap step.)";
+ if (exertOnlyOncePerTurn) {
+ getWatchers().add(new ExertedThisTurnWatcher());
+ }
+ }
+
+ public ExertAbility(final ExertAbility ability) {
+ super(ability);
+ this.ruleText = ability.ruleText;
+
+ }
+
+ @Override
+ public ExertAbility copy() {
+ return new ExertAbility(this);
+ }
+
+ @Override
+ public String getRule() {
+ return ruleText;
+ }
+}
+
+class ExertReplacementEffect extends ReplacementEffectImpl {
+
+ final private boolean exertOnlyOncePerTurn;
+
+ public ExertReplacementEffect(boolean exertOnlyOncePerTurn) {
+ super(Duration.WhileOnBattlefield, Outcome.Detriment);
+ staticText = "You may exert {this} as it attacks";
+ this.exertOnlyOncePerTurn = exertOnlyOncePerTurn;
+ }
+
+ public ExertReplacementEffect(ExertReplacementEffect effect) {
+ super(effect);
+ this.exertOnlyOncePerTurn = effect.exertOnlyOncePerTurn;
+ }
+
+ @Override
+ public boolean checksEventType(GameEvent event, Game game) {
+ return event.getType() == EventType.ATTACKER_DECLARED;
+ }
+
+ @Override
+ public boolean applies(GameEvent event, Ability source, Game game) {
+ return event.getSourceId().equals(source.getSourceId());
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ return false;
+ }
+
+ @Override
+ public boolean replaceEvent(GameEvent event, Ability source, Game game) {
+ Permanent creature = game.getPermanent(event.getSourceId());
+ Player controller = game.getPlayer(source.getControllerId());
+ if (creature != null && controller != null) {
+ if (exertOnlyOncePerTurn) {
+ MageObjectReference creatureReference = new MageObjectReference(creature.getId(), creature.getZoneChangeCounter(game), game);
+ ExertedThisTurnWatcher watcher = (ExertedThisTurnWatcher) game.getState().getWatchers().get(ExertedThisTurnWatcher.class.getSimpleName());
+ if (watcher != null && watcher.getExertedThisTurnCreatures().contains(creatureReference)) {
+ return false;
+ }
+ }
+ if (controller.chooseUse(outcome, "Exert " + creature.getLogName() + '?',
+ "An exerted creature won't untap during your next untap step.", "Yes", "No", source, game)) {
+ if (!game.isSimulation()) {
+ game.informPlayers(controller.getLogName() + " exerted " + creature.getName());
+ }
+ game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BECOMES_EXERTED, creature.getId(), creature.getId(), creature.getControllerId()));
+ ContinuousEffect effect = new DontUntapInControllersNextUntapStepTargetEffect("", creature.getControllerId());
+ effect.setTargetPointer(new FixedTarget(creature, game));
+ game.addEffect(effect, source);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getText(Mode mode) {
+ return staticText;
+ }
+
+ @Override
+ public ExertReplacementEffect copy() {
+ return new ExertReplacementEffect(this);
+ }
+
+}
+
+class ExertedThisTurnWatcher extends Watcher {
+
+ private final Set exertedThisTurnCreatures;
+
+ public ExertedThisTurnWatcher() {
+ super(ExertedThisTurnWatcher.class.getSimpleName(), WatcherScope.GAME);
+ exertedThisTurnCreatures = new HashSet<>();
+ }
+
+ public ExertedThisTurnWatcher(final ExertedThisTurnWatcher watcher) {
+ super(watcher);
+ exertedThisTurnCreatures = new HashSet<>(watcher.exertedThisTurnCreatures);
+ }
+
+ @Override
+ public Watcher copy() {
+ return new ExertedThisTurnWatcher(this);
+ }
+
+ @Override
+ public void watch(GameEvent event, Game game) {
+ if (event.getType() == GameEvent.EventType.BECOMES_EXERTED) {
+ this.exertedThisTurnCreatures.add(new MageObjectReference(event.getSourceId(), game));
+ }
+ }
+
+ public Set getExertedThisTurnCreatures() {
+ return this.exertedThisTurnCreatures;
+ }
+
+ @Override
+ public void reset() {
+ super.reset();
+ exertedThisTurnCreatures.clear();
+ }
+
+}
diff --git a/Mage/src/main/java/mage/abilities/keyword/ExtortAbility.java b/Mage/src/main/java/mage/abilities/keyword/ExtortAbility.java
index 4ab4ff99c5..2ab58ae2ab 100644
--- a/Mage/src/main/java/mage/abilities/keyword/ExtortAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/ExtortAbility.java
@@ -109,7 +109,7 @@ class ExtortEffect extends OneShotEffect {
loseLife += game.getPlayer(opponentId).loseLife(1, game, false);
}
if (loseLife > 0) {
- game.getPlayer(source.getControllerId()).gainLife(loseLife, game);
+ game.getPlayer(source.getControllerId()).gainLife(loseLife, game, source);
}
if (!game.isSimulation())
game.informPlayers(new StringBuilder(permanent.getName()).append(" extorted opponents ").append(loseLife).append(" life").toString());
diff --git a/Mage/src/main/java/mage/abilities/keyword/FlashbackAbility.java b/Mage/src/main/java/mage/abilities/keyword/FlashbackAbility.java
index aa457aea70..13f489dd36 100644
--- a/Mage/src/main/java/mage/abilities/keyword/FlashbackAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/FlashbackAbility.java
@@ -126,8 +126,8 @@ public class FlashbackAbility extends SpellAbility {
spellAbilityCopy.setId(this.getId());
spellAbilityCopy.getManaCosts().clear();
spellAbilityCopy.getManaCostsToPay().clear();
- spellAbilityCopy.getCosts().addAll(this.getCosts());
- spellAbilityCopy.addCost(this.getManaCosts());
+ spellAbilityCopy.getCosts().addAll(this.getCosts().copy());
+ spellAbilityCopy.addCost(this.getManaCosts().copy());
spellAbilityCopy.setSpellAbilityCastMode(this.getSpellAbilityCastMode());
spellAbilityToResolve = spellAbilityCopy;
ContinuousEffect effect = new FlashbackReplacementEffect();
diff --git a/Mage/src/main/java/mage/abilities/keyword/FlyingAbility.java b/Mage/src/main/java/mage/abilities/keyword/FlyingAbility.java
index 1e0bf34cb1..da7d4dddbd 100644
--- a/Mage/src/main/java/mage/abilities/keyword/FlyingAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/FlyingAbility.java
@@ -27,6 +27,7 @@
*/
package mage.abilities.keyword;
+import java.io.ObjectStreamException;
import mage.abilities.Ability;
import mage.abilities.EvasionAbility;
import mage.abilities.MageSingleton;
@@ -37,8 +38,6 @@ import mage.constants.SubType;
import mage.game.Game;
import mage.game.permanent.Permanent;
-import java.io.ObjectStreamException;
-
/**
*
* @author BetaSteward_at_googlemail.com
@@ -90,7 +89,8 @@ class FlyingEffect extends RestrictionEffect implements MageSingleton {
public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game) {
return blocker.getAbilities().containsKey(FlyingAbility.getInstance().getId())
|| blocker.getAbilities().containsKey(ReachAbility.getInstance().getId())
- || (game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_DRAGON, source, blocker.getControllerId(), game) && attacker.hasSubtype(SubType.DRAGON, game));
+ || (null != game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_DRAGON, source, blocker.getControllerId(), game)
+ && attacker.hasSubtype(SubType.DRAGON, game));
}
@Override
diff --git a/Mage/src/main/java/mage/abilities/keyword/ForecastAbility.java b/Mage/src/main/java/mage/abilities/keyword/ForecastAbility.java
index a23e221fff..fdbfe871ff 100644
--- a/Mage/src/main/java/mage/abilities/keyword/ForecastAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/ForecastAbility.java
@@ -43,8 +43,8 @@ import mage.game.Game;
*
* 702.56b A forecast ability may be activated only during the upkeep step of
* the card's owner and only once each turn. The controller of the forecast
- * ability reveals the card with that ability from his or her hand as the
- * ability is activated. That player plays with that card revealed in his or her
+ * ability reveals the card with that ability from their hand as the
+ * ability is activated. That player plays with that card revealed in their
* hand until it leaves the player's hand or until a step or phase that isn't an
* upkeep step begins, whichever comes first.
*
diff --git a/Mage/src/main/java/mage/abilities/keyword/HauntAbility.java b/Mage/src/main/java/mage/abilities/keyword/HauntAbility.java
index 6a6adb7839..771e368ca9 100644
--- a/Mage/src/main/java/mage/abilities/keyword/HauntAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/HauntAbility.java
@@ -35,7 +35,6 @@ import mage.abilities.common.ZoneChangeTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
-import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
diff --git a/Mage/src/main/java/mage/abilities/keyword/HexproofFromBlackAbility.java b/Mage/src/main/java/mage/abilities/keyword/HexproofFromBlackAbility.java
new file mode 100644
index 0000000000..39ed14932e
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/keyword/HexproofFromBlackAbility.java
@@ -0,0 +1,43 @@
+package mage.abilities.keyword;
+
+import java.io.ObjectStreamException;
+import mage.abilities.MageSingleton;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.constants.Zone;
+
+/**
+ * Hexproof from black (This creature or player can't be the target of black
+ * spells or abilities your opponents control.)
+ *
+ * @author igoudt
+ */
+public class HexproofFromBlackAbility extends SimpleStaticAbility implements MageSingleton {
+
+ private static final HexproofFromBlackAbility instance;
+
+ static {
+ instance = new HexproofFromBlackAbility();
+ }
+
+ private Object readResolve() throws ObjectStreamException {
+ return instance;
+ }
+
+ public static HexproofFromBlackAbility getInstance() {
+ return instance;
+ }
+
+ private HexproofFromBlackAbility() {
+ super(Zone.BATTLEFIELD, null);
+ }
+
+ @Override
+ public HexproofFromBlackAbility copy() {
+ return instance;
+ }
+
+ @Override
+ public String getRule() {
+ return "hexproof from black (This creature can't be the target of black spells or abilities your opponents control.)";
+ }
+}
diff --git a/Mage/src/main/java/mage/abilities/keyword/HexproofFromWhiteAbility.java b/Mage/src/main/java/mage/abilities/keyword/HexproofFromWhiteAbility.java
new file mode 100644
index 0000000000..fb535e1c50
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/keyword/HexproofFromWhiteAbility.java
@@ -0,0 +1,43 @@
+package mage.abilities.keyword;
+
+import java.io.ObjectStreamException;
+import mage.abilities.MageSingleton;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.constants.Zone;
+
+/**
+ * Hexproof from white (This creature or player can't be the target of white
+ * spells or abilities your opponents control.)
+ *
+ * @author igoudt
+ */
+public class HexproofFromWhiteAbility extends SimpleStaticAbility implements MageSingleton {
+
+ private static final HexproofFromWhiteAbility instance;
+
+ static {
+ instance = new HexproofFromWhiteAbility();
+ }
+
+ private Object readResolve() throws ObjectStreamException {
+ return instance;
+ }
+
+ public static HexproofFromWhiteAbility getInstance() {
+ return instance;
+ }
+
+ private HexproofFromWhiteAbility() {
+ super(Zone.BATTLEFIELD, null);
+ }
+
+ @Override
+ public HexproofFromWhiteAbility copy() {
+ return instance;
+ }
+
+ @Override
+ public String getRule() {
+ return "hexproof from white (This creature can't be the target of white spells or abilities your opponents control.)";
+ }
+}
diff --git a/Mage/src/main/java/mage/abilities/keyword/IngestAbility.java b/Mage/src/main/java/mage/abilities/keyword/IngestAbility.java
index 23a63d0428..75baf302ef 100644
--- a/Mage/src/main/java/mage/abilities/keyword/IngestAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/IngestAbility.java
@@ -31,7 +31,7 @@ public class IngestAbility extends DealsCombatDamageToAPlayerTriggeredAbility {
@Override
public String getRule() {
- return "Ingest (Whenever this creature deals combat damage to a player, that player exiles the top card of his or her library.)";
+ return "Ingest (Whenever this creature deals combat damage to a player, that player exiles the top card of their library.)";
}
@Override
@@ -44,7 +44,7 @@ class IngestEffect extends OneShotEffect {
public IngestEffect() {
super(Outcome.Exile);
- this.staticText = "that player exiles the top card of his or her library";
+ this.staticText = "that player exiles the top card of their library";
}
public IngestEffect(final IngestEffect effect) {
diff --git a/Mage/src/main/java/mage/abilities/keyword/InspiredAbility.java b/Mage/src/main/java/mage/abilities/keyword/InspiredAbility.java
index 7984d2383a..23a8b876bb 100644
--- a/Mage/src/main/java/mage/abilities/keyword/InspiredAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/InspiredAbility.java
@@ -1,4 +1,4 @@
- /*
+/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
@@ -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.keyword;
import mage.abilities.TriggeredAbilityImpl;
@@ -41,7 +40,6 @@ import mage.game.events.GameEvent.EventType;
*
* @author LevelX2
*/
-
public class InspiredAbility extends TriggeredAbilityImpl {
public InspiredAbility(Effect effect) {
@@ -73,6 +71,6 @@ public class InspiredAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return new StringBuilder("Inspired - Whenever {this} becomes untapped, ").append(super.getRule()).toString();
+ return "Inspired - Whenever {this} becomes untapped, " + super.getRule();
}
}
diff --git a/Mage/src/main/java/mage/abilities/keyword/IntimidateAbility.java b/Mage/src/main/java/mage/abilities/keyword/IntimidateAbility.java
index e510c857ea..c8dd8b4791 100644
--- a/Mage/src/main/java/mage/abilities/keyword/IntimidateAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/IntimidateAbility.java
@@ -4,7 +4,6 @@ import mage.abilities.Ability;
import mage.abilities.EvasionAbility;
import mage.abilities.MageSingleton;
import mage.abilities.effects.RestrictionEffect;
-import mage.constants.CardType;
import mage.constants.Duration;
import mage.game.Game;
import mage.game.permanent.Permanent;
diff --git a/Mage/src/main/java/mage/abilities/keyword/KickerAbility.java b/Mage/src/main/java/mage/abilities/keyword/KickerAbility.java
index 67ea722753..10f5565cea 100644
--- a/Mage/src/main/java/mage/abilities/keyword/KickerAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/KickerAbility.java
@@ -110,7 +110,6 @@ public class KickerAbility extends StaticAbility implements OptionalAdditionalSo
this.reminderText = ability.reminderText;
this.xManaValue = ability.xManaValue;
this.activations.putAll(ability.activations);
-
}
@Override
@@ -140,7 +139,6 @@ public class KickerAbility extends StaticAbility implements OptionalAdditionalSo
activations.put(key, 0);
}
}
-
}
public int getXManaValue() {
diff --git a/Mage/src/main/java/mage/abilities/keyword/LandwalkAbility.java b/Mage/src/main/java/mage/abilities/keyword/LandwalkAbility.java
index bf382c7279..3330e8ffd3 100644
--- a/Mage/src/main/java/mage/abilities/keyword/LandwalkAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/LandwalkAbility.java
@@ -88,21 +88,21 @@ class LandwalkEffect extends RestrictionEffect {
@Override
public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game) {
if (game.getBattlefield().contains(filter, blocker.getControllerId(), 1, game)
- && !game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_LANDWALK, source, blocker.getControllerId(), game)) {
+ && null == game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_LANDWALK, source, blocker.getControllerId(), game)) {
switch (filter.getMessage()) {
case "plains":
- return game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_PLAINSWALK, source, blocker.getControllerId(), game);
+ return null != game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_PLAINSWALK, source, blocker.getControllerId(), game);
case "island":
- return game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_ISLANDWALK, source, blocker.getControllerId(), game);
+ return null != game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_ISLANDWALK, source, blocker.getControllerId(), game);
case "swamp":
- return game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_SWAMPWALK, source, blocker.getControllerId(), game);
+ return null != game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_SWAMPWALK, source, blocker.getControllerId(), game);
case "mountain":
- return game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_MOUNTAINWALK, source, blocker.getControllerId(), game);
+ return null != game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_MOUNTAINWALK, source, blocker.getControllerId(), game);
case "forest":
- return game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_FORESTWALK, source, blocker.getControllerId(), game);
+ return null != game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_FORESTWALK, source, blocker.getControllerId(), game);
default:
return false;
-
+
}
}
return true;
diff --git a/Mage/src/main/java/mage/abilities/keyword/MadnessAbility.java b/Mage/src/main/java/mage/abilities/keyword/MadnessAbility.java
index b8a74f8711..44153d7f32 100644
--- a/Mage/src/main/java/mage/abilities/keyword/MadnessAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/MadnessAbility.java
@@ -33,10 +33,10 @@ import mage.players.Player;
* first ability is applied.
*
* "Madness [cost]" means "If a player would discard this card, that player
- * discards it, but may exile it instead of putting it into his or her
+ * discards it, but may exile it instead of putting it into their
* graveyard" and "When this card is exiled this way, its owner may cast it by
* paying [cost] rather than paying its mana cost. If that player doesn't, he or
- * she puts this card into his or her graveyard.
+ * she puts this card into their graveyard.
*
* 702.33b. Casting a spell using its madness ability follows the rules for
* paying alternative costs in rules 601.2b and 601.2e-g.
diff --git a/Mage/src/main/java/mage/abilities/keyword/MenaceAbility.java b/Mage/src/main/java/mage/abilities/keyword/MenaceAbility.java
index 4359a51a2a..711b7b8d2a 100644
--- a/Mage/src/main/java/mage/abilities/keyword/MenaceAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/MenaceAbility.java
@@ -39,7 +39,7 @@ public class MenaceAbility extends StaticAbility { // Menace may not be a Single
@Override
public String getRule() {
- String res = "Menace";
+ String res = "menace";
if (this.showAbilityHint) {
res += " (This creature can't be blocked except by two or more creatures.)";
}
diff --git a/Mage/src/main/java/mage/abilities/keyword/MiracleAbility.java b/Mage/src/main/java/mage/abilities/keyword/MiracleAbility.java
index 20996fb662..ed50e9b7b0 100644
--- a/Mage/src/main/java/mage/abilities/keyword/MiracleAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/MiracleAbility.java
@@ -24,11 +24,11 @@
* 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.keyword;
import mage.abilities.Ability;
+import mage.abilities.SpellAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.costs.mana.ManaCost;
import mage.abilities.costs.mana.ManaCosts;
@@ -45,61 +45,67 @@ import mage.watchers.common.MiracleWatcher;
/**
* 702.92. Miracle
*
- * 702.92a Miracle is a static ability linked to a triggered ability (see rule 603.10).
- * "Miracle [cost]" means "You may reveal this card from your hand as you draw it if
- * it's the first card you've drawn this turn. When you reveal this card this way,
- * you may cast it by paying [cost] rather than its mana cost."
+ * 702.92a Miracle is a static ability linked to a triggered ability (see rule
+ * 603.10). "Miracle [cost]" means "You may reveal this card from your hand as
+ * you draw it if it's the first card you've drawn this turn. When you reveal
+ * this card this way, you may cast it by paying [cost] rather than its mana
+ * cost."
*
- * 702.92b If a player chooses to reveal a card using its miracle ability, he or she
- * plays with that card revealed until that card leaves his or her hand, that ability
- * resolves, or that ability otherwise leaves the stack.
+ * 702.92b If a player chooses to reveal a card using its miracle ability, he or
+ * she plays with that card revealed until that card leaves their hand,
+ * that ability resolves, or that ability otherwise leaves the stack.
*
- * You can cast a card for its miracle cost only as the miracle triggered ability resolves.
- * If you don't want to cast it at that time (or you can't cast it, perhaps because
- * there are no legal targets available), you won't be able to cast it later for the miracle cost.
+ * You can cast a card for its miracle cost only as the miracle triggered
+ * ability resolves. If you don't want to cast it at that time (or you can't
+ * cast it, perhaps because there are no legal targets available), you won't be
+ * able to cast it later for the miracle cost.
*
- * RULINGS:
- * You still draw the card, whether you use the miracle ability or not. Any ability that
- * triggers whenever you draw a card, for example, will trigger. If you don't cast the card
- * using its miracle ability, it will remain in your hand.
+ * RULINGS: You still draw the card, whether you use the miracle ability or not.
+ * Any ability that triggers whenever you draw a card, for example, will
+ * trigger. If you don't cast the card using its miracle ability, it will remain
+ * in your hand.
*
- * You can reveal and cast a card with miracle on any turn, not just your own, if it's the
- * first card you've drawn that turn.
+ * You can reveal and cast a card with miracle on any turn, not just your own,
+ * if it's the first card you've drawn that turn.
*
- * You don't have to reveal a drawn card with miracle if you don't wish to cast it at that time.
+ * You don't have to reveal a drawn card with miracle if you don't wish to cast
+ * it at that time.
*
- * You can cast a card for its miracle cost only as the miracle triggered ability resolves.
- * If you don't want to cast it at that time (or you can't cast it, perhaps because there are
- * no legal targets available), you won't be able to cast it later for the miracle cost.
+ * You can cast a card for its miracle cost only as the miracle triggered
+ * ability resolves. If you don't want to cast it at that time (or you can't
+ * cast it, perhaps because there are no legal targets available), you won't be
+ * able to cast it later for the miracle cost.
*
- * You cast the card with miracle during the resolution of the triggered ability. Ignore any timing
- * restrictions based on the card's type.
+ * You cast the card with miracle during the resolution of the triggered
+ * ability. Ignore any timing restrictions based on the card's type.
*
- * It's important to reveal a card with miracle before it is mixed with the other cards in your hand.
+ * It's important to reveal a card with miracle before it is mixed with the
+ * other cards in your hand.
*
- * Multiple card draws are always treated as a sequence of individual card draws. For example, if
- * you haven't drawn any cards yet during a turn and cast a spell that instructs you to draw three
- * cards, you'll draw them one at a time. Only the first card drawn this way may be revealed and cast
- * using its miracle ability.
+ * Multiple card draws are always treated as a sequence of individual card
+ * draws. For example, if you haven't drawn any cards yet during a turn and cast
+ * a spell that instructs you to draw three cards, you'll draw them one at a
+ * time. Only the first card drawn this way may be revealed and cast using its
+ * miracle ability.
*
- * If the card with miracle leaves your hand before the triggered ability resolves, you won't be able
- * to cast it using its miracle ability.
+ * If the card with miracle leaves your hand before the triggered ability
+ * resolves, you won't be able to cast it using its miracle ability.
*
- * You draw your opening hand before any turn begins. Cards you draw for your opening hand
- * can't be cast using miracle.
+ * You draw your opening hand before any turn begins. Cards you draw for your
+ * opening hand can't be cast using miracle.
*
* @author noxx, LevelX2
*/
-
public class MiracleAbility extends TriggeredAbilityImpl {
+
private static final String staticRule = " (You may cast this card for its miracle cost when you draw it if it's the first card you drew this turn.)";
private String ruleText;
@SuppressWarnings("unchecked")
public MiracleAbility(Card card, ManaCosts miracleCosts) {
- super(Zone.HAND, new MiracleEffect((ManaCosts)miracleCosts), true);
- addWatcher(new MiracleWatcher());
- ruleText = "Miracle " + miracleCosts.getText() + staticRule;
+ super(Zone.HAND, new MiracleEffect((ManaCosts) miracleCosts), true);
+ addWatcher(new MiracleWatcher());
+ ruleText = "Miracle " + miracleCosts.getText() + staticRule;
}
public MiracleAbility(final MiracleAbility ability) {
@@ -161,17 +167,12 @@ class MiracleEffect extends OneShotEffect {
// use target pointer here, so it's the same card that triggered the event (not gone back to library e.g.)
Card card = game.getCard(getTargetPointer().getFirst(game, source));
if (controller != null && card != null) {
- ManaCosts costRef = card.getSpellAbility().getManaCostsToPay();
+ SpellAbility abilityToCast = card.getSpellAbility().copy();
+ ManaCosts costRef = abilityToCast.getManaCostsToPay();
// replace with the new cost
costRef.clear();
costRef.add(miracleCosts);
- controller.cast(card.getSpellAbility(), game, false);
-
- // Reset the casting costs (in case the player cancels cast and plays the card later)
- costRef.clear();
- for (ManaCost manaCost : card.getSpellAbility().getManaCosts()) {
- costRef.add(manaCost);
- }
+ controller.cast(abilityToCast, game, false);
return true;
}
return false;
diff --git a/Mage/src/main/java/mage/abilities/keyword/MorphAbility.java b/Mage/src/main/java/mage/abilities/keyword/MorphAbility.java
index 46714d9243..9415ed3c62 100644
--- a/Mage/src/main/java/mage/abilities/keyword/MorphAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/MorphAbility.java
@@ -230,7 +230,7 @@ public class MorphAbility extends StaticAbility implements AlternativeSourceCost
spellColor.setGreen(false);
spellColor.setWhite(false);
spellColor.setBlue(false);
- spell.getSubtype(game).clear();
+ game.getState().getCreateCardAttribute(spell.getCard(), game).getSubtype().clear();
} else {
spell.setFaceDown(false, game);
}
diff --git a/Mage/src/main/java/mage/abilities/keyword/RecoverAbility.java b/Mage/src/main/java/mage/abilities/keyword/RecoverAbility.java
index 24821a1fd4..0ca43303b7 100644
--- a/Mage/src/main/java/mage/abilities/keyword/RecoverAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/RecoverAbility.java
@@ -35,7 +35,6 @@ import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileSourceEffect;
import mage.abilities.effects.common.ReturnToHandSourceEffect;
import mage.cards.Card;
-import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
diff --git a/Mage/src/main/java/mage/abilities/keyword/ShadowAbility.java b/Mage/src/main/java/mage/abilities/keyword/ShadowAbility.java
index 2573570731..6188b91b59 100644
--- a/Mage/src/main/java/mage/abilities/keyword/ShadowAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/ShadowAbility.java
@@ -66,7 +66,7 @@ class ShadowEffect extends RestrictionEffect implements MageSingleton {
@Override
public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game) {
return blocker.getAbilities().containsKey(ShadowAbility.getInstance().getId())
- || game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_SHADOW, source, blocker.getControllerId(), game);
+ || null != game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_SHADOW, source, blocker.getControllerId(), game);
}
@Override
diff --git a/Mage/src/main/java/mage/abilities/keyword/SpliceOntoArcaneAbility.java b/Mage/src/main/java/mage/abilities/keyword/SpliceOntoArcaneAbility.java
index b21ebe7d89..0a4f96049b 100644
--- a/Mage/src/main/java/mage/abilities/keyword/SpliceOntoArcaneAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/SpliceOntoArcaneAbility.java
@@ -73,7 +73,7 @@ import java.util.Iterator;
* on the stack, not the card from which the text was copied.
*
* Example: Glacial Ray is a red card with splice onto Arcane that reads, "Glacial
- * Ray deals 2 damage to target creature or player." Suppose Glacial Ray is spliced
+ * Ray deals 2 damage to any target." Suppose Glacial Ray is spliced
* onto Reach Through Mists, a blue spell. The spell is still blue, and Reach Through
* Mists deals the damage. This means that the ability can target a creature with
* protection from red and deal 2 damage to that creature.
diff --git a/Mage/src/main/java/mage/abilities/keyword/SupportAbility.java b/Mage/src/main/java/mage/abilities/keyword/SupportAbility.java
index 2d7910e609..fb96512b55 100644
--- a/Mage/src/main/java/mage/abilities/keyword/SupportAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/SupportAbility.java
@@ -30,7 +30,6 @@ package mage.abilities.keyword;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.keyword.SupportEffect;
import mage.cards.Card;
-import mage.constants.CardType;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.AnotherPredicate;
import mage.target.common.TargetCreaturePermanent;
diff --git a/Mage/src/main/java/mage/abilities/keyword/SuspendAbility.java b/Mage/src/main/java/mage/abilities/keyword/SuspendAbility.java
index 0921b18e12..b19ca7db21 100644
--- a/Mage/src/main/java/mage/abilities/keyword/SuspendAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/SuspendAbility.java
@@ -27,6 +27,9 @@
*/
package mage.abilities.keyword;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.SpecialAction;
@@ -50,10 +53,6 @@ import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
/**
*
* 502.59. Suspend
@@ -120,10 +119,10 @@ import java.util.UUID;
* card involves an additional cost, the card's owner must pay that cost if
* able. If he or she can't, the card remains removed from the game. If the
* additional cost includes mana, the situation is more complex. If the player
- * has enough mana in his or her mana pool to pay the cost, that player must do
- * so. If the player can't possibly pay the cost, the card remains removed from
- * the game. However, if the player has the means to produce enough mana to pay
- * the cost, then he or she has a choice: The player may play the spell, produce
+ * has enough mana in their mana pool to pay the cost, that player must do so.
+ * If the player can't possibly pay the cost, the card remains removed from the
+ * game. However, if the player has the means to produce enough mana to pay the
+ * cost, then he or she has a choice: The player may play the spell, produce
* mana, and pay the cost. Or the player may choose to play no mana abilities,
* thus making the card impossible to play because the additional mana can't be
* paid.
@@ -237,7 +236,7 @@ public class SuspendAbility extends SpecialAction {
MageObject object = game.getObject(sourceId);
return (object.isInstant()
|| object.hasAbility(FlashAbility.getInstance().getId(), game)
- || game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.CAST_AS_INSTANT, this, playerId, game)
+ || null != game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.CAST_AS_INSTANT, this, playerId, game)
|| game.canPlaySorcery(playerId));
}
diff --git a/Mage/src/main/java/mage/abilities/mana/ActivatedManaAbilityImpl.java b/Mage/src/main/java/mage/abilities/mana/ActivatedManaAbilityImpl.java
index 61da85343a..e25aadbe69 100644
--- a/Mage/src/main/java/mage/abilities/mana/ActivatedManaAbilityImpl.java
+++ b/Mage/src/main/java/mage/abilities/mana/ActivatedManaAbilityImpl.java
@@ -77,7 +77,7 @@ public abstract class ActivatedManaAbilityImpl extends ActivatedAbilityImpl impl
}
if (timing == TimingRule.SORCERY
&& !game.canPlaySorcery(playerId)
- && !game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_AS_INSTANT, this, controllerId, game)) {
+ && null == game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_AS_INSTANT, this, controllerId, game)) {
return false;
}
// check if player is in the process of playing spell costs and he is no longer allowed to use activated mana abilities (e.g. because he started to use improvise)
diff --git a/Mage/src/main/java/mage/abilities/mana/AnyColorLandsProduceManaAbility.java b/Mage/src/main/java/mage/abilities/mana/AnyColorLandsProduceManaAbility.java
index 5c9f9d2394..b2f4056fe1 100644
--- a/Mage/src/main/java/mage/abilities/mana/AnyColorLandsProduceManaAbility.java
+++ b/Mage/src/main/java/mage/abilities/mana/AnyColorLandsProduceManaAbility.java
@@ -84,7 +84,7 @@ public class AnyColorLandsProduceManaAbility extends ActivatedManaAbilityImpl {
class AnyColorLandsProduceManaEffect extends ManaEffect {
private final FilterPermanent filter;
- private final boolean onlyColors; // false if mana types can be produced (also Colorless mana), if false only colors can be produced (no Colorless mana).
+ private final boolean onlyColors; // false if mana types can be produced (also Colorless mana), if true only colors can be produced (no Colorless mana).
private boolean inManaTypeCalculation = false;
@@ -94,7 +94,7 @@ class AnyColorLandsProduceManaEffect extends ManaEffect {
this.onlyColors = onlyColors;
filter.add(new ControllerPredicate(targetController));
String text = targetController == TargetController.OPPONENT ? "an opponent controls" : "you control";
- staticText = "Add to your mana pool one mana of any " + (this.onlyColors ? "color" : "type") + " that a land " + text + " could produce";
+ staticText = "Add one mana of any " + (this.onlyColors ? "color" : "type") + " that a land " + text + " could produce";
}
public AnyColorLandsProduceManaEffect(final AnyColorLandsProduceManaEffect effect) {
@@ -190,7 +190,6 @@ class AnyColorLandsProduceManaEffect extends ManaEffect {
return types;
}
inManaTypeCalculation = true;
- // Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "needed to identify endless loop causing cards: {0}", source.getSourceObject(game).getName());
List lands = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game);
for (Permanent land : lands) {
Abilities mana = land.getAbilities().getActivatedManaAbilities(Zone.BATTLEFIELD);
diff --git a/Mage/src/main/java/mage/abilities/mana/AnyColorPermanentTypesManaAbility.java b/Mage/src/main/java/mage/abilities/mana/AnyColorPermanentTypesManaAbility.java
new file mode 100644
index 0000000000..b94f573055
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/mana/AnyColorPermanentTypesManaAbility.java
@@ -0,0 +1,221 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package mage.abilities.mana;
+
+import java.util.ArrayList;
+import java.util.List;
+import mage.Mana;
+import mage.ObjectColor;
+import mage.abilities.Ability;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.effects.common.ManaEffect;
+import mage.choices.Choice;
+import mage.choices.ChoiceColor;
+import mage.constants.ColoredManaSymbol;
+import mage.constants.TargetController;
+import mage.constants.Zone;
+import mage.filter.FilterPermanent;
+import mage.filter.predicate.permanent.ControllerPredicate;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+
+/**
+ *
+ * @author CountAndromalius
+ */
+public class AnyColorPermanentTypesManaAbility extends ActivatedManaAbilityImpl {
+
+ public AnyColorPermanentTypesManaAbility(TargetController targetController, FilterPermanent permanentTypes) {
+ this(targetController, true, permanentTypes);
+ }
+
+ public AnyColorPermanentTypesManaAbility(TargetController targetController, boolean onlyColors, FilterPermanent permanentTypes) {
+ super(Zone.BATTLEFIELD, new AnyColorPermanentTypesManaEffect(targetController, onlyColors, permanentTypes), new TapSourceCost());
+ }
+
+ public AnyColorPermanentTypesManaAbility(final AnyColorPermanentTypesManaAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public AnyColorPermanentTypesManaAbility copy() {
+ return new AnyColorPermanentTypesManaAbility(this);
+ }
+
+ @Override
+ public List getNetMana(Game game) {
+ return ((AnyColorPermanentTypesManaEffect) getEffects().get(0)).getNetMana(game, this);
+ }
+
+ @Override
+ public boolean definesMana(Game game) {
+ return true;
+ }
+
+}
+
+class AnyColorPermanentTypesManaEffect extends ManaEffect {
+
+ private final FilterPermanent filter;
+ private final boolean onlyColors; // false if mana types can be produced (also Colorless mana), if true only colors can be produced (no Colorless mana).
+
+ private boolean inManaTypeCalculation = false;
+
+ public AnyColorPermanentTypesManaEffect(TargetController targetController, boolean onlyColors, FilterPermanent permanentTypes) {
+ super();
+ filter = permanentTypes;
+ this.onlyColors = onlyColors;
+ filter.add(new ControllerPredicate(targetController));
+ String text = targetController == TargetController.OPPONENT ? "an opponent controls." : "you control.";
+ staticText = "Add one mana of any " + (this.onlyColors ? "color" : "type") + " among " + permanentTypes.getMessage() + " " + text;
+ }
+
+ public AnyColorPermanentTypesManaEffect(final AnyColorPermanentTypesManaEffect effect) {
+ super(effect);
+ this.filter = effect.filter.copy();
+ this.onlyColors = effect.onlyColors;
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Mana types = getManaTypes(game, source);
+ Choice choice = new ChoiceColor(true);
+ choice.getChoices().clear();
+ choice.setMessage("Pick a mana color");
+ if (types.getBlack() > 0) {
+ choice.getChoices().add("Black");
+ }
+ if (types.getRed() > 0) {
+ choice.getChoices().add("Red");
+ }
+ if (types.getBlue() > 0) {
+ choice.getChoices().add("Blue");
+ }
+ if (types.getGreen() > 0) {
+ choice.getChoices().add("Green");
+ }
+ if (types.getWhite() > 0) {
+ choice.getChoices().add("White");
+ }
+ if (!onlyColors && types.getColorless() > 0) {
+ choice.getChoices().add("Colorless");
+ }
+ if (types.getAny() > 0) {
+ choice.getChoices().add("Black");
+ choice.getChoices().add("Red");
+ choice.getChoices().add("Blue");
+ choice.getChoices().add("Green");
+ choice.getChoices().add("White");
+ if (!onlyColors) {
+ choice.getChoices().add("Colorless");
+ }
+
+ }
+ if (!choice.getChoices().isEmpty()) {
+ Player player = game.getPlayer(source.getControllerId());
+ if (choice.getChoices().size() == 1) {
+ choice.setChoice(choice.getChoices().iterator().next());
+ } else {
+ if (!player.choose(outcome, choice, game)) {
+ return false;
+ }
+ }
+ if (choice.getChoice() != null) {
+ Mana mana = new Mana();
+ switch (choice.getChoice()) {
+ case "Black":
+ mana.setBlack(1);
+ break;
+ case "Blue":
+ mana.setBlue(1);
+ break;
+ case "Red":
+ mana.setRed(1);
+ break;
+ case "Green":
+ mana.setGreen(1);
+ break;
+ case "White":
+ mana.setWhite(1);
+ break;
+ case "Colorless":
+ mana.setColorless(1);
+ break;
+ }
+ checkToFirePossibleEvents(mana, game, source);
+ player.getManaPool().addMana(mana, game, source);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public Mana getMana(Game game, Ability source) {
+ return null;
+ }
+
+ private Mana getManaTypes(Game game, Ability source) {
+ Mana types = new Mana();
+ if (game == null || game.getPhase() == null) {
+ return types;
+ }
+ if (inManaTypeCalculation) {
+ return types;
+ }
+ inManaTypeCalculation = true;
+
+ ObjectColor permanentColor;
+
+ List permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game);
+
+ for (Permanent permanent : permanents) {
+ permanentColor = permanent.getColor(game);
+ if(permanentColor.isColorless())
+ types.add(Mana.ColorlessMana(1));
+ else{
+ List permanentColors = permanent.getColor(game).getColors();
+ for (ObjectColor color : permanentColors){
+ types.add(new Mana(color.getColoredManaSymbol()));
+ }
+ }
+ }
+ inManaTypeCalculation = false;
+ return types;
+ }
+
+ public List getNetMana(Game game, Ability source) {
+ List netManas = new ArrayList<>();
+ Mana types = getManaTypes(game, source);
+ if (types.getBlack() > 0) {
+ netManas.add(new Mana(ColoredManaSymbol.B));
+ }
+ if (types.getRed() > 0) {
+ netManas.add(new Mana(ColoredManaSymbol.R));
+ }
+ if (types.getBlue() > 0) {
+ netManas.add(new Mana(ColoredManaSymbol.U));
+ }
+ if (types.getGreen() > 0) {
+ netManas.add(new Mana(ColoredManaSymbol.G));
+ }
+ if (types.getWhite() > 0) {
+ netManas.add(new Mana(ColoredManaSymbol.W));
+ }
+ if (types.getColorless() > 0) {
+ netManas.add(Mana.ColorlessMana(1));
+ }
+ if (types.getAny() > 0) {
+ netManas.add(Mana.AnyMana(1));
+ }
+ return netManas;
+ }
+
+ @Override
+ public AnyColorPermanentTypesManaEffect copy() {
+ return new AnyColorPermanentTypesManaEffect(this);
+ }
+}
diff --git a/Mage/src/main/java/mage/abilities/mana/CommanderColorIdentityManaAbility.java b/Mage/src/main/java/mage/abilities/mana/CommanderColorIdentityManaAbility.java
index 25be09ac97..0af4d691c6 100644
--- a/Mage/src/main/java/mage/abilities/mana/CommanderColorIdentityManaAbility.java
+++ b/Mage/src/main/java/mage/abilities/mana/CommanderColorIdentityManaAbility.java
@@ -42,7 +42,6 @@ import mage.constants.Zone;
import mage.filter.FilterMana;
import mage.game.Game;
import mage.players.Player;
-import mage.util.CardUtil;
/**
*
@@ -109,7 +108,7 @@ class CommanderIdentityManaEffect extends ManaEffect {
public CommanderIdentityManaEffect() {
super();
- this.staticText = "Add to your mana pool one mana of any color in your commander's color identity";
+ this.staticText = "Add one mana of any color in your commander's color identity";
}
public CommanderIdentityManaEffect(final CommanderIdentityManaEffect effect) {
diff --git a/Mage/src/main/java/mage/abilities/mana/ConditionalAnyColorManaAbility.java b/Mage/src/main/java/mage/abilities/mana/ConditionalAnyColorManaAbility.java
index a0fbbcc4c6..916997a34c 100644
--- a/Mage/src/main/java/mage/abilities/mana/ConditionalAnyColorManaAbility.java
+++ b/Mage/src/main/java/mage/abilities/mana/ConditionalAnyColorManaAbility.java
@@ -40,7 +40,7 @@ import mage.game.Game;
/**
* For cards like:
- * {tap}: Add three mana of any one color to your mana pool. Spend this mana only to cast creature spells.
+ * {tap}: Add three mana of any one color. Spend this mana only to cast creature spells.
*
* @author noxx
*/
diff --git a/Mage/src/main/java/mage/abilities/mana/builder/common/InstantOrSorcerySpellManaBuilder.java b/Mage/src/main/java/mage/abilities/mana/builder/common/InstantOrSorcerySpellManaBuilder.java
new file mode 100644
index 0000000000..6f6f61f23f
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/mana/builder/common/InstantOrSorcerySpellManaBuilder.java
@@ -0,0 +1,63 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package mage.abilities.mana.builder.common;
+
+import java.util.UUID;
+import mage.ConditionalMana;
+import mage.MageObject;
+import mage.Mana;
+import mage.abilities.Ability;
+import mage.abilities.SpellAbility;
+import mage.abilities.condition.Condition;
+import mage.abilities.costs.Cost;
+import mage.abilities.mana.builder.ConditionalManaBuilder;
+import mage.abilities.mana.conditional.ManaCondition;
+import mage.game.Game;
+
+/**
+ *
+ * @author LevelX2
+ */
+public class InstantOrSorcerySpellManaBuilder extends ConditionalManaBuilder {
+
+ @Override
+ public ConditionalMana build(Object... options) {
+ return new InstantOrSorceryCastConditionalMana(this.mana);
+ }
+
+ @Override
+ public String getRule() {
+ return "Spend this mana only to cast an instant or sorcery spell";
+ }
+}
+
+class InstantOrSorceryCastConditionalMana extends ConditionalMana {
+
+ public InstantOrSorceryCastConditionalMana(Mana mana) {
+ super(mana);
+ staticText = "Spend this mana only to cast an instant or sorcery spell";
+ addCondition(new InstantOrSorceryCastManaCondition());
+ }
+}
+
+class InstantOrSorceryCastManaCondition extends ManaCondition implements Condition {
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ if (source instanceof SpellAbility) {
+ MageObject object = game.getObject(source.getSourceId());
+ if (object != null && (object.isInstant() || object.isSorcery())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source, UUID originalId, Cost costsToPay) {
+ return apply(game, source);
+ }
+}
diff --git a/Mage/src/main/java/mage/abilities/mana/conditional/ArtifactCastManaCondition.java b/Mage/src/main/java/mage/abilities/mana/conditional/ArtifactCastManaCondition.java
index 7df3d14704..6144d884fc 100644
--- a/Mage/src/main/java/mage/abilities/mana/conditional/ArtifactCastManaCondition.java
+++ b/Mage/src/main/java/mage/abilities/mana/conditional/ArtifactCastManaCondition.java
@@ -33,7 +33,6 @@ import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.condition.Condition;
import mage.abilities.costs.Cost;
-import mage.constants.CardType;
import mage.game.Game;
/**
diff --git a/Mage/src/main/java/mage/abilities/mana/conditional/CreatureCastManaCondition.java b/Mage/src/main/java/mage/abilities/mana/conditional/CreatureCastManaCondition.java
index f1deebbca7..bf4e13c765 100644
--- a/Mage/src/main/java/mage/abilities/mana/conditional/CreatureCastManaCondition.java
+++ b/Mage/src/main/java/mage/abilities/mana/conditional/CreatureCastManaCondition.java
@@ -33,7 +33,6 @@ import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.condition.Condition;
import mage.abilities.costs.Cost;
-import mage.constants.CardType;
import mage.game.Game;
/**
diff --git a/Mage/src/main/java/mage/cards/Card.java b/Mage/src/main/java/mage/cards/Card.java
index 16a30646ee..7cff835114 100644
--- a/Mage/src/main/java/mage/cards/Card.java
+++ b/Mage/src/main/java/mage/cards/Card.java
@@ -31,7 +31,6 @@ import java.util.List;
import java.util.UUID;
import mage.MageObject;
import mage.Mana;
-import mage.ObjectColor;
import mage.abilities.Abilities;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
@@ -46,12 +45,6 @@ import mage.game.permanent.Permanent;
public interface Card extends MageObject {
- final String regexBlack = ".*\\x7b.{0,2}B.{0,2}\\x7d.*";
- final String regexBlue = ".*\\x7b.{0,2}U.{0,2}\\x7d.*";
- final String regexRed = ".*\\x7b.{0,2}R.{0,2}\\x7d.*";
- final String regexGreen = ".*\\x7b.{0,2}G.{0,2}\\x7d.*";
- final String regexWhite = ".*\\x7b.{0,2}W.{0,2}\\x7d.*";
-
UUID getOwnerId();
String getCardNumber();
@@ -177,7 +170,7 @@ public interface Card extends MageObject {
/**
*
- * @return The main card of a split half card, otherwise thae card itself is
+ * @return The main card of a split half card, otherwise the card itself is
* returned
*/
Card getMainCard();
@@ -188,62 +181,7 @@ public interface Card extends MageObject {
*
* @return
*/
- default FilterMana getColorIdentity() {
- FilterMana mana = new FilterMana();
- mana.setBlack(getManaCost().getText().matches(regexBlack));
- mana.setBlue(getManaCost().getText().matches(regexBlue));
- mana.setGreen(getManaCost().getText().matches(regexGreen));
- mana.setRed(getManaCost().getText().matches(regexRed));
- mana.setWhite(getManaCost().getText().matches(regexWhite));
-
- for (String rule : getRules()) {
- rule = rule.replaceAll("(?i)", ""); // Ignoring reminder text in italic
- if (!mana.isBlack() && rule.matches(regexBlack)) {
- mana.setBlack(true);
- }
- if (!mana.isBlue() && rule.matches(regexBlue)) {
- mana.setBlue(true);
- }
- if (!mana.isGreen() && rule.matches(regexGreen)) {
- mana.setGreen(true);
- }
- if (!mana.isRed() && rule.matches(regexRed)) {
- mana.setRed(true);
- }
- if (!mana.isWhite() && rule.matches(regexWhite)) {
- mana.setWhite(true);
- }
- }
- if (isTransformable()) {
- Card secondCard = getSecondCardFace();
- ObjectColor color = secondCard.getColor(null);
- mana.setBlack(mana.isBlack() || color.isBlack());
- mana.setGreen(mana.isGreen() || color.isGreen());
- mana.setRed(mana.isRed() || color.isRed());
- mana.setBlue(mana.isBlue() || color.isBlue());
- mana.setWhite(mana.isWhite() || color.isWhite());
- for (String rule : secondCard.getRules()) {
- rule = rule.replaceAll("(?i)", ""); // Ignoring reminder text in italic
- if (!mana.isBlack() && rule.matches(regexBlack)) {
- mana.setBlack(true);
- }
- if (!mana.isBlue() && rule.matches(regexBlue)) {
- mana.setBlue(true);
- }
- if (!mana.isGreen() && rule.matches(regexGreen)) {
- mana.setGreen(true);
- }
- if (!mana.isRed() && rule.matches(regexRed)) {
- mana.setRed(true);
- }
- if (!mana.isWhite() && rule.matches(regexWhite)) {
- mana.setWhite(true);
- }
- }
- }
-
- return mana;
- }
+ FilterMana getColorIdentity();
List getAttachments();
diff --git a/Mage/src/main/java/mage/cards/CardImpl.java b/Mage/src/main/java/mage/cards/CardImpl.java
index 4fc6a220e9..db7017c9ea 100644
--- a/Mage/src/main/java/mage/cards/CardImpl.java
+++ b/Mage/src/main/java/mage/cards/CardImpl.java
@@ -28,6 +28,7 @@
package mage.cards;
import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
import java.util.*;
import mage.MageObject;
import mage.MageObjectImpl;
@@ -35,6 +36,7 @@ import mage.Mana;
import mage.ObjectColor;
import mage.abilities.*;
import mage.abilities.costs.Cost;
+import mage.abilities.costs.VariableCost;
import mage.abilities.costs.common.RemoveVariableCountersTargetCost;
import mage.abilities.effects.common.NameACardEffect;
import mage.abilities.mana.ActivatedManaAbilityImpl;
@@ -44,6 +46,7 @@ import mage.counters.Counter;
import mage.counters.CounterType;
import mage.counters.Counters;
import mage.filter.FilterCard;
+import mage.filter.FilterMana;
import mage.filter.FilterPermanent;
import mage.filter.FilterSpell;
import mage.filter.common.FilterCreaturePermanent;
@@ -73,6 +76,12 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
private static final Logger logger = Logger.getLogger(CardImpl.class);
+ private static final String regexBlack = ".*\\x7b.{0,2}B.{0,2}\\x7d.*";
+ private static final String regexBlue = ".*\\x7b.{0,2}U.{0,2}\\x7d.*";
+ private static final String regexRed = ".*\\x7b.{0,2}R.{0,2}\\x7d.*";
+ private static final String regexGreen = ".*\\x7b.{0,2}G.{0,2}\\x7d.*";
+ private static final String regexWhite = ".*\\x7b.{0,2}W.{0,2}\\x7d.*";
+
protected UUID ownerId;
protected String cardNumber;
public String expansionSetCode;
@@ -89,7 +98,6 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
protected boolean usesVariousArt = false;
protected boolean splitCard;
protected boolean morphCard;
- protected boolean allCreatureTypes;
protected List attachments = new ArrayList<>();
@@ -206,22 +214,30 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
}
public static Card createCard(Class> clazz, CardSetInfo setInfo, List errorList) {
+ String setCode = null;
try {
Card card;
if (setInfo == null) {
Constructor> con = clazz.getConstructor(UUID.class);
card = (Card) con.newInstance(new Object[]{null});
} else {
+ setCode = setInfo.getExpansionSetCode();
Constructor> con = clazz.getConstructor(UUID.class, CardSetInfo.class);
card = (Card) con.newInstance(null, setInfo);
}
return card;
} catch (Exception e) {
- String err = "Error loading card: " + clazz.getCanonicalName();
+ String err = "Error loading card: " + clazz.getCanonicalName() + " (" + setCode + ")";
if (errorList != null) {
errorList.add(err);
}
- logger.fatal(err, e);
+
+ if (e instanceof InvocationTargetException) {
+ logger.fatal(err, ((InvocationTargetException) e).getTargetException());
+ } else {
+ logger.fatal(err, e);
+ }
+
return null;
}
}
@@ -449,6 +465,16 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
newFilter.add(new PowerPredicate(ComparisonType.FEWER_THAN, xValue + 1));
ability.addTarget(new TargetCreaturePermanent(newFilter));
break;
+ case CREATURE_POWER_X_OR_LESS: // Aryel, Knight of Windgrace
+ int value = 0;
+ for (VariableCost cost : ability.getCosts().getVariableCosts()) {
+ value = cost.getAmount();
+ }
+ FilterCreaturePermanent filterCreaturePermanent = new FilterCreaturePermanent("creature with power " + value + " or less");
+ filterCreaturePermanent.add(new PowerPredicate(ComparisonType.FEWER_THAN, value + 1));
+ ability.getTargets().clear();
+ ability.addTarget(new TargetCreaturePermanent(filterCreaturePermanent));
+ break;
}
}
@@ -825,6 +851,64 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
return this;
}
+ @Override
+ public FilterMana getColorIdentity() {
+ FilterMana mana = new FilterMana();
+ mana.setBlack(getManaCost().getText().matches(regexBlack));
+ mana.setBlue(getManaCost().getText().matches(regexBlue));
+ mana.setGreen(getManaCost().getText().matches(regexGreen));
+ mana.setRed(getManaCost().getText().matches(regexRed));
+ mana.setWhite(getManaCost().getText().matches(regexWhite));
+
+ for (String rule : getRules()) {
+ rule = rule.replaceAll("(?i)", ""); // Ignoring reminder text in italic
+ if (!mana.isBlack() && (rule.matches(regexBlack) || this.color.isBlack())) {
+ mana.setBlack(true);
+ }
+ if (!mana.isBlue() && (rule.matches(regexBlue) || this.color.isBlue())) {
+ mana.setBlue(true);
+ }
+ if (!mana.isGreen() && (rule.matches(regexGreen) || this.color.isGreen())) {
+ mana.setGreen(true);
+ }
+ if (!mana.isRed() && (rule.matches(regexRed) || this.color.isRed())) {
+ mana.setRed(true);
+ }
+ if (!mana.isWhite() && (rule.matches(regexWhite) || this.color.isWhite())) {
+ mana.setWhite(true);
+ }
+ }
+ if (isTransformable()) {
+ Card secondCard = getSecondCardFace();
+ ObjectColor color = secondCard.getColor(null);
+ mana.setBlack(mana.isBlack() || color.isBlack());
+ mana.setGreen(mana.isGreen() || color.isGreen());
+ mana.setRed(mana.isRed() || color.isRed());
+ mana.setBlue(mana.isBlue() || color.isBlue());
+ mana.setWhite(mana.isWhite() || color.isWhite());
+ for (String rule : secondCard.getRules()) {
+ rule = rule.replaceAll("(?i)", ""); // Ignoring reminder text in italic
+ if (!mana.isBlack() && rule.matches(regexBlack)) {
+ mana.setBlack(true);
+ }
+ if (!mana.isBlue() && rule.matches(regexBlue)) {
+ mana.setBlue(true);
+ }
+ if (!mana.isGreen() && rule.matches(regexGreen)) {
+ mana.setGreen(true);
+ }
+ if (!mana.isRed() && rule.matches(regexRed)) {
+ mana.setRed(true);
+ }
+ if (!mana.isWhite() && rule.matches(regexWhite)) {
+ mana.setWhite(true);
+ }
+ }
+ }
+
+ return mana;
+ }
+
@Override
public void setZone(Zone zone, Game game) {
game.setZone(getId(), zone);
@@ -857,16 +941,6 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
return super.getSubtype(game);
}
- @Override
- public boolean isAllCreatureTypes() {
- return allCreatureTypes;
- }
-
- @Override
- public void setIsAllCreatureTypes(boolean value) {
- allCreatureTypes = value;
- }
-
@Override
public List getAttachments() {
return attachments;
diff --git a/Mage/src/main/java/mage/cards/ExpansionSet.java b/Mage/src/main/java/mage/cards/ExpansionSet.java
index c14340386e..69ede8fab7 100644
--- a/Mage/src/main/java/mage/cards/ExpansionSet.java
+++ b/Mage/src/main/java/mage/cards/ExpansionSet.java
@@ -83,7 +83,7 @@ public abstract class ExpansionSet implements Serializable {
return this.cardNumber;
}
- public int getCardNumberAsInt(){
+ public int getCardNumberAsInt() {
return CardUtil.parseCardNumberAsInt(this.cardNumber);
}
@@ -121,6 +121,7 @@ public abstract class ExpansionSet implements Serializable {
protected int numBoosterRare;
protected int numBoosterDoubleFaced; // -1 = include normally 0 = exclude 1-n = include explicit
protected int ratioBoosterMythic;
+ protected boolean needsLegends = false;
protected int maxCardNumberInBooster; // used to omit cards with collector numbers beyond the regular cards in a set for boosters
@@ -210,6 +211,20 @@ public abstract class ExpansionSet implements Serializable {
}
public List