mirror of
https://github.com/magefree/mage.git
synced 2025-12-22 03:22:00 -08:00
Merge origin/master
This commit is contained in:
commit
89ce87e16e
57 changed files with 2814 additions and 1336 deletions
|
|
@ -64,7 +64,7 @@ public class VortexElemental extends CardImpl {
|
||||||
this.toughness = new MageInt(1);
|
this.toughness = new MageInt(1);
|
||||||
|
|
||||||
// {U}: Put Vortex Elemental and each creature blocking or blocked by it on top of their owners' libraries, then those players shuffle their libraries.
|
// {U}: Put Vortex Elemental and each creature blocking or blocked by it on top of their owners' libraries, then those players shuffle their libraries.
|
||||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new VortexElementaöEffect(), new ManaCostsImpl("{U}")));
|
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new VortexElementalEffect(), new ManaCostsImpl("{U}")));
|
||||||
|
|
||||||
// {3}{U}{U}: Target creature blocks Vortex Elemental this turn if able.
|
// {3}{U}{U}: Target creature blocks Vortex Elemental this turn if able.
|
||||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MustBeBlockedByTargetSourceEffect(), new ManaCostsImpl("{3}{U}{U}"));
|
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MustBeBlockedByTargetSourceEffect(), new ManaCostsImpl("{3}{U}{U}"));
|
||||||
|
|
@ -82,20 +82,20 @@ public class VortexElemental extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class VortexElementaöEffect extends OneShotEffect {
|
class VortexElementalEffect extends OneShotEffect {
|
||||||
|
|
||||||
public VortexElementaöEffect() {
|
public VortexElementalEffect() {
|
||||||
super(Outcome.Benefit);
|
super(Outcome.Benefit);
|
||||||
this.staticText = "Put {this} and each creature blocking or blocked by it on top of their owners' libraries, then those players shuffle their libraries";
|
this.staticText = "Put {this} and each creature blocking or blocked by it on top of their owners' libraries, then those players shuffle their libraries";
|
||||||
}
|
}
|
||||||
|
|
||||||
public VortexElementaöEffect(final VortexElementaöEffect effect) {
|
public VortexElementalEffect(final VortexElementalEffect effect) {
|
||||||
super(effect);
|
super(effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VortexElementaöEffect copy() {
|
public VortexElementalEffect copy() {
|
||||||
return new VortexElementaöEffect(this);
|
return new VortexElementalEffect(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -103,8 +103,8 @@ class VortexElementaöEffect extends OneShotEffect {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller != null) {
|
if (controller != null) {
|
||||||
Combat combat = game.getState().getCombat();
|
Combat combat = game.getState().getCombat();
|
||||||
Set<UUID> creaturesToReturn = new HashSet<UUID>();
|
Set<UUID> creaturesToReturn = new HashSet<>();
|
||||||
Set<UUID> playersToShuffle = new HashSet<UUID>();
|
Set<UUID> playersToShuffle = new HashSet<>();
|
||||||
creaturesToReturn.add(source.getSourceId());
|
creaturesToReturn.add(source.getSourceId());
|
||||||
if (combat != null) {
|
if (combat != null) {
|
||||||
for(CombatGroup combatGroup: combat.getGroups()) {
|
for(CombatGroup combatGroup: combat.getGroups()) {
|
||||||
|
|
|
||||||
|
|
@ -1,145 +1,146 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification, are
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
* permitted provided that the following conditions are met:
|
* permitted provided that the following conditions are met:
|
||||||
*
|
*
|
||||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
* conditions and the following disclaimer.
|
* conditions and the following disclaimer.
|
||||||
*
|
*
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
* 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
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
* provided with the distribution.
|
* provided with the distribution.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
* 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
|
* 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
|
* 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
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 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
|
* 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
|
* 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
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* The views and conclusions contained in the software and documentation are those of the
|
* 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
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
* or implied, of BetaSteward_at_googlemail.com.
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
*/
|
*/
|
||||||
package mage.sets.championsofkamigawa;
|
package mage.sets.championsofkamigawa;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.condition.Condition;
|
import mage.abilities.condition.Condition;
|
||||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
import mage.abilities.effects.common.discard.DiscardControllerEffect;
|
import mage.abilities.effects.common.discard.DiscardControllerEffect;
|
||||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||||
import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect;
|
import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.constants.WatcherScope;
|
import mage.constants.WatcherScope;
|
||||||
import mage.filter.common.FilterCreatureCard;
|
import mage.filter.common.FilterCreatureCard;
|
||||||
import mage.filter.predicate.mageobject.NamePredicate;
|
import mage.filter.predicate.mageobject.NamePredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.events.GameEvent.EventType;
|
import mage.game.events.GameEvent.EventType;
|
||||||
import mage.game.stack.Spell;
|
import mage.game.stack.Spell;
|
||||||
import mage.target.common.TargetCardInLibrary;
|
import mage.target.common.TargetCardInLibrary;
|
||||||
import mage.watchers.Watcher;
|
import mage.watchers.Watcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author LevelX2
|
* @author LevelX2
|
||||||
*/
|
*/
|
||||||
public class SiftThroughSands extends CardImpl {
|
public class SiftThroughSands extends CardImpl {
|
||||||
|
|
||||||
private static final String rule = "If you've cast a spell named Peer Through Depths and a spell named Reach Through Mists this turn, you may search your library for a card named The Unspeakable, put it onto the battlefield, then shuffle your library";
|
private static final String rule = "If you've cast a spell named Peer Through Depths and a spell named Reach Through Mists this turn, you may search your library for a card named The Unspeakable, put it onto the battlefield, then shuffle your library";
|
||||||
private static final FilterCreatureCard filter = new FilterCreatureCard("a card named The Unspeakable");
|
private static final FilterCreatureCard filter = new FilterCreatureCard("a card named The Unspeakable");
|
||||||
static {
|
static {
|
||||||
filter.add(new NamePredicate("The Unspeakable"));
|
filter.add(new NamePredicate("The Unspeakable"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public SiftThroughSands(UUID ownerId) {
|
public SiftThroughSands(UUID ownerId) {
|
||||||
super(ownerId, 84, "Sift Through Sands", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{U}{U}");
|
super(ownerId, 84, "Sift Through Sands", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{U}{U}");
|
||||||
this.expansionSetCode = "CHK";
|
this.expansionSetCode = "CHK";
|
||||||
this.subtype.add("Arcane");
|
this.subtype.add("Arcane");
|
||||||
|
|
||||||
this.color.setBlue(true);
|
this.color.setBlue(true);
|
||||||
|
|
||||||
// Draw two cards, then discard a card.
|
// Draw two cards, then discard a card.
|
||||||
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(2));
|
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(2));
|
||||||
Effect effect = new DiscardControllerEffect(1);
|
Effect effect = new DiscardControllerEffect(1);
|
||||||
effect.setText(", then discard a card");
|
effect.setText(", then discard a card");
|
||||||
this.getSpellAbility().addEffect(effect);
|
this.getSpellAbility().addEffect(effect);
|
||||||
// If you've cast a spell named Peer Through Depths and a spell named Reach Through Mists this turn, you may search your library for a card named The Unspeakable, put it onto the battlefield, then shuffle your library.
|
|
||||||
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter), false, true), new SiftThroughSandsCondition(), rule));
|
// If you've cast a spell named Peer Through Depths and a spell named Reach Through Mists this turn, you may search your library for a card named The Unspeakable, put it onto the battlefield, then shuffle your library.
|
||||||
this.getSpellAbility().addWatcher(new SiftThroughSandsWatcher());
|
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter), false, true), new SiftThroughSandsCondition(), rule));
|
||||||
}
|
this.getSpellAbility().addWatcher(new SiftThroughSandsWatcher());
|
||||||
|
}
|
||||||
public SiftThroughSands(final SiftThroughSands card) {
|
|
||||||
super(card);
|
public SiftThroughSands(final SiftThroughSands card) {
|
||||||
}
|
super(card);
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public SiftThroughSands copy() {
|
@Override
|
||||||
return new SiftThroughSands(this);
|
public SiftThroughSands copy() {
|
||||||
}
|
return new SiftThroughSands(this);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
class SiftThroughSandsCondition implements Condition {
|
|
||||||
|
class SiftThroughSandsCondition implements Condition {
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
@Override
|
||||||
SiftThroughSandsWatcher watcher = (SiftThroughSandsWatcher) game.getState().getWatchers().get("SiftThroughSandsWatcher", source.getControllerId());
|
public boolean apply(Game game, Ability source) {
|
||||||
if (watcher != null) {
|
SiftThroughSandsWatcher watcher = (SiftThroughSandsWatcher) game.getState().getWatchers().get("SiftThroughSandsWatcher", source.getControllerId());
|
||||||
return watcher.conditionMet();
|
if (watcher != null) {
|
||||||
}
|
return watcher.conditionMet();
|
||||||
return false;
|
}
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
class SiftThroughSandsWatcher extends Watcher {
|
|
||||||
|
class SiftThroughSandsWatcher extends Watcher {
|
||||||
boolean castPeerThroughDepths = false;
|
|
||||||
boolean castReachThroughMists = false;
|
boolean castPeerThroughDepths = false;
|
||||||
|
boolean castReachThroughMists = false;
|
||||||
public SiftThroughSandsWatcher() {
|
|
||||||
super("SiftThroughSandsWatcher", WatcherScope.PLAYER);
|
public SiftThroughSandsWatcher() {
|
||||||
}
|
super("SiftThroughSandsWatcher", WatcherScope.PLAYER);
|
||||||
|
}
|
||||||
public SiftThroughSandsWatcher(final SiftThroughSandsWatcher watcher) {
|
|
||||||
super(watcher);
|
public SiftThroughSandsWatcher(final SiftThroughSandsWatcher watcher) {
|
||||||
this.castPeerThroughDepths = watcher.castPeerThroughDepths;
|
super(watcher);
|
||||||
this.castReachThroughMists = watcher.castReachThroughMists;
|
this.castPeerThroughDepths = watcher.castPeerThroughDepths;
|
||||||
}
|
this.castReachThroughMists = watcher.castReachThroughMists;
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public SiftThroughSandsWatcher copy() {
|
@Override
|
||||||
return new SiftThroughSandsWatcher(this);
|
public SiftThroughSandsWatcher copy() {
|
||||||
}
|
return new SiftThroughSandsWatcher(this);
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public void watch(GameEvent event, Game game) {
|
@Override
|
||||||
if (condition == true) { //no need to check - condition has already occured
|
public void watch(GameEvent event, Game game) {
|
||||||
return;
|
if (condition == true) { //no need to check - condition has already occured
|
||||||
}
|
return;
|
||||||
if (event.getType() == EventType.SPELL_CAST
|
}
|
||||||
&& controllerId == event.getPlayerId()) {
|
if (event.getType() == EventType.SPELL_CAST
|
||||||
Spell spell = game.getStack().getSpell(event.getTargetId());
|
&& controllerId == event.getPlayerId()) {
|
||||||
if (spell.getCard().getName().equals("Peer Through Depths")) {
|
Spell spell = game.getStack().getSpell(event.getTargetId());
|
||||||
castPeerThroughDepths = true;
|
if (spell.getCard().getName().equals("Peer Through Depths")) {
|
||||||
} else if (spell.getCard().getName().equals("Reach Through Mists")) {
|
castPeerThroughDepths = true;
|
||||||
castReachThroughMists = true;
|
} else if (spell.getCard().getName().equals("Reach Through Mists")) {
|
||||||
}
|
castReachThroughMists = true;
|
||||||
condition = castPeerThroughDepths && castReachThroughMists;
|
}
|
||||||
}
|
condition = castPeerThroughDepths && castReachThroughMists;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public void reset() {
|
@Override
|
||||||
super.reset();
|
public void reset() {
|
||||||
this.castPeerThroughDepths = false;
|
super.reset();
|
||||||
this.castReachThroughMists = false;
|
this.castPeerThroughDepths = false;
|
||||||
}
|
this.castReachThroughMists = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ class CommandeerEffect extends OneShotEffect {
|
||||||
Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source));
|
Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source));
|
||||||
if (controller != null && spell != null) {
|
if (controller != null && spell != null) {
|
||||||
spell.setControllerId(controller.getId());
|
spell.setControllerId(controller.getId());
|
||||||
spell.chooseNewTargets(game, controller.getId(), false, false);
|
spell.chooseNewTargets(game, controller.getId(), false, false, null);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,7 @@ class LightningStormAddCounterEffect extends OneShotEffect {
|
||||||
Spell spell = game.getStack().getSpell(source.getSourceId());
|
Spell spell = game.getStack().getSpell(source.getSourceId());
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
spell.addCounters(CounterType.CHARGE.createInstance(2), game);
|
spell.addCounters(CounterType.CHARGE.createInstance(2), game);
|
||||||
return spell.chooseNewTargets(game, source.getControllerId(), false, false);
|
return spell.chooseNewTargets(game, source.getControllerId(), false, false, null);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -89,27 +89,26 @@ class CurseOfInertiaTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
public CurseOfInertiaTriggeredAbility() {
|
public CurseOfInertiaTriggeredAbility() {
|
||||||
super(Zone.BATTLEFIELD, new CurseOfInertiaTapOrUntapTargetEffect(), false);
|
super(Zone.BATTLEFIELD, new CurseOfInertiaTapOrUntapTargetEffect(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CurseOfInertiaTriggeredAbility(Effect effect, boolean optional, String text) {
|
|
||||||
super(Zone.BATTLEFIELD, effect, optional);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CurseOfInertiaTriggeredAbility(final CurseOfInertiaTriggeredAbility ability) {
|
public CurseOfInertiaTriggeredAbility(final CurseOfInertiaTriggeredAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkEventType(GameEvent event, Game game) {
|
||||||
|
return event.getType().equals(EventType.DECLARED_ATTACKERS);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
if (event.getType().equals(EventType.DECLARED_ATTACKERS)) {
|
Permanent enchantment = game.getPermanent(this.getSourceId());
|
||||||
Permanent enchantment = game.getPermanent(this.getSourceId());
|
if (enchantment != null
|
||||||
if (enchantment != null
|
&& enchantment.getAttachedTo() != null
|
||||||
&& enchantment.getAttachedTo() != null
|
&& game.getCombat().getPlayerDefenders(game).contains(enchantment.getAttachedTo())) {
|
||||||
&& game.getCombat().getPlayerDefenders(game).contains(enchantment.getAttachedTo())) {
|
TargetPermanent target = new TargetPermanent();
|
||||||
for (Effect effect: this.getEffects()) {
|
target.setTargetController(game.getCombat().getAttackerId());
|
||||||
effect.setTargetPointer(new FixedTarget(game.getCombat().getAttackerId()));
|
addTarget(target);
|
||||||
}
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -138,24 +137,20 @@ class CurseOfInertiaTapOrUntapTargetEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player player = game.getPlayer(this.getTargetPointer().getFirst(game, source));
|
Player player = game.getPlayer(source.getTargets().get(0).getTargetController());
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
Target target = new TargetPermanent();
|
Permanent targetPermanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||||
if (target.canChoose(source.getSourceId(), player.getId(), game)
|
if (targetPermanent != null) {
|
||||||
&& player.choose(outcome, target, source.getSourceId(), game)) {
|
if (targetPermanent.isTapped()) {
|
||||||
Permanent targetPermanent = game.getPermanent(target.getFirstTarget());
|
if (player.chooseUse(Outcome.Untap, "Untap that permanent?", game)) {
|
||||||
if (targetPermanent != null) {
|
targetPermanent.untap(game);
|
||||||
if (targetPermanent.isTapped()) {
|
}
|
||||||
if (player.chooseUse(Outcome.Untap, "Untap that permanent?", game)) {
|
} else {
|
||||||
targetPermanent.untap(game);
|
if (player.chooseUse(Outcome.Tap, "Tap that permanent?", game)) {
|
||||||
}
|
targetPermanent.tap(game);
|
||||||
} else {
|
|
||||||
if (player.chooseUse(Outcome.Tap, "Tap that permanent?", game)) {
|
|
||||||
targetPermanent.tap(game);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,6 @@ public class DungeonGeists extends CardImpl {
|
||||||
this.expansionSetCode = "DKA";
|
this.expansionSetCode = "DKA";
|
||||||
this.subtype.add("Spirit");
|
this.subtype.add("Spirit");
|
||||||
|
|
||||||
this.color.setBlue(true);
|
|
||||||
this.power = new MageInt(3);
|
this.power = new MageInt(3);
|
||||||
this.toughness = new MageInt(3);
|
this.toughness = new MageInt(3);
|
||||||
|
|
||||||
|
|
@ -112,40 +111,52 @@ class DungeonGeistsEffect extends ContinuousRuleModifyingEffectImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean checksEventType(GameEvent event, Game game) {
|
||||||
return false;
|
return event.getType() == GameEvent.EventType.UNTAP || event.getType() == GameEvent.EventType.ZONE_CHANGE || event.getType() == GameEvent.EventType.LOST_CONTROL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||||
// Source must be on the battlefield (it's neccessary to check here because if as response to the enter
|
// Source must be on the battlefield (it's neccessary to check here because if as response to the enter
|
||||||
// the battlefield triggered ability the source dies (or will be exiled), then the ZONE_CHANGE or LOST_CONTROL
|
// the battlefield triggered ability the source dies (or will be exiled), then the ZONE_CHANGE or LOST_CONTROL
|
||||||
// event will happen before this effect is applied ever)
|
// event will happen before this effect is applied ever)
|
||||||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
Permanent sourcePermanent = (Permanent) source.getSourceObjectIfItStillExists(game);
|
||||||
if (sourcePermanent == null || !sourcePermanent.getControllerId().equals(source.getControllerId())) {
|
if (sourcePermanent == null || !sourcePermanent.getControllerId().equals(source.getControllerId())) {
|
||||||
this.used = true;
|
discard();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (event.getType() == GameEvent.EventType.LOST_CONTROL) {
|
switch(event.getType()) {
|
||||||
if (event.getTargetId().equals(source.getSourceId())) {
|
case ZONE_CHANGE:
|
||||||
discard();
|
// end effect if source does a zone move
|
||||||
return false;
|
if (event.getTargetId().equals(source.getSourceId())) {
|
||||||
}
|
ZoneChangeEvent zEvent = (ZoneChangeEvent)event;
|
||||||
|
if (zEvent.getFromZone() == Zone.BATTLEFIELD) {
|
||||||
|
discard();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case UNTAP:
|
||||||
|
// prevent to untap the target creature
|
||||||
|
if (game.getTurn().getStepType() == PhaseStep.UNTAP && event.getTargetId().equals(targetPointer.getFirst(game, source))) {
|
||||||
|
Permanent targetCreature = game.getPermanent(targetPointer.getFirst(game, source));
|
||||||
|
if (targetCreature != null) {
|
||||||
|
return targetCreature.getControllerId().equals(game.getActivePlayerId());
|
||||||
|
} else {
|
||||||
|
discard();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LOST_CONTROL:
|
||||||
|
// end effect if source control is changed
|
||||||
|
if (event.getTargetId().equals(source.getSourceId())) {
|
||||||
|
discard();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (event.getType() == GameEvent.EventType.ZONE_CHANGE && event.getTargetId().equals(source.getSourceId())) {
|
|
||||||
ZoneChangeEvent zEvent = (ZoneChangeEvent)event;
|
|
||||||
if (zEvent.getFromZone() == Zone.BATTLEFIELD) {
|
|
||||||
discard();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (game.getTurn().getStepType() == PhaseStep.UNTAP && event.getType() == GameEvent.EventType.UNTAP) {
|
|
||||||
if (event.getTargetId().equals(targetPointer.getFirst(game, source))) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,13 +86,14 @@ class CloneLegionEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source));
|
Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source));
|
||||||
if (targetPlayer != null) {
|
if (controller != null && targetPlayer != null) {
|
||||||
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), targetPlayer.getId(), game)) {
|
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), targetPlayer.getId(), game)) {
|
||||||
if (permanent != null) {
|
if (permanent != null) {
|
||||||
EmptyToken token = new EmptyToken();
|
EmptyToken token = new EmptyToken();
|
||||||
CardUtil.copyTo(token).from(permanent);
|
CardUtil.copyTo(token).from(permanent);
|
||||||
token.putOntoBattlefield(1, game, source.getSourceId(), targetPlayer.getId());
|
token.putOntoBattlefield(1, game, source.getSourceId(), controller.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,6 @@ import mage.constants.TargetController;
|
||||||
import mage.constants.WatcherScope;
|
import mage.constants.WatcherScope;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
import static mage.filter.predicate.permanent.ControllerControlsIslandPredicate.filter;
|
|
||||||
import mage.filter.predicate.permanent.ControllerPredicate;
|
import mage.filter.predicate.permanent.ControllerPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
|
|
@ -157,7 +156,8 @@ class IcefallRegentEffect extends ContinuousRuleModifyingEffectImpl {
|
||||||
|
|
||||||
if (game.getTurn().getStepType() == PhaseStep.UNTAP && event.getType() == GameEvent.EventType.UNTAP) {
|
if (game.getTurn().getStepType() == PhaseStep.UNTAP && event.getType() == GameEvent.EventType.UNTAP) {
|
||||||
if (event.getTargetId().equals(targetPointer.getFirst(game, source))) {
|
if (event.getTargetId().equals(targetPointer.getFirst(game, source))) {
|
||||||
return true;
|
Permanent targetCreature = game.getPermanent(targetPointer.getFirst(game, source));
|
||||||
|
return targetCreature != null && game.getActivePlayerId().equals(targetCreature.getControllerId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,6 @@ import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.AttachEffect;
|
import mage.abilities.effects.common.AttachEffect;
|
||||||
import mage.abilities.effects.common.ExileTargetEffect;
|
import mage.abilities.effects.common.ExileTargetEffect;
|
||||||
import mage.abilities.keyword.EnchantAbility;
|
import mage.abilities.keyword.EnchantAbility;
|
||||||
import mage.cards.Card;
|
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.constants.AttachmentType;
|
import mage.constants.AttachmentType;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
|
|
@ -106,22 +105,19 @@ class MirrorMockeryEffect extends OneShotEffect {
|
||||||
}
|
}
|
||||||
Permanent enchanted = game.getPermanent(enchantment.getAttachedTo());
|
Permanent enchanted = game.getPermanent(enchantment.getAttachedTo());
|
||||||
if (enchanted != null) {
|
if (enchanted != null) {
|
||||||
Card card = game.getCard(enchanted.getId());
|
EmptyToken token = new EmptyToken();
|
||||||
if (card != null) {
|
CardUtil.copyTo(token).from(enchanted);
|
||||||
EmptyToken token = new EmptyToken();
|
|
||||||
CardUtil.copyTo(token).from(card);
|
|
||||||
|
|
||||||
token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
|
token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
|
||||||
|
|
||||||
ExileTargetEffect exileEffect = new ExileTargetEffect();
|
ExileTargetEffect exileEffect = new ExileTargetEffect();
|
||||||
exileEffect.setTargetPointer(new FixedTarget(token.getLastAddedToken()));
|
exileEffect.setTargetPointer(new FixedTarget(token.getLastAddedToken()));
|
||||||
DelayedTriggeredAbility delayedAbility = new AtTheEndOfCombatDelayedTriggeredAbility(exileEffect);
|
DelayedTriggeredAbility delayedAbility = new AtTheEndOfCombatDelayedTriggeredAbility(exileEffect);
|
||||||
delayedAbility.setSourceId(source.getSourceId());
|
delayedAbility.setSourceId(source.getSourceId());
|
||||||
delayedAbility.setControllerId(source.getControllerId());
|
delayedAbility.setControllerId(source.getControllerId());
|
||||||
delayedAbility.setSourceObject(source.getSourceObject(game), game);
|
delayedAbility.setSourceObject(source.getSourceObject(game), game);
|
||||||
game.addDelayedTriggeredAbility(delayedAbility);
|
game.addDelayedTriggeredAbility(delayedAbility);
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
54
Mage.Sets/src/mage/sets/exodus/Pandemonium.java
Normal file
54
Mage.Sets/src/mage/sets/exodus/Pandemonium.java
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* 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.sets.exodus;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.constants.Rarity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
public class Pandemonium extends mage.sets.timeshifted.Pandemonium {
|
||||||
|
|
||||||
|
public Pandemonium(UUID ownerId) {
|
||||||
|
super(ownerId);
|
||||||
|
this.cardNumber = 93;
|
||||||
|
this.expansionSetCode = "EXO";
|
||||||
|
this.rarity = Rarity.RARE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pandemonium(final Pandemonium card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Pandemonium copy() {
|
||||||
|
return new Pandemonium(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -48,14 +48,12 @@ import mage.constants.Layer;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.constants.SubLayer;
|
import mage.constants.SubLayer;
|
||||||
import mage.constants.TargetController;
|
|
||||||
import mage.constants.WatcherScope;
|
import mage.constants.WatcherScope;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.filter.FilterCard;
|
import mage.filter.FilterCard;
|
||||||
import mage.filter.FilterObject;
|
import mage.filter.FilterObject;
|
||||||
import mage.filter.predicate.Predicates;
|
import mage.filter.predicate.Predicates;
|
||||||
import mage.filter.predicate.mageobject.CardTypePredicate;
|
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||||
import mage.filter.predicate.permanent.ControllerPredicate;
|
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.events.ZoneChangeEvent;
|
import mage.game.events.ZoneChangeEvent;
|
||||||
|
|
@ -230,7 +228,10 @@ class SoulfireGrandMasterCastFromHandReplacementEffect extends ReplacementEffect
|
||||||
if (zEvent.getFromZone() == Zone.STACK &&
|
if (zEvent.getFromZone() == Zone.STACK &&
|
||||||
zEvent.getToZone() == Zone.GRAVEYARD &&
|
zEvent.getToZone() == Zone.GRAVEYARD &&
|
||||||
event.getTargetId().equals(spellId)) {
|
event.getTargetId().equals(spellId)) {
|
||||||
return true;
|
Spell spell = game.getStack().getSpell(spellId);
|
||||||
|
if (spell != null && !spell.isCountered()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,6 @@ import mage.constants.Duration;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.combat.CombatGroup;
|
import mage.game.combat.CombatGroup;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
|
|
@ -71,7 +70,7 @@ import mage.watchers.common.BlockedAttackerWatcher;
|
||||||
public class TheWretched extends CardImpl {
|
public class TheWretched extends CardImpl {
|
||||||
|
|
||||||
public TheWretched(UUID ownerId) {
|
public TheWretched(UUID ownerId) {
|
||||||
super(ownerId, 239, "The Wretched", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{B}{B}");
|
super(ownerId, 59, "The Wretched", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{B}{B}");
|
||||||
this.expansionSetCode = "5ED";
|
this.expansionSetCode = "5ED";
|
||||||
this.subtype.add("Demon");
|
this.subtype.add("Demon");
|
||||||
this.power = new MageInt(2);
|
this.power = new MageInt(2);
|
||||||
|
|
@ -160,19 +159,6 @@ class TheWretchedEffect extends OneShotEffect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
// BlockedAttackerWatcher watcher = (BlockedAttackerWatcher) game.getState().getWatchers().get("BlockedAttackerWatcher");
|
|
||||||
// if (watcher != null) {
|
|
||||||
// for (Permanent creature : game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), game)) {
|
|
||||||
// if (watcher.creatureHasBlockedAttacker(theWretched, creature, game)
|
|
||||||
// && !creature.isRemovedFromCombat()) {
|
|
||||||
// ContinuousEffect effect = new ConditionalContinuousEffect(new GainControlTargetEffect(Duration.Custom, source.getControllerId()), new SourceOnBattlefieldControlUnchangedCondition(), "test");
|
|
||||||
// effect.setTargetPointer(new FixedTarget(creature.getId()));
|
|
||||||
// game.addEffect(effect, source);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -1,119 +1,117 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification, are
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
* permitted provided that the following conditions are met:
|
* permitted provided that the following conditions are met:
|
||||||
*
|
*
|
||||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
* conditions and the following disclaimer.
|
* conditions and the following disclaimer.
|
||||||
*
|
*
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
* 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
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
* provided with the distribution.
|
* provided with the distribution.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
* 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
|
* 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
|
* 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
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 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
|
* 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
|
* 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
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* The views and conclusions contained in the software and documentation are those of the
|
* 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
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
* or implied, of BetaSteward_at_googlemail.com.
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
*/
|
*/
|
||||||
package mage.sets.gatecrash;
|
package mage.sets.gatecrash;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.permanent.token.Token;
|
import mage.game.permanent.token.Token;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author LevelX2
|
* @author LevelX2
|
||||||
*/
|
*/
|
||||||
public class MimingSlime extends CardImpl {
|
public class MimingSlime extends CardImpl {
|
||||||
|
|
||||||
public MimingSlime(UUID ownerId) {
|
public MimingSlime(UUID ownerId) {
|
||||||
super(ownerId, 126, "Miming Slime", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{2}{G}");
|
super(ownerId, 126, "Miming Slime", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{2}{G}");
|
||||||
this.expansionSetCode = "GTC";
|
this.expansionSetCode = "GTC";
|
||||||
|
|
||||||
this.color.setGreen(true);
|
// Put an X/X green Ooze creature token onto the battlefield, where X is the greatest power among creatures you control.
|
||||||
|
this.getSpellAbility().addEffect(new MimingSlimeEffect());
|
||||||
// Put an X/X green Ooze creature token onto the battlefield, where X is the greatest power among creatures you control.
|
}
|
||||||
this.getSpellAbility().addEffect(new MimingSlimeEffect());
|
|
||||||
}
|
public MimingSlime(final MimingSlime card) {
|
||||||
|
super(card);
|
||||||
public MimingSlime(final MimingSlime card) {
|
}
|
||||||
super(card);
|
|
||||||
}
|
@Override
|
||||||
|
public MimingSlime copy() {
|
||||||
@Override
|
return new MimingSlime(this);
|
||||||
public MimingSlime copy() {
|
}
|
||||||
return new MimingSlime(this);
|
}
|
||||||
}
|
|
||||||
}
|
class MimingSlimeEffect extends OneShotEffect {
|
||||||
|
|
||||||
class MimingSlimeEffect extends OneShotEffect {
|
public MimingSlimeEffect() {
|
||||||
|
super(Outcome.PutCreatureInPlay);
|
||||||
public MimingSlimeEffect() {
|
staticText = "Put an X/X green Ooze creature token onto the battlefield, where X is the greatest power among creatures you control";
|
||||||
super(Outcome.PutCreatureInPlay);
|
}
|
||||||
staticText = "Put an X/X green Ooze creature token onto the battlefield, where X is the greatest power among creatures you control";
|
|
||||||
}
|
public MimingSlimeEffect(final MimingSlimeEffect effect) {
|
||||||
|
super(effect);
|
||||||
public MimingSlimeEffect(final MimingSlimeEffect effect) {
|
}
|
||||||
super(effect);
|
|
||||||
}
|
@Override
|
||||||
|
public MimingSlimeEffect copy() {
|
||||||
@Override
|
return new MimingSlimeEffect(this);
|
||||||
public MimingSlimeEffect copy() {
|
}
|
||||||
return new MimingSlimeEffect(this);
|
|
||||||
}
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
@Override
|
Player player = game.getPlayer(source.getControllerId());
|
||||||
public boolean apply(Game game, Ability source) {
|
if (player != null) {
|
||||||
Player player = game.getPlayer(source.getControllerId());
|
List<Permanent> creatures = game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), player.getId(), game);
|
||||||
if (player != null) {
|
int amount = 0;
|
||||||
List<Permanent> creatures = game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), player.getId(), game);
|
for (Permanent creature : creatures) {
|
||||||
int amount = 0;
|
int power = creature.getPower().getValue();
|
||||||
for (Permanent creature : creatures) {
|
if (amount < power) {
|
||||||
int power = creature.getPower().getValue();
|
amount = power;
|
||||||
if (amount < power) {
|
}
|
||||||
amount = power;
|
}
|
||||||
}
|
OozeToken oozeToken = new OozeToken();
|
||||||
}
|
oozeToken.getPower().initValue(amount);
|
||||||
OozeToken oozeToken = new OozeToken();
|
oozeToken.getToughness().initValue(amount);
|
||||||
oozeToken.getPower().initValue(amount);
|
oozeToken.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
|
||||||
oozeToken.getToughness().initValue(amount);
|
return true;
|
||||||
oozeToken.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
|
}
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
}
|
class OozeToken extends Token {
|
||||||
|
public OozeToken() {
|
||||||
class OozeToken extends Token {
|
super("Ooze", "X/X green Ooze creature token");
|
||||||
public OozeToken() {
|
cardType.add(CardType.CREATURE);
|
||||||
super("Ooze", "X/X green Ooze creature token");
|
subtype.add("Ooze");
|
||||||
cardType.add(CardType.CREATURE);
|
color.setGreen(true);
|
||||||
subtype.add("Ooze");
|
power = new MageInt(0);
|
||||||
color.setGreen(true);
|
toughness = new MageInt(0);
|
||||||
power = new MageInt(0);
|
setOriginalExpansionSetCode("RTR");
|
||||||
toughness = new MageInt(0);
|
}
|
||||||
setOriginalExpansionSetCode("RTR");
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,111 +1,109 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification, are
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
* permitted provided that the following conditions are met:
|
* permitted provided that the following conditions are met:
|
||||||
*
|
*
|
||||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
* conditions and the following disclaimer.
|
* conditions and the following disclaimer.
|
||||||
*
|
*
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
* 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
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
* provided with the distribution.
|
* provided with the distribution.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
* 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
|
* 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
|
* 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
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 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
|
* 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
|
* 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
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* The views and conclusions contained in the software and documentation are those of the
|
* 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
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
* or implied, of BetaSteward_at_googlemail.com.
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
*/
|
*/
|
||||||
package mage.sets.gatecrash;
|
package mage.sets.gatecrash;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.common.RemoveVariableCountersTargetCost;
|
import mage.abilities.costs.common.RemoveVariableCountersTargetCost;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.counters.CounterType;
|
import mage.counters.CounterType;
|
||||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.token.Token;
|
import mage.game.permanent.token.Token;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author LevelX2
|
* @author LevelX2
|
||||||
*/
|
*/
|
||||||
public class OozeFlux extends CardImpl {
|
public class OozeFlux extends CardImpl {
|
||||||
|
|
||||||
public OozeFlux(UUID ownerId) {
|
public OozeFlux(UUID ownerId) {
|
||||||
super(ownerId, 128, "Ooze Flux", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}");
|
super(ownerId, 128, "Ooze Flux", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}");
|
||||||
this.expansionSetCode = "GTC";
|
this.expansionSetCode = "GTC";
|
||||||
|
|
||||||
this.color.setGreen(true);
|
// {1}{G}, Remove one or more +1/+1 counters from among creatures you control: Put an X/X green Ooze creature token onto the battlefield, where X is the number of +1/+1 counters removed this way.
|
||||||
|
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new OozeFluxCreateTokenEffect(new OozeToken()),new ManaCostsImpl("{1}{G}"));
|
||||||
// {1}{G}, Remove one or more +1/+1 counters from among creatures you control: Put an X/X green Ooze creature token onto the battlefield, where X is the number of +1/+1 counters removed this way.
|
ability.addCost(new RemoveVariableCountersTargetCost(new FilterControlledCreaturePermanent("creatures you control"), CounterType.P1P1, "one or more", 1));
|
||||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new OozeFluxCreateTokenEffect(new OozeToken()),new ManaCostsImpl("{1}{G}"));
|
this.addAbility(ability);
|
||||||
ability.addCost(new RemoveVariableCountersTargetCost(new FilterControlledCreaturePermanent("creatures you control"), CounterType.P1P1, "one or more", 1));
|
}
|
||||||
this.addAbility(ability);
|
|
||||||
}
|
public OozeFlux(final OozeFlux card) {
|
||||||
|
super(card);
|
||||||
public OozeFlux(final OozeFlux card) {
|
}
|
||||||
super(card);
|
|
||||||
}
|
@Override
|
||||||
|
public OozeFlux copy() {
|
||||||
@Override
|
return new OozeFlux(this);
|
||||||
public OozeFlux copy() {
|
}
|
||||||
return new OozeFlux(this);
|
}
|
||||||
}
|
|
||||||
}
|
class OozeFluxCreateTokenEffect extends OneShotEffect {
|
||||||
|
|
||||||
class OozeFluxCreateTokenEffect extends OneShotEffect {
|
private final Token token;
|
||||||
|
|
||||||
private Token token;
|
public OozeFluxCreateTokenEffect(Token token) {
|
||||||
|
super(Outcome.PutCreatureInPlay);
|
||||||
public OozeFluxCreateTokenEffect(Token token) {
|
this.token = token;
|
||||||
super(Outcome.PutCreatureInPlay);
|
staticText = "Put an X/X green Ooze creature token onto the battlefield, where X is the number of +1/+1 counters removed this way";
|
||||||
this.token = token;
|
}
|
||||||
staticText = "Put an X/X green Ooze creature token onto the battlefield, where X is the number of +1/+1 counters removed this way";
|
|
||||||
}
|
public OozeFluxCreateTokenEffect(final OozeFluxCreateTokenEffect effect) {
|
||||||
|
super(effect);
|
||||||
public OozeFluxCreateTokenEffect(final OozeFluxCreateTokenEffect effect) {
|
this.token = effect.token.copy();
|
||||||
super(effect);
|
}
|
||||||
this.token = effect.token.copy();
|
|
||||||
}
|
@Override
|
||||||
|
public OozeFluxCreateTokenEffect copy() {
|
||||||
@Override
|
return new OozeFluxCreateTokenEffect(this);
|
||||||
public OozeFluxCreateTokenEffect copy() {
|
}
|
||||||
return new OozeFluxCreateTokenEffect(this);
|
|
||||||
}
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
@Override
|
int xValue = 0;
|
||||||
public boolean apply(Game game, Ability source) {
|
for (Cost cost : source.getCosts()) {
|
||||||
int xValue = 0;
|
if (cost instanceof RemoveVariableCountersTargetCost) {
|
||||||
for (Cost cost : source.getCosts()) {
|
xValue = ((RemoveVariableCountersTargetCost) cost).getAmount();
|
||||||
if (cost instanceof RemoveVariableCountersTargetCost) {
|
break;
|
||||||
xValue = ((RemoveVariableCountersTargetCost) cost).getAmount();
|
}
|
||||||
break;
|
}
|
||||||
}
|
Token tokenCopy = token.copy();
|
||||||
}
|
tokenCopy.getAbilities().newId();
|
||||||
Token tokenCopy = token.copy();
|
tokenCopy.getPower().initValue(xValue);
|
||||||
tokenCopy.getAbilities().newId();
|
tokenCopy.getToughness().initValue(xValue);
|
||||||
tokenCopy.getPower().initValue(xValue);
|
tokenCopy.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
|
||||||
tokenCopy.getToughness().initValue(xValue);
|
return true;
|
||||||
tokenCopy.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
|
}
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ class QuicksilverDragonEffect extends OneShotEffect {
|
||||||
numTargets += target.getTargets().size();
|
numTargets += target.getTargets().size();
|
||||||
}
|
}
|
||||||
if (numTargets == 1 && spell.getSpellAbility().getTargets().getFirstTarget().equals(source.getSourceId())) {
|
if (numTargets == 1 && spell.getSpellAbility().getTargets().getFirstTarget().equals(source.getSourceId())) {
|
||||||
spell.chooseNewTargets(game, source.getControllerId(), true, false);
|
spell.chooseNewTargets(game, source.getControllerId(), true, false, null);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ import mage.filter.predicate.permanent.ControllerPredicate;
|
||||||
import mage.game.ExileZone;
|
import mage.game.ExileZone;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.game.permanent.PermanentToken;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.util.CardUtil;
|
import mage.util.CardUtil;
|
||||||
|
|
||||||
|
|
@ -143,8 +144,10 @@ class WorldgorgerDragonLeavesEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller != null) {
|
MageObject sourceObject = source.getSourceObject(game);
|
||||||
ExileZone exile = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter() -1));
|
if (controller != null && sourceObject != null) {
|
||||||
|
int zoneChangeCounter = (sourceObject instanceof PermanentToken) ? source.getSourceObjectZoneChangeCounter() : source.getSourceObjectZoneChangeCounter() -1;
|
||||||
|
ExileZone exile = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source.getSourceId(), zoneChangeCounter));
|
||||||
if (exile != null) {
|
if (exile != null) {
|
||||||
exile = exile.copy();
|
exile = exile.copy();
|
||||||
for (UUID cardId : exile) {
|
for (UUID cardId : exile) {
|
||||||
|
|
|
||||||
|
|
@ -86,24 +86,27 @@ class TheAbyssTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
public TheAbyssTriggeredAbility copy() {
|
public TheAbyssTriggeredAbility copy() {
|
||||||
return new TheAbyssTriggeredAbility(this);
|
return new TheAbyssTriggeredAbility(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkEventType(GameEvent event, Game game) {
|
||||||
|
return event.getType() == GameEvent.EventType.UPKEEP_STEP_PRE;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
if (event.getType() == GameEvent.EventType.UPKEEP_STEP_PRE) {
|
Player player = game.getPlayer(event.getPlayerId());
|
||||||
Player player = game.getPlayer(event.getPlayerId());
|
if (player != null) {
|
||||||
if (player != null) {
|
FilterCreaturePermanent filter = new FilterCreaturePermanent("nonartifact creature you control");
|
||||||
FilterCreaturePermanent filter = new FilterCreaturePermanent("nonartifact creature you control");
|
filter.add(Predicates.not(new CardTypePredicate(CardType.ARTIFACT)));
|
||||||
filter.add(Predicates.not(new CardTypePredicate(CardType.ARTIFACT)));
|
filter.add(new ControllerIdPredicate(player.getId()));
|
||||||
filter.add(new ControllerIdPredicate(player.getId()));
|
Target target = new TargetCreaturePermanent(filter);
|
||||||
Target target = new TargetCreaturePermanent(filter);
|
if (target.canChoose(this.getSourceId(), this.getControllerId(), game) && player.chooseTarget(Outcome.DestroyPermanent, target, this, game)) {
|
||||||
if (target.canChoose(this.getSourceId(), this.getControllerId(), game) && player.chooseTarget(Outcome.DestroyPermanent, target, this, game)) {
|
for (Effect effect: this.getEffects()) {
|
||||||
for (Effect effect: this.getEffects()) {
|
if (effect instanceof DestroyTargetEffect) {
|
||||||
if (effect instanceof DestroyTargetEffect) {
|
effect.setTargetPointer(new FixedTarget(target.getFirstTarget()));
|
||||||
effect.setTargetPointer(new FixedTarget(target.getFirstTarget()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -30,10 +30,12 @@ package mage.sets.limitedalpha;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.cards.Card;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
|
import mage.constants.Zone;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
|
||||||
|
|
@ -81,14 +83,23 @@ class TimetwisterEffect extends OneShotEffect {
|
||||||
for (UUID playerId: sourcePlayer.getInRange()) {
|
for (UUID playerId: sourcePlayer.getInRange()) {
|
||||||
Player player = game.getPlayer(playerId);
|
Player player = game.getPlayer(playerId);
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
player.getLibrary().addAll(player.getHand().getCards(game), game);
|
for (Card card: player.getHand().getCards(game)) {
|
||||||
player.getLibrary().addAll(player.getGraveyard().getCards(game), game);
|
card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
|
||||||
|
}
|
||||||
|
for (Card card: player.getGraveyard().getCards(game)) {
|
||||||
|
card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
|
||||||
|
}
|
||||||
player.shuffleLibrary(game);
|
player.shuffleLibrary(game);
|
||||||
player.getHand().clear();
|
|
||||||
player.getGraveyard().clear();
|
|
||||||
player.drawCards(7, game);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
game.getState().handleSimultaneousEvent(game); // needed here so state based triggered effects
|
||||||
|
for (UUID playerId: sourcePlayer.getInRange()) {
|
||||||
|
Player player = game.getPlayer(playerId);
|
||||||
|
if (player != null) {
|
||||||
|
player.drawCards(7, game);
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
65
Mage.Sets/src/mage/sets/lorwyn/JudgeOfCurrents.java
Normal file
65
Mage.Sets/src/mage/sets/lorwyn/JudgeOfCurrents.java
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* 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.sets.lorwyn;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.common.BecomesTappedCreatureControlledTriggeredAbility;
|
||||||
|
import mage.abilities.effects.common.GainLifeEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Rarity;
|
||||||
|
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
public class JudgeOfCurrents extends CardImpl {
|
||||||
|
|
||||||
|
public JudgeOfCurrents(UUID ownerId) {
|
||||||
|
super(ownerId, 22, "Judge of Currents", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{W}");
|
||||||
|
this.expansionSetCode = "LRW";
|
||||||
|
this.subtype.add("Merfolk");
|
||||||
|
this.subtype.add("Wizard");
|
||||||
|
this.power = new MageInt(1);
|
||||||
|
this.toughness = new MageInt(1);
|
||||||
|
|
||||||
|
// Whenever a Merfolk you control becomes tapped, you may gain 1 life.
|
||||||
|
this.addAbility(new BecomesTappedCreatureControlledTriggeredAbility(new GainLifeEffect(1), true, new FilterControlledCreaturePermanent("Merfolk", "a Merfolk you control")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public JudgeOfCurrents(final JudgeOfCurrents card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JudgeOfCurrents copy() {
|
||||||
|
return new JudgeOfCurrents(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -106,30 +106,24 @@ class GrandAbolisherEffect extends ContinuousRuleModifyingEffectImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
public boolean checksEventType(GameEvent event, Game game) {
|
||||||
boolean spell = event.getType() == GameEvent.EventType.CAST_SPELL;
|
return event.getType() == GameEvent.EventType.CAST_SPELL || event.getType() == GameEvent.EventType.ACTIVATE_ABILITY;
|
||||||
boolean activated = event.getType() == GameEvent.EventType.ACTIVATE_ABILITY;
|
|
||||||
if ((spell || activated) && game.getActivePlayerId().equals(source.getControllerId()) && game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) {
|
|
||||||
|
|
||||||
if (spell) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check source of activated ability
|
|
||||||
Permanent permanent = game.getPermanent(event.getSourceId());
|
|
||||||
if (permanent != null) {
|
|
||||||
return permanent.getCardType().contains(CardType.ARTIFACT) || permanent.getCardType().contains(CardType.CREATURE)
|
|
||||||
|| permanent.getCardType().contains(CardType.ENCHANTMENT);
|
|
||||||
} else {
|
|
||||||
MageObject object = game.getObject(event.getSourceId());
|
|
||||||
if (object != null) {
|
|
||||||
return object.getCardType().contains(CardType.ARTIFACT) || object.getCardType().contains(CardType.CREATURE)
|
|
||||||
|| object.getCardType().contains(CardType.ENCHANTMENT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||||
|
if (game.getActivePlayerId().equals(source.getControllerId()) && game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) {
|
||||||
|
switch(event.getType()) {
|
||||||
|
case CAST_SPELL:
|
||||||
|
return true;
|
||||||
|
case ACTIVATE_ABILITY:
|
||||||
|
Permanent permanent = game.getPermanent(event.getSourceId());
|
||||||
|
if (permanent != null) {
|
||||||
|
return permanent.getCardType().contains(CardType.ARTIFACT) || permanent.getCardType().contains(CardType.CREATURE)
|
||||||
|
|| permanent.getCardType().contains(CardType.ENCHANTMENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ class DivertEffect extends OneShotEffect {
|
||||||
cost.clearPaid();
|
cost.clearPaid();
|
||||||
if (!cost.pay(source, game, spell.getControllerId(),
|
if (!cost.pay(source, game, spell.getControllerId(),
|
||||||
spell.getControllerId(), false)) {
|
spell.getControllerId(), false)) {
|
||||||
return spell.chooseNewTargets(game, source.getControllerId(), true, true);
|
return spell.chooseNewTargets(game, source.getControllerId(), true, true, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,9 @@ import mage.cards.CardImpl;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
|
import mage.constants.SetTargetPointer;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.filter.FilterSpell;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.common.TargetCardInHand;
|
import mage.target.common.TargetCardInHand;
|
||||||
|
|
@ -52,7 +55,7 @@ public class PainfulQuandary extends CardImpl {
|
||||||
this.expansionSetCode = "SOM";
|
this.expansionSetCode = "SOM";
|
||||||
|
|
||||||
// Whenever an opponent casts a spell, that player loses 5 life unless he or she discards a card.
|
// Whenever an opponent casts a spell, that player loses 5 life unless he or she discards a card.
|
||||||
this.addAbility(new SpellCastOpponentTriggeredAbility(new PainfulQuandryEffect(), false));
|
this.addAbility(new SpellCastOpponentTriggeredAbility(Zone.BATTLEFIELD, new PainfulQuandryEffect(), new FilterSpell(), false, SetTargetPointer.PLAYER));
|
||||||
}
|
}
|
||||||
|
|
||||||
public PainfulQuandary(final PainfulQuandary card) {
|
public PainfulQuandary(final PainfulQuandary card) {
|
||||||
|
|
|
||||||
54
Mage.Sets/src/mage/sets/stronghold/Cannibalize.java
Normal file
54
Mage.Sets/src/mage/sets/stronghold/Cannibalize.java
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* 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.sets.stronghold;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.constants.Rarity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
public class Cannibalize extends mage.sets.tempestremastered.Cannibalize {
|
||||||
|
|
||||||
|
public Cannibalize(UUID ownerId) {
|
||||||
|
super(ownerId);
|
||||||
|
this.cardNumber = 3;
|
||||||
|
this.expansionSetCode = "STH";
|
||||||
|
this.rarity = Rarity.COMMON;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cannibalize(final Cannibalize card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Cannibalize copy() {
|
||||||
|
return new Cannibalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
52
Mage.Sets/src/mage/sets/stronghold/SilverWyvern.java
Normal file
52
Mage.Sets/src/mage/sets/stronghold/SilverWyvern.java
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* 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.sets.stronghold;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
public class SilverWyvern extends mage.sets.tempestremastered.SilverWyvern {
|
||||||
|
|
||||||
|
public SilverWyvern(UUID ownerId) {
|
||||||
|
super(ownerId);
|
||||||
|
this.cardNumber = 43;
|
||||||
|
this.expansionSetCode = "STH";
|
||||||
|
}
|
||||||
|
|
||||||
|
public SilverWyvern(final SilverWyvern card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SilverWyvern copy() {
|
||||||
|
return new SilverWyvern(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
52
Mage.Sets/src/mage/sets/tempest/CoffinQueen.java
Normal file
52
Mage.Sets/src/mage/sets/tempest/CoffinQueen.java
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* 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.sets.tempest;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author anonymous
|
||||||
|
*/
|
||||||
|
public class CoffinQueen extends mage.sets.tempestremastered.CoffinQueen {
|
||||||
|
|
||||||
|
public CoffinQueen(UUID ownerId) {
|
||||||
|
super(ownerId);
|
||||||
|
this.cardNumber = 8;
|
||||||
|
this.expansionSetCode = "TMP";
|
||||||
|
}
|
||||||
|
|
||||||
|
public CoffinQueen(final CoffinQueen card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CoffinQueen copy() {
|
||||||
|
return new CoffinQueen(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
70
Mage.Sets/src/mage/sets/tempest/TrumpetingArmodon.java
Normal file
70
Mage.Sets/src/mage/sets/tempest/TrumpetingArmodon.java
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
* permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
* conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The views and conclusions contained in the software and documentation are those of the
|
||||||
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
|
*/
|
||||||
|
package mage.sets.tempest;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
import mage.abilities.effects.common.combat.MustBeBlockedByTargetSourceEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.Rarity;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Sir-Speshkitty
|
||||||
|
*/
|
||||||
|
public class TrumpetingArmodon extends CardImpl {
|
||||||
|
|
||||||
|
public TrumpetingArmodon(UUID ownerId) {
|
||||||
|
super(ownerId, 156, "Trumpeting Armodon", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{G}");
|
||||||
|
this.expansionSetCode = "TMP";
|
||||||
|
this.subtype.add("Elephant");
|
||||||
|
this.power = new MageInt(3);
|
||||||
|
this.toughness = new MageInt(3);
|
||||||
|
|
||||||
|
// {1}{G}: Target creature blocks Trumpeting Armodon this turn if able.
|
||||||
|
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MustBeBlockedByTargetSourceEffect(), new ManaCostsImpl("{1}{G}"));
|
||||||
|
ability.addTarget(new TargetCreaturePermanent());
|
||||||
|
this.addAbility(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrumpetingArmodon(final TrumpetingArmodon card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TrumpetingArmodon copy() {
|
||||||
|
return new TrumpetingArmodon(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
152
Mage.Sets/src/mage/sets/tempestremastered/Cannibalize.java
Normal file
152
Mage.Sets/src/mage/sets/tempestremastered/Cannibalize.java
Normal file
|
|
@ -0,0 +1,152 @@
|
||||||
|
/*
|
||||||
|
* 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.sets.tempestremastered;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageObject;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.Rarity;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.counters.CounterType;
|
||||||
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.filter.predicate.Predicates;
|
||||||
|
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||||
|
import mage.filter.predicate.permanent.PermanentIdPredicate;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.players.Player;
|
||||||
|
import mage.target.Target;
|
||||||
|
import mage.target.TargetPermanent;
|
||||||
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
public class Cannibalize extends CardImpl {
|
||||||
|
|
||||||
|
public Cannibalize(UUID ownerId) {
|
||||||
|
super(ownerId, 83, "Cannibalize", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{1}{B}");
|
||||||
|
this.expansionSetCode = "TPR";
|
||||||
|
|
||||||
|
// Choose two target creatures controlled by the same player. Exile one of the creatures and put two +1/+1 counters on the other.
|
||||||
|
this.getSpellAbility().addEffect(new CannibalizeEffect());
|
||||||
|
this.getSpellAbility().addTarget(new TargetCreaturePermanentSameController(2,2,new FilterCreaturePermanent(),false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cannibalize(final Cannibalize card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Cannibalize copy() {
|
||||||
|
return new Cannibalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class CannibalizeEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
public CannibalizeEffect() {
|
||||||
|
super(Outcome.Benefit);
|
||||||
|
this.staticText = "Choose two target creatures controlled by the same player. Exile one of the creatures and put two +1/+1 counters on the other";
|
||||||
|
}
|
||||||
|
|
||||||
|
public CannibalizeEffect(final CannibalizeEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CannibalizeEffect copy() {
|
||||||
|
return new CannibalizeEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
MageObject sourceObject = source.getSourceObject(game);
|
||||||
|
if (controller != null && sourceObject != null) {
|
||||||
|
boolean exileDone = false;
|
||||||
|
int count = 0;
|
||||||
|
for(UUID targetId: getTargetPointer().getTargets(game, source)) {
|
||||||
|
Permanent creature = game.getPermanent(targetId);
|
||||||
|
if (creature != null) {
|
||||||
|
if ((count == 0 && controller.chooseUse(Outcome.Exile, "Exile " + creature.getLogName() +"?", game))
|
||||||
|
|| (count == 1 && !exileDone)) {
|
||||||
|
controller.moveCardToExileWithInfo(creature, null, "", source.getSourceId(), game, Zone.BATTLEFIELD, true);
|
||||||
|
exileDone = true;
|
||||||
|
} else {
|
||||||
|
creature.addCounters(CounterType.P1P1.createInstance(2), game);
|
||||||
|
game.informPlayers("Added two +1/+1 counters on " + creature.getLogName());
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TargetCreaturePermanentSameController extends TargetCreaturePermanent {
|
||||||
|
|
||||||
|
public TargetCreaturePermanentSameController(int minNumTargets, int maxNumTargets, FilterCreaturePermanent filter, boolean notTarget) {
|
||||||
|
super(minNumTargets, maxNumTargets, filter, notTarget);
|
||||||
|
this.targetName = filter.getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TargetCreaturePermanentSameController(final TargetCreaturePermanentSameController target) {
|
||||||
|
super(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canTarget(UUID id, Ability source, Game game) {
|
||||||
|
UUID firstTarget = this.getFirstTarget();
|
||||||
|
if (firstTarget != null) {
|
||||||
|
Permanent permanent = game.getPermanent(firstTarget);
|
||||||
|
Permanent targetPermanent = game.getPermanent(id);
|
||||||
|
if (permanent == null || targetPermanent == null
|
||||||
|
|| !permanent.getControllerId().equals(targetPermanent.getOwnerId())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.canTarget(id, source, game);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TargetCreaturePermanentSameController copy() {
|
||||||
|
return new TargetCreaturePermanentSameController(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
153
Mage.Sets/src/mage/sets/tempestremastered/CoffinQueen.java
Normal file
153
Mage.Sets/src/mage/sets/tempestremastered/CoffinQueen.java
Normal file
|
|
@ -0,0 +1,153 @@
|
||||||
|
/*
|
||||||
|
* 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.sets.tempestremastered;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.DelayedTriggeredAbility;
|
||||||
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
|
import mage.abilities.common.SkipUntapOptionalAbility;
|
||||||
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
|
||||||
|
import mage.abilities.effects.common.ExileTargetEffect;
|
||||||
|
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.Rarity;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.filter.common.FilterCreatureCard;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.target.common.TargetCardInGraveyard;
|
||||||
|
import mage.target.targetpointer.FixedTarget;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author anonymous
|
||||||
|
*/
|
||||||
|
public class CoffinQueen extends CardImpl {
|
||||||
|
|
||||||
|
public CoffinQueen(UUID ownerId) {
|
||||||
|
super(ownerId, 87, "Coffin Queen", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{B}");
|
||||||
|
this.expansionSetCode = "TPR";
|
||||||
|
this.subtype.add("Zombie");
|
||||||
|
this.subtype.add("Wizard");
|
||||||
|
this.power = new MageInt(1);
|
||||||
|
this.toughness = new MageInt(1);
|
||||||
|
|
||||||
|
// You may choose not to untap Coffin Queen during your untap step.
|
||||||
|
this.addAbility(new SkipUntapOptionalAbility());
|
||||||
|
|
||||||
|
// {2}{B}, {tap}: Put target creature card from a graveyard onto the battlefield under your control. When Coffin Queen becomes untapped or you lose control of Coffin Queen, exile that creature.
|
||||||
|
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ReturnFromGraveyardToBattlefieldTargetEffect(), new ManaCostsImpl("{2}{B}"));
|
||||||
|
ability.addCost(new TapSourceCost());
|
||||||
|
ability.addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature card from a graveyard")));
|
||||||
|
ability.addEffect(new CoffinQueenCreateDelayedTriggerEffect());
|
||||||
|
this.addAbility(ability);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public CoffinQueen(final CoffinQueen card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CoffinQueen copy() {
|
||||||
|
return new CoffinQueen(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class CoffinQueenCreateDelayedTriggerEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
public CoffinQueenCreateDelayedTriggerEffect() {
|
||||||
|
super(Outcome.Detriment);
|
||||||
|
this.staticText = "When Coffin Queen becomes untapped or you lose control of Coffin Queen, exile that creature";
|
||||||
|
}
|
||||||
|
|
||||||
|
public CoffinQueenCreateDelayedTriggerEffect(final CoffinQueenCreateDelayedTriggerEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CoffinQueenCreateDelayedTriggerEffect copy() {
|
||||||
|
return new CoffinQueenCreateDelayedTriggerEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Permanent controlledCreature = game.getPermanent(source.getFirstTarget());
|
||||||
|
if (controlledCreature != null) {
|
||||||
|
DelayedTriggeredAbility delayedAbility = new CoffinQueenDelayedTriggeredAbility();
|
||||||
|
delayedAbility.getEffects().get(0).setTargetPointer(new FixedTarget(controlledCreature.getId()));
|
||||||
|
delayedAbility.setSourceId(source.getSourceId());
|
||||||
|
delayedAbility.setControllerId(source.getControllerId());
|
||||||
|
delayedAbility.setSourceObject(source.getSourceObject(game), game);
|
||||||
|
delayedAbility.init(game);
|
||||||
|
game.addDelayedTriggeredAbility(delayedAbility);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CoffinQueenDelayedTriggeredAbility extends DelayedTriggeredAbility {
|
||||||
|
|
||||||
|
CoffinQueenDelayedTriggeredAbility() {
|
||||||
|
super(new ExileTargetEffect(), Duration.EndOfGame, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
CoffinQueenDelayedTriggeredAbility(CoffinQueenDelayedTriggeredAbility ability) {
|
||||||
|
super(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
|
if (GameEvent.EventType.LOST_CONTROL.equals(event.getType())
|
||||||
|
&& event.getSourceId().equals(getSourceId())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return GameEvent.EventType.UNTAPPED.equals(event.getType())
|
||||||
|
&& event.getTargetId() != null && event.getTargetId().equals(getSourceId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CoffinQueenDelayedTriggeredAbility copy() {
|
||||||
|
return new CoffinQueenDelayedTriggeredAbility(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRule() {
|
||||||
|
return "When {this} becomes untapped or you lose control of {this}, exile that creature";
|
||||||
|
}
|
||||||
|
}
|
||||||
54
Mage.Sets/src/mage/sets/tempestremastered/Pandemonium.java
Normal file
54
Mage.Sets/src/mage/sets/tempestremastered/Pandemonium.java
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* 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.sets.tempestremastered;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.constants.Rarity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
public class Pandemonium extends mage.sets.timeshifted.Pandemonium {
|
||||||
|
|
||||||
|
public Pandemonium(UUID ownerId) {
|
||||||
|
super(ownerId);
|
||||||
|
this.cardNumber = 149;
|
||||||
|
this.expansionSetCode = "TPR";
|
||||||
|
this.rarity = Rarity.RARE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pandemonium(final Pandemonium card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Pandemonium copy() {
|
||||||
|
return new Pandemonium(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
118
Mage.Sets/src/mage/sets/tempestremastered/SilverWyvern.java
Normal file
118
Mage.Sets/src/mage/sets/tempestremastered/SilverWyvern.java
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
* 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.sets.tempestremastered;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.MageObject;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
import mage.abilities.effects.Effect;
|
||||||
|
import mage.abilities.effects.common.ChooseNewTargetsTargetEffect;
|
||||||
|
import mage.abilities.keyword.FlyingAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Rarity;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.filter.FilterStackObject;
|
||||||
|
import mage.filter.predicate.Predicate;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.stack.StackObject;
|
||||||
|
import mage.target.Target;
|
||||||
|
import mage.target.TargetStackObject;
|
||||||
|
import mage.target.Targets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
public class SilverWyvern extends CardImpl {
|
||||||
|
|
||||||
|
public SilverWyvern(UUID ownerId) {
|
||||||
|
super(ownerId, 68, "Silver Wyvern", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{U}{U}");
|
||||||
|
this.expansionSetCode = "TPR";
|
||||||
|
this.subtype.add("Drake");
|
||||||
|
this.power = new MageInt(4);
|
||||||
|
this.toughness = new MageInt(3);
|
||||||
|
|
||||||
|
// Flying
|
||||||
|
this.addAbility(FlyingAbility.getInstance());
|
||||||
|
// {U}: Change the target of target spell or ability that targets only Silver Wyvern. The new target must be a creature.
|
||||||
|
Effect effect = new ChooseNewTargetsTargetEffect(true, true);
|
||||||
|
effect.setText("Change the target of target spell or ability that targets only {this}. The new target must be a creature");
|
||||||
|
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{U}"));
|
||||||
|
FilterStackObject filter = new FilterStackObject();
|
||||||
|
filter.add(new TargetsOnlySourcePredicate(getId()));
|
||||||
|
ability.addTarget(new TargetStackObject(filter));
|
||||||
|
this.addAbility(ability);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public SilverWyvern(final SilverWyvern card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SilverWyvern copy() {
|
||||||
|
return new SilverWyvern(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TargetsOnlySourcePredicate implements Predicate<MageObject> {
|
||||||
|
|
||||||
|
private final UUID sourceId;
|
||||||
|
|
||||||
|
public TargetsOnlySourcePredicate(UUID sourceId) {
|
||||||
|
this.sourceId = sourceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(MageObject input, Game game) {
|
||||||
|
StackObject stackObject = game.getStack().getStackObject(input.getId());
|
||||||
|
if (stackObject != null) {
|
||||||
|
Targets spellTargets = stackObject.getStackAbility().getTargets();
|
||||||
|
int numberOfTargets = 0;
|
||||||
|
for (Target target : spellTargets) {
|
||||||
|
if (target.getFirstTarget() == null || !target.getFirstTarget().toString().equals(sourceId.toString())) { // UUID != UUID does not work - it's always false
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
numberOfTargets += target.getTargets().size();
|
||||||
|
}
|
||||||
|
if (numberOfTargets == 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "target spell or ability that targets only source";
|
||||||
|
}
|
||||||
|
}
|
||||||
119
Mage.Sets/src/mage/sets/timeshifted/Pandemonium.java
Normal file
119
Mage.Sets/src/mage/sets/timeshifted/Pandemonium.java
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
* 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.sets.timeshifted;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
|
||||||
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.Rarity;
|
||||||
|
import mage.constants.SetTargetPointer;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.players.Player;
|
||||||
|
import mage.target.common.TargetCreatureOrPlayer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
public class Pandemonium extends CardImpl {
|
||||||
|
|
||||||
|
public Pandemonium(UUID ownerId) {
|
||||||
|
super(ownerId, 68, "Pandemonium", Rarity.SPECIAL, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}");
|
||||||
|
this.expansionSetCode = "TSB";
|
||||||
|
|
||||||
|
// Whenever a creature enters the battlefield, that creature's controller may have it deal damage equal to its power to target creature or player of his or her choice.
|
||||||
|
Ability ability = new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new PandemoniumEffect(), new FilterCreaturePermanent(), false, SetTargetPointer.PERMANENT, "");
|
||||||
|
ability.addTarget(new TargetCreatureOrPlayer());
|
||||||
|
this.addAbility(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pandemonium(final Pandemonium card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void adjustTargets(Ability ability, Game game) {
|
||||||
|
if (ability instanceof EntersBattlefieldAllTriggeredAbility) {
|
||||||
|
UUID creatureId = ability.getEffects().get(0).getTargetPointer().getFirst(game, ability);
|
||||||
|
Permanent creature = game.getPermanent(creatureId);
|
||||||
|
if (creature != null) {
|
||||||
|
ability.getTargets().get(0).setTargetController(creature.getControllerId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Pandemonium copy() {
|
||||||
|
return new Pandemonium(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PandemoniumEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
public PandemoniumEffect() {
|
||||||
|
super(Outcome.Benefit);
|
||||||
|
this.staticText = "that creature's controller may have it deal damage equal to its power to target creature or player of his or her choice";
|
||||||
|
}
|
||||||
|
|
||||||
|
public PandemoniumEffect(final PandemoniumEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PandemoniumEffect copy() {
|
||||||
|
return new PandemoniumEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
if (controller != null) {
|
||||||
|
Permanent enteringCreature = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source));
|
||||||
|
if (enteringCreature != null) {
|
||||||
|
Permanent targetPermanent = game.getPermanent(source.getTargets().getFirstTarget());
|
||||||
|
if (targetPermanent != null) {
|
||||||
|
targetPermanent.damage(enteringCreature.getPower().getValue(), source.getSourceId(), game, false, true);
|
||||||
|
} else {
|
||||||
|
Player targetPlayer = game.getPlayer(source.getTargets().getFirstTarget());
|
||||||
|
if (targetPlayer != null) {
|
||||||
|
targetPlayer.damage(enteringCreature.getPower().getValue(), source.getSourceId(), game, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
71
Mage.Sets/src/mage/sets/timespiral/BonesplitterSliver.java
Normal file
71
Mage.Sets/src/mage/sets/timespiral/BonesplitterSliver.java
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* 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.sets.timespiral;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
|
import mage.abilities.effects.common.continuous.BoostAllEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.Rarity;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Sir-Speshkitty
|
||||||
|
*/
|
||||||
|
public class BonesplitterSliver extends CardImpl {
|
||||||
|
|
||||||
|
public BonesplitterSliver(UUID ownerId) {
|
||||||
|
super(ownerId, 149, "Bonesplitter Sliver", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{3}{R}");
|
||||||
|
this.expansionSetCode = "TSP";
|
||||||
|
this.subtype.add("Sliver");
|
||||||
|
this.power = new MageInt(2);
|
||||||
|
this.toughness = new MageInt(2);
|
||||||
|
|
||||||
|
// All Sliver creatures get +2/+0.
|
||||||
|
this.addAbility(
|
||||||
|
new SimpleStaticAbility(
|
||||||
|
Zone.BATTLEFIELD,
|
||||||
|
new BoostAllEffect(2, 0, Duration.WhileOnBattlefield, new FilterCreaturePermanent("Sliver","Sliver creatures"), false)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BonesplitterSliver(final BonesplitterSliver card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BonesplitterSliver copy() {
|
||||||
|
return new BonesplitterSliver(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -36,6 +36,7 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.mana.ColoredManaCost;
|
import mage.abilities.costs.mana.ColoredManaCost;
|
||||||
import mage.abilities.effects.common.RegenerateSourceEffect;
|
import mage.abilities.effects.common.RegenerateSourceEffect;
|
||||||
|
import mage.abilities.effects.common.SacrificeControllerEffect;
|
||||||
import mage.abilities.effects.common.SacrificeEffect;
|
import mage.abilities.effects.common.SacrificeEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.constants.ColoredManaSymbol;
|
import mage.constants.ColoredManaSymbol;
|
||||||
|
|
@ -54,7 +55,6 @@ public class SpinedFluke extends CardImpl {
|
||||||
this.subtype.add("Worm");
|
this.subtype.add("Worm");
|
||||||
this.subtype.add("Horror");
|
this.subtype.add("Horror");
|
||||||
|
|
||||||
this.color.setBlack(true);
|
|
||||||
this.power = new MageInt(5);
|
this.power = new MageInt(5);
|
||||||
this.toughness = new MageInt(1);
|
this.toughness = new MageInt(1);
|
||||||
}
|
}
|
||||||
|
|
@ -62,7 +62,7 @@ public class SpinedFluke extends CardImpl {
|
||||||
@Override
|
@Override
|
||||||
public void build() {
|
public void build() {
|
||||||
// When Spined Fluke enters the battlefield, sacrifice a creature.
|
// When Spined Fluke enters the battlefield, sacrifice a creature.
|
||||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new SacrificeEffect(new FilterCreaturePermanent("a creature"), 1, "")));
|
this.addAbility(new EntersBattlefieldTriggeredAbility(new SacrificeControllerEffect(new FilterCreaturePermanent("a creature"), 1, "")));
|
||||||
// {B}: Regenerate Spined Fluke.
|
// {B}: Regenerate Spined Fluke.
|
||||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new ColoredManaCost(ColoredManaSymbol.B)));
|
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new ColoredManaCost(ColoredManaSymbol.B)));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,6 @@ public class VinesOfVastwood extends CardImpl {
|
||||||
public VinesOfVastwood(UUID ownerId) {
|
public VinesOfVastwood(UUID ownerId) {
|
||||||
super(ownerId, 193, "Vines of Vastwood", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{G}");
|
super(ownerId, 193, "Vines of Vastwood", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{G}");
|
||||||
this.expansionSetCode = "ZEN";
|
this.expansionSetCode = "ZEN";
|
||||||
this.color.setGreen(true);
|
|
||||||
|
|
||||||
// Kicker {G} (You may pay an additional {G} as you cast this spell.)
|
// Kicker {G} (You may pay an additional {G} as you cast this spell.)
|
||||||
this.addAbility(new KickerAbility("{G}"));
|
this.addAbility(new KickerAbility("{G}"));
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* 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 org.mage.test.cards.abilities.activated;
|
||||||
|
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class PutOntoBattlefieldTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests to put a token onto the battlefield
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testOozeFlux() {
|
||||||
|
// Enchantment
|
||||||
|
// {1}{G}, Remove one or more +1/+1 counters from among creatures you control: Put an X/X green Ooze creature token onto the battlefield, where X is the number of +1/+1 counters removed this way.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Ooze Flux");
|
||||||
|
// Trample
|
||||||
|
// Kalonian Hydra enters the battlefield with four +1/+1 counters on it.
|
||||||
|
// Whenever Kalonian Hydra attacks, double the number of +1/+1 counters on each creature you control.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Kalonian Hydra");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
|
||||||
|
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{G},");
|
||||||
|
setChoice(playerA, "X=2"); // Remove how many
|
||||||
|
setChoice(playerA,"Kalonian Hydra");
|
||||||
|
setChoice(playerA, "X=2"); // Remove from Hydra
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPowerToughness(playerA, "Kalonian Hydra", 2, 2);
|
||||||
|
assertPermanentCount(playerA, "Ooze", 1);
|
||||||
|
assertPowerToughness(playerA, "Ooze", 2, 2);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -30,7 +30,6 @@ package org.mage.test.cards.abilities.other;
|
||||||
|
|
||||||
import mage.constants.PhaseStep;
|
import mage.constants.PhaseStep;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
|
@ -42,7 +41,7 @@ public class SoulfireGrandMasterTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Soulfire Grand Master
|
* Soulfire Grand Master
|
||||||
* Creature — Human Monk 2/2, 1W (2)
|
* Creature - Human Monk 2/2, 1W (2)
|
||||||
* Lifelink
|
* Lifelink
|
||||||
* Instant and sorcery spells you control have lifelink.
|
* Instant and sorcery spells you control have lifelink.
|
||||||
* {2}{U/R}{U/R}: The next time you cast an instant or sorcery spell from
|
* {2}{U/R}{U/R}: The next time you cast an instant or sorcery spell from
|
||||||
|
|
@ -233,5 +232,67 @@ public class SoulfireGrandMasterTest extends CardTestPlayerBase {
|
||||||
assertLife(playerA, 20);
|
assertLife(playerA, 20);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* I activated the ability of Soulfire grand master, it resolved, then i cast Stoke the Flames
|
||||||
|
* on Whisperwood Elemental, my opponenet sacrificed the elemental, so stoke didnt resolve,
|
||||||
|
* but i still got the life from lifelink.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSoulfireStokeTheFlames() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 8);
|
||||||
|
|
||||||
|
addCard(Zone.HAND, playerA, "Stoke the Flames");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Soulfire Grand Master", 1);
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Whisperwood Elemental", 1);
|
||||||
|
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{2}{U/R}{U/R}:");
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Stoke the Flames", "Whisperwood Elemental");
|
||||||
|
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Sacrifice {this}", null ,"{this} deals 4 damage");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertGraveyardCount(playerA, "Stoke the Flames", 1); // no legal target left so the spell is countered and goes to graveyard
|
||||||
|
assertGraveyardCount(playerB, "Whisperwood Elemental", 1);
|
||||||
|
|
||||||
|
assertLife(playerB, 20);
|
||||||
|
assertLife(playerA, 20);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if second ability resolved, the next spell that is counterer
|
||||||
|
* won't go to hand back because it did not resolve
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSoulfireCounteredSpellDontGoesBack() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 8);
|
||||||
|
|
||||||
|
addCard(Zone.HAND, playerA, "Stoke the Flames");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Soulfire Grand Master", 1);
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Island", 2);
|
||||||
|
addCard(Zone.HAND, playerB, "Counterspell", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Whisperwood Elemental", 1);
|
||||||
|
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{2}{U/R}{U/R}:");
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Stoke the Flames", "Whisperwood Elemental");
|
||||||
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Counterspell", "Stoke the Flames");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertGraveyardCount(playerB, "Counterspell", 1);
|
||||||
|
assertGraveyardCount(playerA, "Stoke the Flames", 1); // no legal target left so the spell is countered and goes to graveyard
|
||||||
|
|
||||||
|
assertLife(playerB, 20);
|
||||||
|
assertLife(playerA, 20);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,16 +74,20 @@ public class DungeonGeistsTest extends CardTestPlayerBase {
|
||||||
public void testWithBlink() {
|
public void testWithBlink() {
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
|
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
|
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
|
||||||
|
// When Dungeon Geists enters the battlefield, tap target creature an opponent controls.
|
||||||
|
// That creature doesn't untap during its controller's untap step for as long as you control Dungeon Geists.
|
||||||
addCard(Zone.HAND, playerA, "Dungeon Geists");
|
addCard(Zone.HAND, playerA, "Dungeon Geists");
|
||||||
addCard(Zone.HAND, playerA, "Cloudshift");
|
addCard(Zone.HAND, playerA, "Cloudshift");
|
||||||
addCard(Zone.BATTLEFIELD, playerB, "Craw Wurm");
|
addCard(Zone.BATTLEFIELD, playerB, "Craw Wurm");
|
||||||
addCard(Zone.BATTLEFIELD, playerB, "Elite Vanguard");
|
addCard(Zone.BATTLEFIELD, playerB, "Elite Vanguard");
|
||||||
|
|
||||||
addTarget(playerA, "Craw Wurm"); // first target Craw Wurm
|
|
||||||
addTarget(playerA, "Elite Vanguard"); // after Cloudshift effect (return back to battlefield) target Elite Vanguard
|
|
||||||
|
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dungeon Geists");
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dungeon Geists");
|
||||||
|
addTarget(playerA, "Craw Wurm"); // first target Craw Wurm
|
||||||
|
|
||||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Cloudshift", "Dungeon Geists");
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Cloudshift", "Dungeon Geists");
|
||||||
|
addTarget(playerA, "Elite Vanguard"); // after Cloudshift effect (return back to battlefield) target Elite Vanguard
|
||||||
|
|
||||||
setStopAt(2, PhaseStep.DRAW);
|
setStopAt(2, PhaseStep.DRAW);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* 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 org.mage.test.cards.triggers.state;
|
||||||
|
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.counters.CounterType;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class SynodCenturionTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that Synod Centurion gets sacrificed if no other artifacts are on the battlefield
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testAlone() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 6);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Demon's Horn");
|
||||||
|
addCard(Zone.HAND, playerA, "Shatter");
|
||||||
|
addCard(Zone.HAND, playerA, "Synod Centurion");
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Synod Centurion");
|
||||||
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Shatter", "Demon's Horn");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertGraveyardCount(playerA, "Demon's Horn", 1);
|
||||||
|
assertGraveyardCount(playerA, "Shatter", 1);
|
||||||
|
assertGraveyardCount(playerA, "Synod Centurion", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that Synod Centurion gets sacrificed if the only other
|
||||||
|
* artifact left the battlefiled for a short time
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testWithFlicker() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Plains", 6);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Bottle Gnomes");
|
||||||
|
addCard(Zone.HAND, playerA, "Cloudshift");
|
||||||
|
addCard(Zone.HAND, playerA, "Synod Centurion");
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Synod Centurion");
|
||||||
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Cloudshift", "Bottle Gnomes");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, "Bottle Gnomes", 1);
|
||||||
|
assertGraveyardCount(playerA, "Cloudshift", 1);
|
||||||
|
assertGraveyardCount(playerA, "Synod Centurion", 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -502,6 +502,18 @@ public class TestPlayer extends ComputerPlayer {
|
||||||
return super.announceXCost(min, max, message, game, ability, null);
|
return super.announceXCost(min, max, message, game, ability, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAmount(int min, int max, String message, Game game) {
|
||||||
|
if (!choices.isEmpty()) {
|
||||||
|
if (choices.get(0).startsWith("X=")) {
|
||||||
|
int xValue = Integer.parseInt(choices.get(0).substring(2));
|
||||||
|
choices.remove(0);
|
||||||
|
return xValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.getAmount(min, max, message, game);
|
||||||
|
}
|
||||||
|
|
||||||
protected Permanent findPermanent(FilterPermanent filter, UUID controllerId, Game game) {
|
protected Permanent findPermanent(FilterPermanent filter, UUID controllerId, Game game) {
|
||||||
List<Permanent> permanents = game.getBattlefield().getAllActivePermanents(filter, controllerId, game);
|
List<Permanent> permanents = game.getBattlefield().getAllActivePermanents(filter, controllerId, game);
|
||||||
if (permanents.size() > 0) {
|
if (permanents.size() > 0) {
|
||||||
|
|
|
||||||
|
|
@ -215,14 +215,20 @@ public abstract class AbilityImpl implements Ability {
|
||||||
else {
|
else {
|
||||||
game.addEffect((ContinuousEffect) effect, this);
|
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,
|
* game.applyEffects() has to be done at least for every effect that moves cards/permanent between zones,
|
||||||
* so Static effects work as intened if dependant from the moved objects zone it is in
|
* 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 to late
|
* Otherwise for example were static abilities with replacement effects deactivated to late
|
||||||
* Example: {@link org.mage.test.cards.replacement.DryadMilitantTest#testDiesByDestroy testDiesByDestroy}
|
* Example: {@link org.mage.test.cards.replacement.DryadMilitantTest#testDiesByDestroy testDiesByDestroy}
|
||||||
*/
|
*/
|
||||||
// game.applyEffects();
|
|
||||||
// some effects must be applied before next effect is resolved, because effect is dependend.
|
|
||||||
if (effect.applyEffectsAfter()) {
|
if (effect.applyEffectsAfter()) {
|
||||||
game.applyEffects();
|
game.applyEffects();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,10 @@
|
||||||
*/
|
*/
|
||||||
package mage.abilities.common;
|
package mage.abilities.common;
|
||||||
|
|
||||||
import mage.constants.CardType;
|
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.TriggeredAbilityImpl;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
|
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
|
|
@ -18,12 +18,19 @@ import mage.game.permanent.Permanent;
|
||||||
*/
|
*/
|
||||||
public class BecomesTappedCreatureControlledTriggeredAbility extends TriggeredAbilityImpl{
|
public class BecomesTappedCreatureControlledTriggeredAbility extends TriggeredAbilityImpl{
|
||||||
|
|
||||||
|
FilterControlledCreaturePermanent filter;
|
||||||
|
|
||||||
public BecomesTappedCreatureControlledTriggeredAbility(Effect effect, boolean optional) {
|
public BecomesTappedCreatureControlledTriggeredAbility(Effect effect, boolean optional) {
|
||||||
|
this(effect, optional, new FilterControlledCreaturePermanent("a creature you control"));
|
||||||
|
}
|
||||||
|
public BecomesTappedCreatureControlledTriggeredAbility(Effect effect, boolean optional, FilterControlledCreaturePermanent filter) {
|
||||||
super(Zone.BATTLEFIELD, effect, optional);
|
super(Zone.BATTLEFIELD, effect, optional);
|
||||||
|
this.filter = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BecomesTappedCreatureControlledTriggeredAbility(final BecomesTappedCreatureControlledTriggeredAbility ability) {
|
public BecomesTappedCreatureControlledTriggeredAbility(final BecomesTappedCreatureControlledTriggeredAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
|
this.filter = ability.filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -39,15 +46,11 @@ public class BecomesTappedCreatureControlledTriggeredAbility extends TriggeredAb
|
||||||
@Override
|
@Override
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
Permanent permanent = game.getPermanent(event.getTargetId());
|
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||||
if (permanent != null && permanent.getControllerId().equals(this.controllerId)
|
return permanent != null && filter.match(permanent, getSourceId(), getControllerId(), game);
|
||||||
&& permanent.getCardType().contains(CardType.CREATURE)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getRule() {
|
public String getRule() {
|
||||||
return "When a creature you control becomes tapped, " + super.getRule();
|
return "When " + filter.getMessage() + " becomes tapped, " + super.getRule();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,10 @@ import mage.constants.Outcome;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.Mode;
|
import mage.abilities.Mode;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.filter.Filter;
|
||||||
|
import mage.filter.FilterPermanent;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.stack.Spell;
|
import mage.game.stack.StackObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
|
|
@ -43,21 +45,27 @@ public class ChooseNewTargetsTargetEffect extends OneShotEffect {
|
||||||
|
|
||||||
private boolean forceChange;
|
private boolean forceChange;
|
||||||
private boolean onlyOneTarget;
|
private boolean onlyOneTarget;
|
||||||
|
private FilterPermanent filterNewTarget;
|
||||||
|
|
||||||
public ChooseNewTargetsTargetEffect() {
|
public ChooseNewTargetsTargetEffect() {
|
||||||
this(false, false);
|
this(false, false);
|
||||||
}
|
}
|
||||||
|
public ChooseNewTargetsTargetEffect(boolean forceChange, boolean onlyOneTarget) {
|
||||||
|
this(forceChange, onlyOneTarget, null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param forceChange forces the user to choose another target (only targets with maxtargets = 1 supported)
|
* @param forceChange forces the user to choose another target (only targets with maxtargets = 1 supported)
|
||||||
* @param onlyOneTarget only one target can be selected for the change
|
* @param onlyOneTarget only one target can be selected for the change
|
||||||
|
* @param filterNewTarget restriction to the new target
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public ChooseNewTargetsTargetEffect(boolean forceChange, boolean onlyOneTarget) {
|
public ChooseNewTargetsTargetEffect(boolean forceChange, boolean onlyOneTarget, FilterPermanent filterNewTarget) {
|
||||||
super(Outcome.Benefit);
|
super(Outcome.Benefit);
|
||||||
this.forceChange = forceChange;
|
this.forceChange = forceChange;
|
||||||
this.onlyOneTarget = onlyOneTarget;
|
this.onlyOneTarget = onlyOneTarget;
|
||||||
|
this.filterNewTarget = filterNewTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChooseNewTargetsTargetEffect(final ChooseNewTargetsTargetEffect effect) {
|
public ChooseNewTargetsTargetEffect(final ChooseNewTargetsTargetEffect effect) {
|
||||||
|
|
@ -68,9 +76,9 @@ public class ChooseNewTargetsTargetEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Spell spell = game.getStack().getSpell(source.getFirstTarget());
|
StackObject stackObject = game.getStack().getStackObject(source.getFirstTarget());
|
||||||
if (spell != null) {
|
if (stackObject != null) {
|
||||||
return spell.chooseNewTargets(game, source.getControllerId(), forceChange, onlyOneTarget);
|
return stackObject.chooseNewTargets(game, source.getControllerId(), forceChange, onlyOneTarget, filterNewTarget);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -82,6 +90,9 @@ public class ChooseNewTargetsTargetEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getText(Mode mode) {
|
public String getText(Mode mode) {
|
||||||
|
if (staticText != null && !staticText.isEmpty()) {
|
||||||
|
return staticText;
|
||||||
|
}
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
if (forceChange) {
|
if (forceChange) {
|
||||||
sb.append("change the target of target ");
|
sb.append("change the target of target ");
|
||||||
|
|
|
||||||
|
|
@ -95,9 +95,10 @@ public class AddCountersTargetEffect extends OneShotEffect {
|
||||||
permanent.addCounters(newCounter, game);
|
permanent.addCounters(newCounter, game);
|
||||||
int numberAdded = permanent.getCounters().getCount(counter.getName()) - before;
|
int numberAdded = permanent.getCounters().getCount(counter.getName()) - before;
|
||||||
affectedTargets ++;
|
affectedTargets ++;
|
||||||
if (!game.isSimulation())
|
if (!game.isSimulation()) {
|
||||||
game.informPlayers(sourceObject.getLogName() +": "+ controller.getName()+ " puts " +
|
game.informPlayers(sourceObject.getLogName() +": "+ controller.getName()+ " puts " +
|
||||||
numberAdded + " " + counter.getName().toLowerCase() + " counter on " + permanent.getLogName());
|
numberAdded + " " + counter.getName().toLowerCase() + " counter on " + permanent.getLogName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Player player = game.getPlayer(uuid);
|
Player player = game.getPlayer(uuid);
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ public class ShadowAbility extends EvasionAbility implements MageSingleton {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getRule() {
|
public String getRule() {
|
||||||
return "Shadow";
|
return "Shadow <i>(This creature can block or be blocked by only creatures with shadow.)</i>";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -53,10 +53,7 @@ class ShadowEffect extends RestrictionEffect implements MageSingleton {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applies(Permanent permanent, Ability source, Game game) {
|
public boolean applies(Permanent permanent, Ability source, Game game) {
|
||||||
if (permanent.getAbilities().containsKey(ShadowAbility.getInstance().getId())) {
|
return permanent.getAbilities().containsKey(ShadowAbility.getInstance().getId());
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -66,11 +63,8 @@ class ShadowEffect extends RestrictionEffect implements MageSingleton {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game) {
|
public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game) {
|
||||||
if (blocker.getAbilities().containsKey(ShadowAbility.getInstance().getId())
|
return blocker.getAbilities().containsKey(ShadowAbility.getInstance().getId())
|
||||||
|| game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_SHADOW, source, blocker.getControllerId(), game)) {
|
|| game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_SHADOW, source, blocker.getControllerId(), game);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -60,7 +60,7 @@ public enum CardRepository {
|
||||||
// raise this if db structure was changed
|
// raise this if db structure was changed
|
||||||
private static final long CARD_DB_VERSION = 37;
|
private static final long CARD_DB_VERSION = 37;
|
||||||
// raise this if new cards were added to the server
|
// raise this if new cards were added to the server
|
||||||
private static final long CARD_CONTENT_VERSION = 12;
|
private static final long CARD_CONTENT_VERSION = 13;
|
||||||
|
|
||||||
private final Random random = new Random();
|
private final Random random = new Random();
|
||||||
private Dao<CardInfo, Object> cardDao;
|
private Dao<CardInfo, Object> cardDao;
|
||||||
|
|
|
||||||
|
|
@ -177,7 +177,16 @@ public class GameEvent {
|
||||||
ADD_COUNTER, COUNTER_ADDED,
|
ADD_COUNTER, COUNTER_ADDED,
|
||||||
ADD_COUNTERS, COUNTERS_ADDED,
|
ADD_COUNTERS, COUNTERS_ADDED,
|
||||||
COUNTER_REMOVED,
|
COUNTER_REMOVED,
|
||||||
LOSE_CONTROL, LOST_CONTROL,
|
LOSE_CONTROL,
|
||||||
|
|
||||||
|
/* LOST_CONTROL
|
||||||
|
targetId id of the creature that lost control
|
||||||
|
sourceId id of the creature that lost control
|
||||||
|
playerId player that controlles the creature before
|
||||||
|
amount not used for this event
|
||||||
|
flag not used for this event
|
||||||
|
*/
|
||||||
|
LOST_CONTROL,
|
||||||
GAIN_CONTROL, GAINED_CONTROL,
|
GAIN_CONTROL, GAINED_CONTROL,
|
||||||
CREATE_TOKEN,
|
CREATE_TOKEN,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ public class PermanentToken extends PermanentImpl {
|
||||||
if (!game.replaceEvent(new ZoneChangeEvent(this, sourceId, this.getControllerId(), Zone.BATTLEFIELD, Zone.EXILED))) {
|
if (!game.replaceEvent(new ZoneChangeEvent(this, sourceId, this.getControllerId(), Zone.BATTLEFIELD, Zone.EXILED))) {
|
||||||
game.rememberLKI(objectId, Zone.BATTLEFIELD, this);
|
game.rememberLKI(objectId, Zone.BATTLEFIELD, this);
|
||||||
if (game.getPlayer(controllerId).removeFromBattlefield(this, game)) {
|
if (game.getPlayer(controllerId).removeFromBattlefield(this, game)) {
|
||||||
game.fireEvent(new ZoneChangeEvent(this, sourceId, this.getControllerId(), Zone.BATTLEFIELD, Zone.EXILED));
|
game.addSimultaneousEvent(new ZoneChangeEvent(this, sourceId, this.getControllerId(), Zone.BATTLEFIELD, Zone.EXILED));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ import mage.constants.SpellAbilityType;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.counters.Counter;
|
import mage.counters.Counter;
|
||||||
import mage.counters.Counters;
|
import mage.counters.Counters;
|
||||||
|
import mage.filter.FilterPermanent;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.ZoneChangeEvent;
|
import mage.game.events.ZoneChangeEvent;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
|
|
@ -81,6 +82,7 @@ public class Spell implements StackObject, Card {
|
||||||
private UUID controllerId;
|
private UUID controllerId;
|
||||||
private boolean copiedSpell;
|
private boolean copiedSpell;
|
||||||
private boolean faceDown;
|
private boolean faceDown;
|
||||||
|
private boolean countered;
|
||||||
|
|
||||||
public Spell(Card card, SpellAbility ability, UUID controllerId, Zone fromZone) {
|
public Spell(Card card, SpellAbility ability, UUID controllerId, Zone fromZone) {
|
||||||
this.card = card;
|
this.card = card;
|
||||||
|
|
@ -99,6 +101,7 @@ public class Spell implements StackObject, Card {
|
||||||
}
|
}
|
||||||
this.controllerId = controllerId;
|
this.controllerId = controllerId;
|
||||||
this.fromZone = fromZone;
|
this.fromZone = fromZone;
|
||||||
|
this.countered = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Spell(final Spell spell) {
|
public Spell(final Spell spell) {
|
||||||
|
|
@ -198,8 +201,8 @@ public class Spell implements StackObject, Card {
|
||||||
result |= spellAbility.resolve(game);
|
result |= spellAbility.resolve(game);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
game.getState().handleSimultaneousEvent(game);
|
// game.getState().handleSimultaneousEvent(game);
|
||||||
game.resetShortLivingLKI();
|
// game.resetShortLivingLKI();
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -319,7 +322,7 @@ public class Spell implements StackObject, Card {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public boolean chooseNewTargets(Game game, UUID playerId) {
|
public boolean chooseNewTargets(Game game, UUID playerId) {
|
||||||
return chooseNewTargets(game, playerId, false, false);
|
return chooseNewTargets(game, playerId, false, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -377,13 +380,13 @@ public class Spell implements StackObject, Card {
|
||||||
*
|
*
|
||||||
* @param game
|
* @param game
|
||||||
* @param playerId - player that can/has to change the taregt of the spell
|
* @param playerId - player that can/has to change the taregt of the spell
|
||||||
* @param forceChange - does only work for targets with maximum of one
|
* @param forceChange - does only work for targets with maximum of one targetId
|
||||||
* targetId
|
* @param onlyOneTarget - 114.6b one target must be changed to another target
|
||||||
* @param onlyOneTarget - 114.6b one target must be changed to another
|
* @param filterNewTarget restriction for the new target, if null nothing is cheched
|
||||||
* target
|
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public boolean chooseNewTargets(Game game, UUID playerId, boolean forceChange, boolean onlyOneTarget) {
|
@Override
|
||||||
|
public boolean chooseNewTargets(Game game, UUID playerId, boolean forceChange, boolean onlyOneTarget, FilterPermanent filterNewTarget) {
|
||||||
Player player = game.getPlayer(playerId);
|
Player player = game.getPlayer(playerId);
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
StringBuilder newTargetDescription = new StringBuilder();
|
StringBuilder newTargetDescription = new StringBuilder();
|
||||||
|
|
@ -393,7 +396,7 @@ public class Spell implements StackObject, Card {
|
||||||
for (UUID modeId : spellAbility.getModes().getSelectedModes()) {
|
for (UUID modeId : spellAbility.getModes().getSelectedModes()) {
|
||||||
Mode mode = spellAbility.getModes().get(modeId);
|
Mode mode = spellAbility.getModes().get(modeId);
|
||||||
for (Target target : mode.getTargets()) {
|
for (Target target : mode.getTargets()) {
|
||||||
Target newTarget = chooseNewTarget(player, spellAbility, mode, target, forceChange, game);
|
Target newTarget = chooseNewTarget(player, spellAbility, mode, target, forceChange, filterNewTarget, game);
|
||||||
// clear the old target and copy all targets from new target
|
// clear the old target and copy all targets from new target
|
||||||
target.clearChosen();
|
target.clearChosen();
|
||||||
for (UUID targetId : newTarget.getTargets()) {
|
for (UUID targetId : newTarget.getTargets()) {
|
||||||
|
|
@ -424,7 +427,7 @@ public class Spell implements StackObject, Card {
|
||||||
* @param game
|
* @param game
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private Target chooseNewTarget(Player player, SpellAbility spellAbility, Mode mode, Target target, boolean forceChange, Game game) {
|
private Target chooseNewTarget(Player player, SpellAbility spellAbility, Mode mode, Target target, boolean forceChange, FilterPermanent filterNewTarget, Game game) {
|
||||||
Target newTarget = target.copy();
|
Target newTarget = target.copy();
|
||||||
newTarget.clearChosen();
|
newTarget.clearChosen();
|
||||||
for (UUID targetId : target.getTargets()) {
|
for (UUID targetId : target.getTargets()) {
|
||||||
|
|
@ -443,6 +446,14 @@ public class Spell implements StackObject, Card {
|
||||||
newTarget.clearChosen();
|
newTarget.clearChosen();
|
||||||
// TODO: Distinction between "spell controller" and "player that can change the target" - here player is used for both
|
// TODO: Distinction between "spell controller" and "player that can change the target" - here player is used for both
|
||||||
newTarget.chooseTarget(mode.getEffects().get(0).getOutcome(), player.getId(), spellAbility, game);
|
newTarget.chooseTarget(mode.getEffects().get(0).getOutcome(), player.getId(), spellAbility, game);
|
||||||
|
// check target restriction
|
||||||
|
if (newTarget.getFirstTarget() != null && filterNewTarget != null) {
|
||||||
|
Permanent newTargetPermanent = game.getPermanent(newTarget.getFirstTarget());
|
||||||
|
if (newTargetPermanent == null || !filterNewTarget.match(newTargetPermanent, game)) {
|
||||||
|
game.informPlayer(player, "Target does not fullfil the target requirements (" + filterNewTarget.getMessage() +")");
|
||||||
|
newTarget.clearChosen();
|
||||||
|
}
|
||||||
|
}
|
||||||
} while (player.isInGame() && (targetId.equals(newTarget.getFirstTarget()) || newTarget.getTargets().size() != 1));
|
} while (player.isInGame() && (targetId.equals(newTarget.getFirstTarget()) || newTarget.getTargets().size() != 1));
|
||||||
// choose a new target
|
// choose a new target
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -473,6 +484,12 @@ public class Spell implements StackObject, Card {
|
||||||
} else {
|
} else {
|
||||||
newTarget.addTarget(targetId, target.getTargetAmount(targetId), spellAbility, game, false);
|
newTarget.addTarget(targetId, target.getTargetAmount(targetId), spellAbility, game, false);
|
||||||
}
|
}
|
||||||
|
} else if (newTarget.getFirstTarget() != null && filterNewTarget != null) {
|
||||||
|
Permanent newTargetPermanent = game.getPermanent(newTarget.getFirstTarget());
|
||||||
|
if (newTargetPermanent == null || !filterNewTarget.match(newTargetPermanent, game)) {
|
||||||
|
game.informPlayer(player, "This target does not fullfil the target requirements (" + filterNewTarget.getMessage() +")");
|
||||||
|
again = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// valid target was selected, add it to the new target definition
|
// valid target was selected, add it to the new target definition
|
||||||
newTarget.addTarget(tempTarget.getFirstTarget(), target.getTargetAmount(targetId), spellAbility, game, false);
|
newTarget.addTarget(tempTarget.getFirstTarget(), target.getTargetAmount(targetId), spellAbility, game, false);
|
||||||
|
|
@ -506,6 +523,7 @@ public class Spell implements StackObject, Card {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void counter(UUID sourceId, Game game) {
|
public void counter(UUID sourceId, Game game) {
|
||||||
|
this.countered = true;
|
||||||
if (!isCopiedSpell()) {
|
if (!isCopiedSpell()) {
|
||||||
card.moveToZone(Zone.GRAVEYARD, sourceId, game, false);
|
card.moveToZone(Zone.GRAVEYARD, sourceId, game, false);
|
||||||
}
|
}
|
||||||
|
|
@ -987,4 +1005,8 @@ public class Spell implements StackObject, Card {
|
||||||
throw new UnsupportedOperationException("Not supported.");
|
throw new UnsupportedOperationException("Not supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isCountered() {
|
||||||
|
return countered;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -97,9 +97,10 @@ public class SpellStack extends ArrayDeque<StackObject> {
|
||||||
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER, objectId, sourceId, stackObject.getControllerId()))) {
|
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER, objectId, sourceId, stackObject.getControllerId()))) {
|
||||||
if ( stackObject instanceof Spell ) {
|
if ( stackObject instanceof Spell ) {
|
||||||
game.rememberLKI(objectId, Zone.STACK, (Spell)stackObject);
|
game.rememberLKI(objectId, Zone.STACK, (Spell)stackObject);
|
||||||
|
} else {
|
||||||
|
this.remove(stackObject);
|
||||||
}
|
}
|
||||||
this.remove(stackObject);
|
stackObject.counter(sourceId, game);
|
||||||
stackObject.counter(sourceId, game); // tries to move to graveyard
|
|
||||||
if (!game.isSimulation())
|
if (!game.isSimulation())
|
||||||
game.informPlayers(counteredObjectName + " is countered by " + sourceObject.getLogName());
|
game.informPlayers(counteredObjectName + " is countered by " + sourceObject.getLogName());
|
||||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.COUNTERED, objectId, sourceId, stackObject.getControllerId()));
|
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.COUNTERED, objectId, sourceId, stackObject.getControllerId()));
|
||||||
|
|
|
||||||
|
|
@ -54,10 +54,15 @@ import mage.target.Targets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import mage.abilities.dynamicvalue.common.StaticValue;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.constants.AbilityWord;
|
import mage.constants.AbilityWord;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.filter.FilterPermanent;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
import mage.target.TargetAmount;
|
||||||
import mage.watchers.Watcher;
|
import mage.watchers.Watcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -535,4 +540,197 @@ public class StackAbility implements StackObject, Ability {
|
||||||
throw new UnsupportedOperationException("Not supported.");
|
throw new UnsupportedOperationException("Not supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 114.6. Some effects allow a player to change the target(s) of a spell or
|
||||||
|
* ability, and other effects allow a player to choose new targets for a
|
||||||
|
* spell or ability.
|
||||||
|
*
|
||||||
|
* 114.6a If an effect allows a player to "change the
|
||||||
|
* target(s)" of a spell or ability, each target can be changed only to
|
||||||
|
* another legal target. If a target can't be changed to another legal
|
||||||
|
* target, the original target is unchanged, even if the original target is
|
||||||
|
* itself illegal by then. If all the targets aren't changed to other legal
|
||||||
|
* targets, none of them are changed.
|
||||||
|
*
|
||||||
|
* 114.6b If an effect allows a player to "change a target" of a
|
||||||
|
* spell or ability, the process described in rule 114.6a
|
||||||
|
* is followed, except that only one of those targets may be changed
|
||||||
|
* (rather than all of them or none of them).
|
||||||
|
*
|
||||||
|
* 114.6c If an effect allows a
|
||||||
|
* player to "change any targets" of a spell or ability, the process
|
||||||
|
* described in rule 114.6a is followed, except that any number of those
|
||||||
|
* targets may be changed (rather than all of them or none of them).
|
||||||
|
*
|
||||||
|
* 114.6d If an effect allows a player to "choose new targets" for a spell or
|
||||||
|
* ability, the player may leave any number of the targets unchanged, even
|
||||||
|
* if those targets would be illegal. If the player chooses to change some
|
||||||
|
* or all of the targets, the new targets must be legal and must not cause
|
||||||
|
* any unchanged targets to become illegal.
|
||||||
|
*
|
||||||
|
* 114.6e When changing targets or
|
||||||
|
* choosing new targets for a spell or ability, only the final set of
|
||||||
|
* targets is evaluated to determine whether the change is legal.
|
||||||
|
*
|
||||||
|
* Example: Arc Trail is a sorcery that reads "Arc Trail deals 2 damage to
|
||||||
|
* target creature or player and 1 damage to another target creature or
|
||||||
|
* player." The current targets of Arc Trail are Runeclaw Bear and Llanowar
|
||||||
|
* Elves, in that order. You cast Redirect, an instant that reads "You may
|
||||||
|
* choose new targets for target spell," targeting Arc Trail. You can change
|
||||||
|
* the first target to Llanowar Elves and change the second target to
|
||||||
|
* Runeclaw Bear.
|
||||||
|
*
|
||||||
|
* 114.7. Modal spells and abilities may have different targeting
|
||||||
|
* requirements for each mode. An effect that allows a player to change the
|
||||||
|
* target(s) of a modal spell or ability, or to choose new targets for a
|
||||||
|
* modal spell or ability, doesn't allow that player to change its mode.
|
||||||
|
* (See rule 700.2.)
|
||||||
|
*
|
||||||
|
* 706.10c Some effects copy a spell or ability and state that its
|
||||||
|
* controller may choose new targets for the copy. The player may leave any
|
||||||
|
* number of the targets unchanged, even if those targets would be illegal.
|
||||||
|
* If the player chooses to change some or all of the targets, the new
|
||||||
|
* targets must be legal. Once the player has decided what the copy's
|
||||||
|
* targets will be, the copy is put onto the stack with those targets.
|
||||||
|
*
|
||||||
|
* @param game
|
||||||
|
* @param playerId - player that can/has to change the target of the ability
|
||||||
|
* @param forceChange - does only work for targets with maximum of one targetId
|
||||||
|
* @param onlyOneTarget - 114.6b one target must be changed to another target
|
||||||
|
* @param filterNewTarget restriction for the new target, if null nothing is cheched
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean chooseNewTargets(Game game, UUID playerId, boolean forceChange, boolean onlyOneTarget, FilterPermanent filterNewTarget) {
|
||||||
|
Player player = game.getPlayer(playerId);
|
||||||
|
if (player != null) {
|
||||||
|
StringBuilder newTargetDescription = new StringBuilder();
|
||||||
|
// Some abilities can have more than one mode
|
||||||
|
for (UUID modeId : ability.getModes().getSelectedModes()) {
|
||||||
|
Mode mode = ability.getModes().get(modeId);
|
||||||
|
for (Target target : mode.getTargets()) {
|
||||||
|
Target newTarget = chooseNewTarget(player, getStackAbility(), mode, target, forceChange, filterNewTarget, game);
|
||||||
|
// clear the old target and copy all targets from new target
|
||||||
|
target.clearChosen();
|
||||||
|
for (UUID targetId : newTarget.getTargets()) {
|
||||||
|
target.addTarget(targetId, newTarget.getTargetAmount(targetId), ability, game, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
newTargetDescription.append(((AbilityImpl)ability).getTargetDescription(mode.getTargets(), game));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newTargetDescription.length() > 0 && !game.isSimulation()) {
|
||||||
|
game.informPlayers(this.getName() + " is now " + newTargetDescription.toString());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the change of one target instance of a mode
|
||||||
|
*
|
||||||
|
* @param player - player that can choose the new target
|
||||||
|
* @param ability
|
||||||
|
* @param mode
|
||||||
|
* @param target
|
||||||
|
* @param forceChange
|
||||||
|
* @param game
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Target chooseNewTarget(Player player, Ability ability, Mode mode, Target target, boolean forceChange, FilterPermanent filterNewTarget, Game game) {
|
||||||
|
Target newTarget = target.copy();
|
||||||
|
newTarget.clearChosen();
|
||||||
|
for (UUID targetId : target.getTargets()) {
|
||||||
|
String targetNames = getNamesOfTargets(targetId, game);
|
||||||
|
// change the target?
|
||||||
|
if (targetNames != null
|
||||||
|
&& (forceChange || player.chooseUse(mode.getEffects().get(0).getOutcome(), "Change this target: " + targetNames + "?", game))) {
|
||||||
|
// choose exactly one other target
|
||||||
|
if (forceChange && target.possibleTargets(this.getSourceId(), getControllerId(), game).size() > 1) { // controller of ability must be used (e.g. TargetOpponent)
|
||||||
|
int iteration = 0;
|
||||||
|
do {
|
||||||
|
if (iteration > 0 && !game.isSimulation()) {
|
||||||
|
game.informPlayer(player, "You may only select exactly one target that must be different from the origin target!");
|
||||||
|
}
|
||||||
|
iteration++;
|
||||||
|
newTarget.clearChosen();
|
||||||
|
// TODO: Distinction between "ability controller" and "player that can change the target" - here player is used for both
|
||||||
|
newTarget.chooseTarget(mode.getEffects().get(0).getOutcome(), player.getId(), ability, game);
|
||||||
|
// check target restriction
|
||||||
|
if (newTarget.getFirstTarget() != null && filterNewTarget != null) {
|
||||||
|
Permanent newTargetPermanent = game.getPermanent(newTarget.getFirstTarget());
|
||||||
|
if (newTargetPermanent == null || !filterNewTarget.match(newTargetPermanent, game)) {
|
||||||
|
game.informPlayer(player, "Target does not fullfil the target requirements (" + filterNewTarget.getMessage() +")");
|
||||||
|
newTarget.clearChosen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (player.isInGame() && (targetId.equals(newTarget.getFirstTarget()) || newTarget.getTargets().size() != 1));
|
||||||
|
// choose a new target
|
||||||
|
} else {
|
||||||
|
// build a target definition with exactly one possible target to select that replaces old target
|
||||||
|
Target tempTarget = target.copy();
|
||||||
|
if (target instanceof TargetAmount) {
|
||||||
|
((TargetAmount)tempTarget).setAmountDefinition(new StaticValue(target.getTargetAmount(targetId)));
|
||||||
|
}
|
||||||
|
tempTarget.setMinNumberOfTargets(1);
|
||||||
|
tempTarget.setMaxNumberOfTargets(1);
|
||||||
|
boolean again;
|
||||||
|
do {
|
||||||
|
again = false;
|
||||||
|
tempTarget.clearChosen();
|
||||||
|
if (!tempTarget.chooseTarget(mode.getEffects().get(0).getOutcome(), player.getId(), ability, game)) {
|
||||||
|
if (player.chooseUse(Outcome.Benefit, "No target object selected. Reset to original target?", game)) {
|
||||||
|
// use previous target no target was selected
|
||||||
|
newTarget.addTarget(targetId, target.getTargetAmount(targetId), ability, game, false);
|
||||||
|
} else {
|
||||||
|
again = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// if possible add the alternate Target - it may not be included in the old definition nor in the already selected targets of the new definition
|
||||||
|
if (newTarget.getTargets().contains(tempTarget.getFirstTarget()) || target.getTargets().contains(tempTarget.getFirstTarget())) {
|
||||||
|
if (player.isHuman()) {
|
||||||
|
game.informPlayer(player, "This target was already selected from origin ability. You can only keep this target!");
|
||||||
|
again = true;
|
||||||
|
} else {
|
||||||
|
newTarget.addTarget(targetId, target.getTargetAmount(targetId), ability, game, false);
|
||||||
|
}
|
||||||
|
} else if (newTarget.getFirstTarget() != null && filterNewTarget != null) {
|
||||||
|
Permanent newTargetPermanent = game.getPermanent(newTarget.getFirstTarget());
|
||||||
|
if (newTargetPermanent == null || !filterNewTarget.match(newTargetPermanent, game)) {
|
||||||
|
game.informPlayer(player, "This target does not fullfil the target requirements (" + filterNewTarget.getMessage() +")");
|
||||||
|
again = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// valid target was selected, add it to the new target definition
|
||||||
|
newTarget.addTarget(tempTarget.getFirstTarget(), target.getTargetAmount(targetId), ability, game, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (again && player.isInGame());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// keep the target
|
||||||
|
else {
|
||||||
|
newTarget.addTarget(targetId, target.getTargetAmount(targetId), ability, game, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String getNamesOfTargets(UUID targetId, Game game) {
|
||||||
|
MageObject object = game.getObject(targetId);
|
||||||
|
String targetNames = null;
|
||||||
|
if (object == null) {
|
||||||
|
Player targetPlayer = game.getPlayer(targetId);
|
||||||
|
if (targetPlayer != null) {
|
||||||
|
targetNames = targetPlayer.getName();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
targetNames = object.getName();
|
||||||
|
}
|
||||||
|
return targetNames;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ package mage.game.stack;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
|
import mage.filter.FilterPermanent;
|
||||||
import mage.game.Controllable;
|
import mage.game.Controllable;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
|
||||||
|
|
@ -41,6 +42,7 @@ public interface StackObject extends MageObject, Controllable {
|
||||||
void counter(UUID sourceId, Game game);
|
void counter(UUID sourceId, Game game);
|
||||||
Ability getStackAbility();
|
Ability getStackAbility();
|
||||||
int getConvertedManaCost();
|
int getConvertedManaCost();
|
||||||
|
boolean chooseNewTargets(Game game, UUID playerId, boolean forceChange, boolean onlyOneTarget, FilterPermanent filterNewTarget);
|
||||||
@Override
|
@Override
|
||||||
StackObject copy();
|
StackObject copy();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -104,4 +104,8 @@ public interface Target extends Serializable {
|
||||||
UUID getFirstTarget();
|
UUID getFirstTarget();
|
||||||
|
|
||||||
Target copy();
|
Target copy();
|
||||||
}
|
|
||||||
|
// some targets are choosen from players that are not the controller of the ability (e.g. Pandemonium)
|
||||||
|
void setTargetController(UUID playerId);
|
||||||
|
UUID getTargetController();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ public abstract class TargetImpl implements Target {
|
||||||
// is the target handled as targeted spell/ability (notTarget = true is used for not targeted effects like e.g. sacrifice)
|
// is the target handled as targeted spell/ability (notTarget = true is used for not targeted effects like e.g. sacrifice)
|
||||||
protected boolean notTarget = false;
|
protected boolean notTarget = false;
|
||||||
protected boolean atRandom = false;
|
protected boolean atRandom = false;
|
||||||
|
protected UUID targetController = null; // if null the ability controller is the targetController
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public abstract TargetImpl copy();
|
public abstract TargetImpl copy();
|
||||||
|
|
@ -84,6 +85,7 @@ public abstract class TargetImpl implements Target {
|
||||||
this.zoneChangeCounters.putAll(target.zoneChangeCounters);
|
this.zoneChangeCounters.putAll(target.zoneChangeCounters);
|
||||||
this.atRandom = target.atRandom;
|
this.atRandom = target.atRandom;
|
||||||
this.notTarget = target.notTarget;
|
this.notTarget = target.notTarget;
|
||||||
|
this.targetController = target.targetController;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -421,5 +423,15 @@ public abstract class TargetImpl implements Target {
|
||||||
this.atRandom = atRandom;
|
this.atRandom = atRandom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTargetController(UUID playerId) {
|
||||||
|
this.targetController = playerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID getTargetController() {
|
||||||
|
return targetController;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,11 @@ public class Targets extends ArrayList<Target> {
|
||||||
}
|
}
|
||||||
while (!isChosen()) {
|
while (!isChosen()) {
|
||||||
Target target = this.getUnchosen().get(0);
|
Target target = this.getUnchosen().get(0);
|
||||||
if (!target.chooseTarget(outcome, playerId, source, game)) {
|
UUID targetController = playerId;
|
||||||
|
if (target.getTargetController() != null) { // some targets can have controller different than ability controller
|
||||||
|
targetController = target.getTargetController();
|
||||||
|
}
|
||||||
|
if (!target.chooseTarget(outcome, targetController, source, game)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ public class CardUtil {
|
||||||
* @param increaseCount
|
* @param increaseCount
|
||||||
*/
|
*/
|
||||||
public static void increaseCost(Ability ability, int increaseCount) {
|
public static void increaseCost(Ability ability, int increaseCount) {
|
||||||
adjustCost(ability, -increaseCount);
|
adjustAbilityCost(ability, -increaseCount);
|
||||||
adjustAlternativeCosts(ability, -increaseCount);
|
adjustAlternativeCosts(ability, -increaseCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -143,7 +143,7 @@ public class CardUtil {
|
||||||
* @param reduceCount
|
* @param reduceCount
|
||||||
*/
|
*/
|
||||||
public static void reduceCost(Ability ability, int reduceCount) {
|
public static void reduceCost(Ability ability, int reduceCount) {
|
||||||
adjustCost(ability, reduceCount);
|
adjustAbilityCost(ability, reduceCount);
|
||||||
adjustAlternativeCosts(ability, reduceCount);
|
adjustAlternativeCosts(ability, reduceCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -154,7 +154,7 @@ public class CardUtil {
|
||||||
* @param reduceCount
|
* @param reduceCount
|
||||||
*/
|
*/
|
||||||
public static void adjustCost(SpellAbility spellAbility, int reduceCount) {
|
public static void adjustCost(SpellAbility spellAbility, int reduceCount) {
|
||||||
CardUtil.adjustCost((Ability) spellAbility, reduceCount);
|
CardUtil.adjustAbilityCost((Ability) spellAbility, reduceCount);
|
||||||
adjustAlternativeCosts(spellAbility, reduceCount);
|
adjustAlternativeCosts(spellAbility, reduceCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -208,7 +208,7 @@ public class CardUtil {
|
||||||
* @param ability
|
* @param ability
|
||||||
* @param reduceCount
|
* @param reduceCount
|
||||||
*/
|
*/
|
||||||
private static void adjustCost(Ability ability, int reduceCount) {
|
public static void adjustAbilityCost(Ability ability, int reduceCount) {
|
||||||
ManaCosts<ManaCost> adjustedCost = adjustCost(ability.getManaCostsToPay(), reduceCount);
|
ManaCosts<ManaCost> adjustedCost = adjustCost(ability.getManaCostsToPay(), reduceCount);
|
||||||
ability.getManaCostsToPay().clear();
|
ability.getManaCostsToPay().clear();
|
||||||
ability.getManaCostsToPay().addAll(adjustedCost);
|
ability.getManaCostsToPay().addAll(adjustedCost);
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,9 @@ git log 65f731557bb55d0c85723e382001bdf9701f0a7f..HEAD --diff-filter=A --name-st
|
||||||
since 1.3.0-2015-03-14v6
|
since 1.3.0-2015-03-14v6
|
||||||
git log b79d6e64cff01726be93cbbfffca8a6f18188a3c..HEAD --diff-filter=A --name-status | sed -ne "s/^A[^u]Mage.Sets\/src\/mage\/sets\///p" | sort > added_cards.txt
|
git log b79d6e64cff01726be93cbbfffca8a6f18188a3c..HEAD --diff-filter=A --name-status | sed -ne "s/^A[^u]Mage.Sets\/src\/mage\/sets\///p" | sort > added_cards.txt
|
||||||
|
|
||||||
|
since 1.3.0-2015-03-14v8
|
||||||
|
git log 47b17535194c6aa5397a966463c8b17d37f8bd44..HEAD --diff-filter=A --name-status | sed -ne "s/^A[^u]Mage.Sets\/src\/mage\/sets\///p" | sort > added_cards.txt
|
||||||
|
|
||||||
3. Copy added_cards.txt to trunk\Utils folder
|
3. Copy added_cards.txt to trunk\Utils folder
|
||||||
4. Run script:
|
4. Run script:
|
||||||
> perl extract_in_wiki_format.perl
|
> perl extract_in_wiki_format.perl
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue