Implement cards: Caribou Range, Fatespinner, Hibernation's End, and Safe Haven

This commit is contained in:
LoneFox 2015-10-07 12:25:31 +03:00
parent 3a426e3cd8
commit 06f61ce616
9 changed files with 662 additions and 0 deletions

View file

@ -0,0 +1,141 @@
/*
* 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.coldsnap;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect;
import mage.abilities.keyword.CumulativeUpkeepAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.Filter;
import mage.filter.FilterCard;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
import mage.game.Game;
import mage.game.events.GameEvent.EventType;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCardInLibrary;
/**
*
* @author LoneFox
*/
public class HibernationsEnd extends CardImpl {
public HibernationsEnd(UUID ownerId) {
super(ownerId, 110, "Hibernation's End", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{4}{G}");
this.expansionSetCode = "CSP";
// Cumulative upkeep {1}
this.addAbility(new CumulativeUpkeepAbility(new ManaCostsImpl("{1}")));
// Whenever you pay Hibernation's End's cumulative upkeep, you may search your library for a creature card with converted mana cost equal to the number of age counters on Hibernation's End and put it onto the battlefield. If you do, shuffle your library.
this.addAbility(new HibernationsEndAbility());
}
public HibernationsEnd(final HibernationsEnd card) {
super(card);
}
@Override
public HibernationsEnd copy() {
return new HibernationsEnd(this);
}
}
class HibernationsEndAbility extends TriggeredAbilityImpl {
public HibernationsEndAbility() {
super(Zone.BATTLEFIELD, new HibernationsEndEffect(), true);
}
public HibernationsEndAbility(final HibernationsEndAbility ability) {
super(ability);
}
@Override
public HibernationsEndAbility copy() {
return new HibernationsEndAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == EventType.PAID_CUMULATIVE_UPKEEP;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return event.getSourceId() == this.getSourceId();
}
@Override
public String getRule() {
return "Whenever you pay {this}'s cumulative upkeep, " + super.getRule();
}
}
class HibernationsEndEffect extends OneShotEffect {
public HibernationsEndEffect() {
super(Outcome.Benefit);
this.staticText = "search your library for a creature card with converted mana cost equal to the number of age counters on {this} and put it onto the battlefield. If you do, shuffle your library.";
}
public HibernationsEndEffect(final HibernationsEndEffect effect) {
super(effect);
}
@Override
public HibernationsEndEffect copy() {
return new HibernationsEndEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
if(sourcePermanent != null && player != null) {
int newConvertedCost = sourcePermanent.getCounters().getCount("age");
FilterCard filter = new FilterCard("creature card with converted mana cost " + newConvertedCost);
filter.add(new ConvertedManaCostPredicate(Filter.ComparisonType.Equal, newConvertedCost));
filter.add(new CardTypePredicate(CardType.CREATURE));
TargetCardInLibrary target = new TargetCardInLibrary(filter);
return new SearchLibraryPutInPlayEffect(target).apply(game, source);
}
return false;
}
}

View file

@ -0,0 +1,114 @@
/*
* 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.fifthedition;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterControlledLandPermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.predicate.permanent.TokenPredicate;
import mage.game.permanent.token.Token;
import mage.target.TargetPermanent;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetControlledPermanent;
/**
*
* @author LoneFox
*/
public class CaribouRange extends CardImpl {
static FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("a Caribou token");
static {
filter.add(new TokenPredicate());
filter.add(new SubtypePredicate("Caribou"));
}
public CaribouRange(UUID ownerId) {
super(ownerId, 290, "Caribou Range", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}");
this.expansionSetCode = "5ED";
this.subtype.add("Aura");
// Enchant land you control
TargetPermanent auraTarget = new TargetControlledPermanent(new FilterControlledLandPermanent("land you control"));
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility));
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
// Enchanted land has "{W}{W}, {T}: Put a 0/1 white Caribou creature token onto the battlefield."
ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new CaribouToken()), new ManaCostsImpl("{W}{W}"));
ability.addCost(new TapSourceCost());
Effect effect = new GainAbilityAttachedEffect(ability, AttachmentType.AURA);
effect.setText("Enchanted land has \"{W}{W}, {T}: Put a 0/1 white Caribou creature token onto the battlefield.\"");
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
// Sacrifice a Caribou token: You gain 1 life.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainLifeEffect(1),
new SacrificeTargetCost(new TargetControlledCreaturePermanent(filter))));
}
public CaribouRange(final CaribouRange card) {
super(card);
}
@Override
public CaribouRange copy() {
return new CaribouRange(this);
}
}
class CaribouToken extends Token {
public CaribouToken() {
super("Caribou", "0/1 white Caribou creature token");
cardType.add(CardType.CREATURE);
color.setWhite(true);
subtype.add("Caribou");
power = new MageInt(0);
toughness = new MageInt(1);
}
}

