This commit is contained in:
LevelX2 2013-09-18 18:17:08 +02:00
commit aae4b019f6
6 changed files with 633 additions and 18 deletions

View file

@ -0,0 +1,155 @@
/*
* 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.theros;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BecomesMonstrousSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.MonstrosityAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.TargetController;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.ControllerPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.Target;
import mage.target.common.TargetCreaturePermanentAmount;
/**
*
* * The value of X in Polukranoss last ability is equal to the value chosen
* for X when its activated ability was activated.
*
* * The number of targets chosen for the triggered ability must be at least one
* (if X wasnt 0) and at most X. You choose the division of damage as you put
* the ability on the stack, not as it resolves. Each target must be assigned
* at least 1 damage. In multiplayer games, you may choose creatures controlled
* by different opponents.
*
* * If some, but not all, of the abilitys targets become illegal, you cant change
* the division of damage. Damage that wouldve been dealt to illegal targets
* simply isnt dealt.
*
* * As Polukranoss triggered ability resolves, Polukranos deals damage first, then
* the target creatures do. Although no creature will die until after the ability
* finishes resolving, the order could matter if Polukranos has wither or infect.
*
* @author LevelX2
*/
public class PolukranosWorldEater extends CardImpl<PolukranosWorldEater> {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
static {
filter.add(new ControllerPredicate(TargetController.OPPONENT));
}
public PolukranosWorldEater(UUID ownerId) {
super(ownerId, 172, "Polukranos, World Eater", Rarity.MYTHIC, new CardType[]{CardType.CREATURE}, "{2}{G}{G}");
this.expansionSetCode = "THS";
this.supertype.add("Legendary");
this.subtype.add("Hydra");
this.color.setGreen(true);
this.power = new MageInt(5);
this.toughness = new MageInt(5);
// {X}{X}{G}: Monstrosity X.
this.addAbility(new MonstrosityAbility("{X}{X}{G}", Integer.MAX_VALUE));
// When Polukranos, World Eater becomes monstrous, it deals X damage divided as you choose among any number of target creatures your opponents control. Each of those creatures deals damage equal to its power to Polukranos.
Ability ability = new BecomesMonstrousSourceTriggeredAbility(new PolukranosWorldEaterEffect());
ability.addTarget(new TargetCreaturePermanentAmount(1, filter));
this.addAbility(ability);
}
@Override
public void adjustTargets(Ability ability, Game game) {
if (ability instanceof BecomesMonstrousSourceTriggeredAbility) {
int xValue = ((BecomesMonstrousSourceTriggeredAbility) ability).getMonstrosityValue();
ability.getTargets().clear();
ability.addTarget(new TargetCreaturePermanentAmount(xValue, filter));
}
}
public PolukranosWorldEater(final PolukranosWorldEater card) {
super(card);
}
@Override
public PolukranosWorldEater copy() {
return new PolukranosWorldEater(this);
}
}
class PolukranosWorldEaterEffect extends OneShotEffect<PolukranosWorldEaterEffect> {
public PolukranosWorldEaterEffect() {
super(Outcome.Benefit);
this.staticText = "it deals X damage divided as you choose among any number of target creatures your opponents control. Each of those creatures deals damage equal to its power to Polukranos";
}
public PolukranosWorldEaterEffect(final PolukranosWorldEaterEffect effect) {
super(effect);
}
@Override
public PolukranosWorldEaterEffect copy() {
return new PolukranosWorldEaterEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
if (source.getTargets().size() > 0) {
Target multiTarget = source.getTargets().get(0);
Set<Permanent> permanents = new HashSet<Permanent>();
for (UUID target: multiTarget.getTargets()) {
Permanent permanent = game.getPermanent(target);
if (permanent != null) {
permanents.add(permanent);
permanent.damage(multiTarget.getTargetAmount(target), source.getSourceId(), game, true, false);
}
}
// Each of those creatures deals damage equal to its power to Polukranos
Permanent sourceCreature = game.getPermanent(source.getSourceId());
if (sourceCreature != null) {
for (Permanent permanent :permanents) {
sourceCreature.damage(permanent.getPower().getValue(), source.getSourceId(), game, true, false);
}
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,272 @@
/*
* 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.theros;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.Mode;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileSourceEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.TargetController;
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.players.Player;
import mage.target.Target;
import mage.target.common.TargetCardInGraveyard;
import mage.target.common.TargetCardInYourGraveyard;
import mage.target.common.TargetControlledCreaturePermanent;
/**
*
* Once you announce youre casting Rescue from the Underworld, no player may attempt to
* stop you from casting the spell by removing the creature you want to sacrifice.
*
* If you sacrifice a creature token to cast Rescue from the Underworld, it wont return
* to the battlefield, although the target creature card will.
*
* If either the sacrificed creature or the target creature card leaves the graveyard
* before the delayed triggered ability resolves during your next upkeep, it wont return.
*
* However, if the sacrificed creature is put into another public zone instead of the graveyard,
* perhaps because its your commander or because of another replacement effect, it will return
* to the battlefield from the zone it went to.
*
* Rescue from the Underworld is exiled as it resolves, not later as its delayed trigger resolves.
*
*
* @author LevelX2
*/
public class RescueFromTheUnderworld extends CardImpl<RescueFromTheUnderworld> {
public RescueFromTheUnderworld(UUID ownerId) {
super(ownerId, 102, "Rescue from the Underworld", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{4}{B}");
this.expansionSetCode = "THS";
this.color.setBlack(true);
// As an additional cost to cast Rescue from the Underworld, sacrifice a creature.
this.getSpellAbility().addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent()));
// Choose target creature card in your graveyard. Return that card and the sacrificed card to the battlefield under your control at the beginning of your next upkeep. Exile Rescue from the Underworld.
this.getSpellAbility().addEffect(new RescueFromTheUnderworldTextEffect());
this.getSpellAbility().addEffect(new RescueFromTheUnderworldCreateDelayedTriggeredAbilityEffect(new RescueFromTheUnderworldDelayedTriggeredAbility()));
Target target = new TargetCardInYourGraveyard(new FilterCreatureCard("creature card in your graveyard"));
target.setRequired(true);
this.getSpellAbility().addTarget(target);
this.getSpellAbility().addEffect(new ExileSourceEffect());
}
public RescueFromTheUnderworld(final RescueFromTheUnderworld card) {
super(card);
}
@Override
public RescueFromTheUnderworld copy() {
return new RescueFromTheUnderworld(this);
}
}
class RescueFromTheUnderworldTextEffect extends OneShotEffect<RescueFromTheUnderworldTextEffect> {
public RescueFromTheUnderworldTextEffect() {
super(Outcome.Benefit);
this.staticText = "Choose target creature card in your graveyard";
}
public RescueFromTheUnderworldTextEffect(final RescueFromTheUnderworldTextEffect effect) {
super(effect);
}
@Override
public RescueFromTheUnderworldTextEffect copy() {
return new RescueFromTheUnderworldTextEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
}
class RescueFromTheUnderworldCreateDelayedTriggeredAbilityEffect extends OneShotEffect<RescueFromTheUnderworldCreateDelayedTriggeredAbilityEffect> {
protected DelayedTriggeredAbility ability;
public RescueFromTheUnderworldCreateDelayedTriggeredAbilityEffect(DelayedTriggeredAbility ability) {
super(ability.getEffects().get(0).getOutcome());
this.ability = ability;
}
public RescueFromTheUnderworldCreateDelayedTriggeredAbilityEffect(final RescueFromTheUnderworldCreateDelayedTriggeredAbilityEffect effect) {
super(effect);
this.ability = effect.ability.copy();
}
@Override
public RescueFromTheUnderworldCreateDelayedTriggeredAbilityEffect copy() {
return new RescueFromTheUnderworldCreateDelayedTriggeredAbilityEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
DelayedTriggeredAbility delayedAbility = (DelayedTriggeredAbility) ability.copy();
delayedAbility.setSourceId(source.getSourceId());
delayedAbility.setControllerId(source.getControllerId());
delayedAbility.getTargets().addAll(source.getTargets());
for(Effect effect : delayedAbility.getEffects()) {
effect.getTargetPointer().init(game, source);
}
// add the scraificed creature as target
for (Cost cost :source.getCosts()) {
if (cost instanceof SacrificeTargetCost) {
SacrificeTargetCost sacCost = (SacrificeTargetCost) cost;
TargetCardInGraveyard target = new TargetCardInGraveyard();
for(Permanent permanent : sacCost.getPermanents()) {
target.add(permanent.getId(), game);
delayedAbility.getTargets().add(target);
}
}
}
game.addDelayedTriggeredAbility(delayedAbility);
return true;
}
@Override
public String getText(Mode mode) {
return ability.getRule();
}
}
class RescueFromTheUnderworldDelayedTriggeredAbility extends DelayedTriggeredAbility<RescueFromTheUnderworldDelayedTriggeredAbility> {
public RescueFromTheUnderworldDelayedTriggeredAbility() {
this(new RescueFromTheUnderworldReturnEffect(), TargetController.YOU);
}
public RescueFromTheUnderworldDelayedTriggeredAbility(Effect effect, TargetController targetController) {
super(effect);
}
public RescueFromTheUnderworldDelayedTriggeredAbility(RescueFromTheUnderworldDelayedTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.UPKEEP_STEP_PRE && event.getPlayerId().equals(this.controllerId)) {
return true;
}
return false;
}
@Override
public RescueFromTheUnderworldDelayedTriggeredAbility copy() {
return new RescueFromTheUnderworldDelayedTriggeredAbility(this);
}
@Override
public String getRule() {
return "Return that card and the sacrificed card to the battlefield under your control at the beginning of your next upkeep";
}
}
class RescueFromTheUnderworldReturnEffect extends OneShotEffect<RescueFromTheUnderworldReturnEffect> {
private boolean tapped;
public RescueFromTheUnderworldReturnEffect() {
this(false);
}
public RescueFromTheUnderworldReturnEffect(boolean tapped) {
super(Outcome.PutCreatureInPlay);
this.tapped = tapped;
}
public RescueFromTheUnderworldReturnEffect(final RescueFromTheUnderworldReturnEffect effect) {
super(effect);
this.tapped = effect.tapped;
}
@Override
public RescueFromTheUnderworldReturnEffect copy() {
return new RescueFromTheUnderworldReturnEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
boolean result = false;
// Target card comes only back if in graveyard
for (UUID targetId: getTargetPointer().getTargets(game, source)) {
Card card = game.getCard(targetId);
if (card != null) {
Player player = game.getPlayer(card.getOwnerId());
if (player != null) {
if(card.putOntoBattlefield(game, Zone.GRAVEYARD, source.getSourceId(), source.getControllerId(), tapped)){
result = true;
}
}
}
}
// However, if the sacrificed creature is put into another public zone instead of the graveyard,
// perhaps because its your commander or because of another replacement effect, it will return
// to the battlefield from the zone it went to.
if (source.getTargets().get(1) != null) {
for (UUID targetId: ((Target) source.getTargets().get(1)).getTargets()) {
Card card = game.getCard(targetId);
if (card != null && !card.isFaceDown()) {
Player player = game.getPlayer(card.getOwnerId());
if (player != null) {
Zone currentZone = game.getState().getZone(card.getId());
if (currentZone.equals(Zone.COMMAND) || currentZone.equals(Zone.GRAVEYARD) || currentZone.equals(Zone.EXILED)) {
if(card.putOntoBattlefield(game, currentZone, source.getSourceId(), source.getControllerId(), false)){
result = true;
}
}
}
}
}
}
return result;
}
}

View file

@ -0,0 +1,151 @@
/*
* 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.theros;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.FightTargetsEffect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.TargetController;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.ControllerPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.target.Target;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetCreaturePermanent;
/**
* Time to Feed has two targets: a creature an opponent controls and a creature you control.
* If only one of those creatures is a legal target when Time to Feed tries to resolve, the
* creatures wont fight and neither will deal or be dealt damage. However, youll still gain
* 3 life when the creature you dont control dies that turn, even if it was the illegal target as Time to Feed resolved.
* If neither creature is a legal target when Time to Feed tries to resolve, the spell will
* be countered and none of its effects will happen.
* If the first target creature dies that turn, youll gain 3 life no matter what caused the creature to die or who controls the creature at that time.
*
* @author LevelX2
*/
public class TimeToFeed extends CardImpl<TimeToFeed> {
private static final FilterCreaturePermanent filter1 = new FilterCreaturePermanent("creature an opponent controls");
static {
filter1.add(new ControllerPredicate(TargetController.OPPONENT));
}
public TimeToFeed(UUID ownerId) {
super(ownerId, 181, "Time to Feed", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{G}");
this.expansionSetCode = "THS";
this.color.setGreen(true);
// Choose target creature an opponent controls. When that creature dies this turn, you gain 3 life. Target creature you control fights that creature.
this.getSpellAbility().addEffect(new TimeToFeedTextEffect());
Target target = new TargetCreaturePermanent(filter1);
target.setRequired(true);
this.getSpellAbility().addTarget(target);
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(true));
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new TimeToFeedDiesTargetTriggeredAbility()));
Effect effect = new FightTargetsEffect();
effect.setText("Target creature you control fights that creature");
this.getSpellAbility().addEffect(effect);
}
public TimeToFeed(final TimeToFeed card) {
super(card);
}
@Override
public TimeToFeed copy() {
return new TimeToFeed(this);
}
}
class TimeToFeedTextEffect extends OneShotEffect<TimeToFeedTextEffect> {
public TimeToFeedTextEffect() {
super(Outcome.Detriment);
this.staticText = "Choose target creature an opponent controls";
}
public TimeToFeedTextEffect(final TimeToFeedTextEffect effect) {
super(effect);
}
@Override
public TimeToFeedTextEffect copy() {
return new TimeToFeedTextEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
}
class TimeToFeedDiesTargetTriggeredAbility extends DelayedTriggeredAbility<TimeToFeedDiesTargetTriggeredAbility> {
public TimeToFeedDiesTargetTriggeredAbility() {
super(new GainLifeEffect(3), Duration.EndOfTurn, false);
}
public TimeToFeedDiesTargetTriggeredAbility(final TimeToFeedDiesTargetTriggeredAbility ability) {
super(ability);
}
@Override
public TimeToFeedDiesTargetTriggeredAbility copy() {
return new TimeToFeedDiesTargetTriggeredAbility(this);
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.ZONE_CHANGE && ((ZoneChangeEvent)event).isDiesEvent()) {
if (event.getTargetId().equals(getEffects().get(0).getTargetPointer().getFirst(game, this))) {
return true;
}
}
return false;
}
@Override
public String getRule() {
return "When that creature dies this turn, " + super.getRule();
}
}

View file

@ -40,12 +40,15 @@ import mage.game.events.GameEvent.EventType;
*/
public class BecomesMonstrousSourceTriggeredAbility extends TriggeredAbilityImpl<BecomesMonstrousSourceTriggeredAbility> {
private int monstrosityValue;
public BecomesMonstrousSourceTriggeredAbility(Effect effect) {
super(Zone.BATTLEFIELD, effect, false);
}
public BecomesMonstrousSourceTriggeredAbility(final BecomesMonstrousSourceTriggeredAbility ability) {
super(ability);
this.monstrosityValue = ability.monstrosityValue;
}
@Override
@ -56,11 +59,16 @@ public class BecomesMonstrousSourceTriggeredAbility extends TriggeredAbilityImpl
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getType().equals(EventType.BECOMES_MONSTROUS) && event.getSourceId().equals(this.getSourceId())) {
this.monstrosityValue = event.getAmount();
return true;
}
return false;
}
public int getMonstrosityValue() {
return monstrosityValue;
}
@Override
public String getRule() {
return "When {this} becomes monstrous, " + super.getRule();

View file

@ -72,8 +72,8 @@ public class CreateDelayedTriggeredAbilityEffect extends OneShotEffect<CreateDel
delayedAbility.setControllerId(source.getControllerId());
if (this.copyTargets) {
delayedAbility.getTargets().addAll(source.getTargets());
for(Effect effect : ability.getEffects()) {
effect.setTargetPointer(targetPointer);
for(Effect effect : delayedAbility.getEffects()) {
effect.getTargetPointer().init(game, source);
}
}
game.addDelayedTriggeredAbility(delayedAbility);

View file

@ -30,10 +30,7 @@ package mage.abilities.keyword;
import mage.abilities.Ability;
import mage.abilities.ActivatedAbilityImpl;
import mage.abilities.condition.InvertCondition;
import mage.abilities.condition.common.MonstrousCondition;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.constants.Outcome;
@ -44,8 +41,29 @@ import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.util.CardUtil;
/**
* Monstrosity
*
* 701.28. Monstrosity
*
* 701.28a Monstrosity N means If this permanent isnt monstrous, put N +1/+1 counters on it
* and it becomes monstrous. Monstrous is a condition of that permanent that can be
* referred to by other abilities.
*
* 701.28b If a permanents ability instructs a player to monstrosity X, other abilities of
* that permanent may also refer to X. The value of X in those abilities is equal to
* the value of X as that permanent became monstrous.
*
* * Once a creature becomes monstrous, it cant become monstrous again. If the creature
* is already monstrous when the monstrosity ability resolves, nothing happens.
*
* * Monstrous isnt an ability that a creature has. Its just something true about that
* creature. If the creature stops being a creature or loses its abilities, it will
* continue to be monstrous.
*
* * An ability that triggers when a creature becomes monstrous wont trigger if that creature
* isnt on the battlefield when its monstrosity ability resolves.
*
* @author LevelX2
*/
@ -54,15 +72,13 @@ public class MonstrosityAbility extends ActivatedAbilityImpl<MonstrosityAbility>
private int monstrosityValue;
/**
*
* @param manaString
* @param monstrosityValue use Integer.MAX_VALUE for monstrosity X.
*/
public MonstrosityAbility(String manaString, int monstrosityValue) {
super(Zone.BATTLEFIELD, new ConditionalOneShotEffect(
new AddCountersSourceEffect(CounterType.P1P1.createInstance(monstrosityValue)),
new InvertCondition(MonstrousCondition.getInstance()),
""), new ManaCostsImpl(manaString));
this.addEffect(new ConditionalOneShotEffect(
new BecomeMonstrousSourceEffect(),
new InvertCondition(MonstrousCondition.getInstance()),""));
super(Zone.BATTLEFIELD, new BecomeMonstrousSourceEffect(),new ManaCostsImpl(manaString));
this.monstrosityValue = monstrosityValue;
}
@ -78,13 +94,20 @@ public class MonstrosityAbility extends ActivatedAbilityImpl<MonstrosityAbility>
@Override
public String getRule() {
return new StringBuilder(manaCosts.getText()).append(": Monstrosity ").append(monstrosityValue)
.append(". <i>(If this creature isn't monstrous, put ").append(CardUtil.numberToText(monstrosityValue))
return new StringBuilder(manaCosts.getText()).append(": Monstrosity ")
.append(monstrosityValue == Integer.MAX_VALUE ? "X":monstrosityValue)
.append(". <i>(If this creature isn't monstrous, put ")
.append(monstrosityValue == Integer.MAX_VALUE ? "X":CardUtil.numberToText(monstrosityValue))
.append(" +1/+1 counters on it and it becomes monstrous.)</i>").toString();
}
}
public int getMonstrosityValue() {
return monstrosityValue;
}
}
class BecomeMonstrousSourceEffect extends OneShotEffect<BecomeMonstrousSourceEffect> {
public BecomeMonstrousSourceEffect() {
@ -104,9 +127,15 @@ class BecomeMonstrousSourceEffect extends OneShotEffect<BecomeMonstrousSourceEff
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
if (permanent != null && !permanent.isMonstrous() && source instanceof MonstrosityAbility) {
int monstrosityValue = ((MonstrosityAbility) source).getMonstrosityValue();
// handle monstrosity = X
if (monstrosityValue == Integer.MAX_VALUE) {
monstrosityValue = source.getManaCostsToPay().getX();
}
new AddCountersSourceEffect(CounterType.P1P1.createInstance(monstrosityValue)).apply(game, source);
permanent.setMonstrous(true);
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BECOMES_MONSTROUS, source.getSourceId(), source.getSourceId(), source.getControllerId()));
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BECOMES_MONSTROUS, source.getSourceId(), source.getSourceId(), source.getControllerId(), monstrosityValue));
return true;
}
return false;