View 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.iceage;
import java.util.UUID;
/**
*
* @author LoneFox
*/
public class CaribouRange extends mage.sets.fifthedition.CaribouRange {
public CaribouRange(UUID ownerId) {
super(ownerId);
this.cardNumber = 235;
this.expansionSetCode = "ICE";
}
public CaribouRange(final CaribouRange card) {
super(card);
}
@Override
public CaribouRange copy() {
return new CaribouRange(this);
}
}

View 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.masterseditionii;
import java.util.UUID;
/**
*
* @author LoneFox
*/
public class CaribouRange extends mage.sets.fifthedition.CaribouRange {
public CaribouRange(UUID ownerId) {
super(ownerId);
this.cardNumber = 8;
this.expansionSetCode = "ME2";
}
public CaribouRange(final CaribouRange card) {
super(card);
}
@Override
public CaribouRange copy() {
return new CaribouRange(this);
}
}

View file

@ -0,0 +1,168 @@
/*
* 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.mirrodin;
import java.util.HashSet;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.cards.CardImpl;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent.EventType;
import mage.game.events.GameEvent;
import mage.players.Player;
/**
*
* @author LoneFox
*/
public class Fatespinner extends CardImpl {
public Fatespinner(UUID ownerId) {
super(ownerId, 36, "Fatespinner", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{1}{U}{U}");
this.expansionSetCode = "MRD";
this.subtype.add("Human");
this.subtype.add("Wizard");
this.power = new MageInt(1);
this.toughness = new MageInt(2);
// At the beginning of each opponent's upkeep, that player chooses draw step, main phase, or combat phase. The player skips each instance of the chosen step or phase this turn.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new FatespinnerChooseEffect(),
TargetController.OPPONENT, false, true));
}
public Fatespinner(final Fatespinner card) {
super(card);
}
@java.lang.Override
public Fatespinner copy() {
return new Fatespinner(this);
}
}
class FatespinnerChooseEffect extends OneShotEffect {
private static final HashSet<String> choices = new HashSet<>();
static {
choices.add("Draw step");
choices.add("Main phase");
choices.add("Combat phase");
}
public FatespinnerChooseEffect() {
super(Outcome.Detriment);
staticText = "At the beginning of each opponent's upkeep, that player chooses draw step, main phase, or combat phase. The player skips each instance of the chosen step or phase this turn.";
}
public FatespinnerChooseEffect(final FatespinnerChooseEffect effect) {
super(effect);
}
@java.lang.Override
public FatespinnerChooseEffect copy() {
return new FatespinnerChooseEffect(this);
}
@java.lang.Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
if(player != null) {
Choice choice = new ChoiceImpl(true);
choice.setMessage("Choose phase or step to skip");
choice.setChoices(choices);
while(!player.choose(outcome, choice, game)) {
if(player.canRespond()) {
return false;
}
}
String chosenPhase = choice.getChoice();
game.informPlayers(player.getLogName() + " has chosen to skip " + chosenPhase.toLowerCase() + ".");
game.addEffect(new FatespinnerSkipEffect(chosenPhase), source);
return true;
}
return false;
}
}
class FatespinnerSkipEffect extends ReplacementEffectImpl {
private final String phase;
public FatespinnerSkipEffect(String phase) {
super(Duration.EndOfTurn, Outcome.Detriment);
this.phase = phase;
}
public FatespinnerSkipEffect(final FatespinnerSkipEffect effect) {
super(effect);
this.phase = effect.phase;
}
@java.lang.Override
public FatespinnerSkipEffect copy() {
return new FatespinnerSkipEffect(this);
}
@java.lang.Override
public boolean apply(Game game, Ability source) {
return true;
}
@java.lang.Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
EventType type = event.getType();
return ((phase.equals("Draw step") && type == EventType.DRAW_STEP)
|| (phase.equals("Main phase") && (type == EventType.PRECOMBAT_MAIN_PHASE || type == EventType.POSTCOMBAT_MAIN_PHASE))
|| (phase.equals("Combat phase") && type == EventType.COMBAT_PHASE));
}
@java.lang.Override
public boolean checksEventType(GameEvent event, Game game) {
EventType type = event.getType();
return (type == EventType.DRAW_STEP || type == EventType.PRECOMBAT_MAIN_PHASE
|| type == EventType.POSTCOMBAT_MAIN_PHASE || type == EventType.COMBAT_PHASE);
}
@java.lang.Override
public boolean applies(GameEvent event, Ability source, Game game) {
return true;
}
}

View file

@ -0,0 +1,78 @@
/*
* 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.thedark;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.effects.common.ReturnFromExileEffect;
import mage.abilities.effects.common.SacrificeSourceEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.target.common.TargetControlledCreaturePermanent;
/**
*
* @author LoneFox
*/
public class SafeHaven extends CardImpl {
public SafeHaven(UUID ownerId) {
super(ownerId, 115, "Safe Haven", Rarity.RARE, new CardType[]{CardType.LAND}, "");
this.expansionSetCode = "DRK";
// {2}, {tap}: Exile target creature you control.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileTargetEffect(this.getId(),
this.getIdName()), new ManaCostsImpl("{2}"));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetControlledCreaturePermanent());
this.addAbility(ability);
// At the beginning of your upkeep, you may sacrifice Safe Haven. If you do, return each card exiled with Safe Haven to the battlefield under its owner's control.
ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new SacrificeSourceEffect(),
TargetController.YOU, true);
ability.addEffect(new ReturnFromExileEffect(this.getId(), Zone.BATTLEFIELD,
"If you do, return each card exiled with {this} to the battlefield under its owner's control"));
this.addAbility(ability);
}
public SafeHaven(final SafeHaven card) {
super(card);
}
@Override
public SafeHaven copy() {
return new SafeHaven(this);
}
}

View 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.timeshifted;
import java.util.UUID;
import mage.constants.Rarity;
/**
*
* @author LoneFox
*/
public class SafeHaven extends mage.sets.thedark.SafeHaven {
public SafeHaven(UUID ownerId) {
super(ownerId);
this.cardNumber = 121;
this.expansionSetCode = "TSB";
this.rarity = Rarity.SPECIAL;
}
public SafeHaven(final SafeHaven card) {
super(card);
}
@Override
public SafeHaven copy() {
return new SafeHaven(this);
}
}

View file

@ -107,6 +107,7 @@ class CumulativeUpkeepEffect extends OneShotEffect {
if (player.chooseUse(Outcome.Benefit, "Pay " + totalCost.getText() + "?", source, game)) { if (player.chooseUse(Outcome.Benefit, "Pay " + totalCost.getText() + "?", source, game)) {
totalCost.clearPaid(); totalCost.clearPaid();
if (totalCost.payOrRollback(source, game, source.getSourceId(), source.getControllerId())) { if (totalCost.payOrRollback(source, game, source.getSourceId(), source.getControllerId())) {
game.fireEvent(new GameEvent(EventType.PAID_CUMULATIVE_UPKEEP, permanent.getId(), permanent.getId(), player.getId(), ageCounter, false));
return true; return true;
} }
} }
@ -122,6 +123,7 @@ class CumulativeUpkeepEffect extends OneShotEffect {
totalCost.clearPaid(); totalCost.clearPaid();
int bookmark = game.bookmarkState(); int bookmark = game.bookmarkState();
if (totalCost.pay(source, game, source.getSourceId(), source.getControllerId(), false)) { if (totalCost.pay(source, game, source.getSourceId(), source.getControllerId(), false)) {
game.fireEvent(new GameEvent(EventType.PAID_CUMULATIVE_UPKEEP, permanent.getId(), permanent.getId(), player.getId(), ageCounter, false));
return true; return true;
} else { } else {
game.restoreState(bookmark, source.getRule()); game.restoreState(bookmark, source.getRule());

View file

@ -185,6 +185,7 @@ public class GameEvent implements Serializable {
ENCHANT_PLAYER, ENCHANTED_PLAYER, ENCHANT_PLAYER, ENCHANTED_PLAYER,
CAN_TAKE_MULLIGAN, CAN_TAKE_MULLIGAN,
FLIP_COIN, COIN_FLIPPED, SCRY, FATESEAL, FLIP_COIN, COIN_FLIPPED, SCRY, FATESEAL,
PAID_CUMULATIVE_UPKEEP,
DIDNT_PAY_CUMULATIVE_UPKEEP, DIDNT_PAY_CUMULATIVE_UPKEEP,
//permanent events //permanent events
ENTERS_THE_BATTLEFIELD, ENTERS_THE_BATTLEFIELD,