Merge branch 'master' into master

This commit is contained in:
LevelX2 2018-04-18 11:02:14 +02:00 committed by GitHub
commit e354335a6c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 1390 additions and 19 deletions

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.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.keyword.KickerAbility;
import mage.abilities.keyword.MenaceAbility;
import mage.constants.SubType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.stack.Spell;
/**
*
* @author TheElk801
*/
public class BloodstoneGoblin extends CardImpl {
public BloodstoneGoblin(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");
this.subtype.add(SubType.GOBLIN);
this.subtype.add(SubType.WARRIOR);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Whenever you cast a spell, if that spell was kicked, Bloodstone Goblin gets +1/+1 and gains menace until end of turn.
this.addAbility(new BloodstoneGoblinTriggeredAbility());
}
public BloodstoneGoblin(final BloodstoneGoblin card) {
super(card);
}
@Override
public BloodstoneGoblin copy() {
return new BloodstoneGoblin(this);
}
}
class BloodstoneGoblinTriggeredAbility extends TriggeredAbilityImpl {
BloodstoneGoblinTriggeredAbility() {
super(Zone.BATTLEFIELD, new BoostSourceEffect(1, 1, Duration.EndOfTurn).setText("{this} gets +1/+1"), true);
this.addEffect(new GainAbilitySourceEffect(new MenaceAbility(), Duration.EndOfTurn).setText("and gains menace until end of turn"));
}
BloodstoneGoblinTriggeredAbility(final BloodstoneGoblinTriggeredAbility ability) {
super(ability);
}
@Override
public BloodstoneGoblinTriggeredAbility copy() {
return new BloodstoneGoblinTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.SPELL_CAST;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Spell spell = game.getStack().getSpell(event.getTargetId());
if (spell != null && spell.getControllerId().equals(controllerId)) {
for (Ability ability : spell.getAbilities()) {
if (ability instanceof KickerAbility && ((KickerAbility) ability).getKickedCounter(game, spell.getSpellAbility()) > 0) {
return true;
}
}
}
return false;
}
@Override
public String getRule() {
return "Whenever you cast a spell, if it was kicked," + super.getRule();
}
}

View file

@ -0,0 +1,122 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.c;
import java.util.LinkedList;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.EquippedPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
/**
*
* @author rscoates
*/
public class CorrosiveOoze extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("equipped creature");
static {
filter.add(new EquippedPredicate());
}
public CorrosiveOoze(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}");
this.subtype.add(SubType.OOZE);
this.color.setGreen(true);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Whenever Corrosive Ooze blocks or becomes blocked by an equipped creature, destroy all Equipment attached to that creature at end of combat.
Effect effect = new CreateDelayedTriggeredAbilityEffect(new AtTheEndOfCombatDelayedTriggeredAbility(new CorrosiveOozeEffect()), true);
this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(effect, filter, false));
}
public CorrosiveOoze(final CorrosiveOoze card) {
super(card);
}
@Override
public CorrosiveOoze copy() {
return new CorrosiveOoze(this);
}
}
class CorrosiveOozeEffect extends OneShotEffect {
public CorrosiveOozeEffect() {
super(Outcome.DestroyPermanent);
}
public CorrosiveOozeEffect(final CorrosiveOozeEffect effect) {
super(effect);
}
@Override
public CorrosiveOozeEffect copy() {
return new CorrosiveOozeEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent != null) {
LinkedList<UUID> attachments = new LinkedList();
attachments.addAll(permanent.getAttachments());
for (UUID uuid : attachments) {
Permanent attachment = game.getPermanent(uuid);
if (attachment != null && attachment.hasSubtype(SubType.EQUIPMENT, game)) {
attachment.destroy(source.getSourceId(), game, false);
}
}
return true;
}
return false;
}
@Override
public String getText(Mode mode) {
return "destroy all Equipment attached to that creature at end of combat";
}
}

View file

@ -0,0 +1,85 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.f;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.condition.common.KickedCondition;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.common.DamageMultiEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.keyword.KickerAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.game.Game;
import mage.target.common.TargetAnyTargetAmount;
/**
*
* @author TheElk801
*/
public class FightWithFire extends CardImpl {
public FightWithFire(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}");
// Kicker {5}{R}
this.addAbility(new KickerAbility("{5}{R}"));
// Fight with Fire deals 5 damage to target creature. If this spell was kicked, it deals 10 damage divided as you choose among any number of targets instead.<i> (Those targets can include players and planeswalkers.)</i>
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
new DamageMultiEffect(10),
new DamageTargetEffect(5),
KickedCondition.instance,
"{this} deals 5 damage to target creature. If this spell was kicked, "
+ "it deals 10 damage divided as you choose among any number of targets instead."
+ "<i> (Those targets can include players and planeswalkers.)</i>"
));
}
public FightWithFire(final FightWithFire card) {
super(card);
}
@Override
public void adjustTargets(Ability ability, Game game) {
if (ability instanceof SpellAbility) {
if (KickedCondition.instance.apply(game, ability)) {
ability.getTargets().clear();
getSpellAbility().addTarget(new TargetAnyTargetAmount(10));
}
}
}
@Override
public FightWithFire copy() {
return new FightWithFire(this);
}
}

View file

@ -52,7 +52,7 @@ import mage.constants.Zone;
public class FlamewakePhoenix extends CardImpl {
public FlamewakePhoenix(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{R}{R}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{R}");
this.subtype.add(SubType.PHOENIX);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
@ -68,7 +68,7 @@ public class FlamewakePhoenix extends CardImpl {
this.addAbility(new ConditionalTriggeredAbility(
new BeginningOfCombatTriggeredAbility(
Zone.GRAVEYARD,
new DoIfCostPaid(new ReturnToBattlefieldUnderOwnerControlSourceEffect(), new ManaCostsImpl("{R")),
new DoIfCostPaid(new ReturnToBattlefieldUnderOwnerControlSourceEffect(), new ManaCostsImpl("{R}")),
TargetController.YOU, false, false),
FerociousCondition.instance,
"<i>Ferocious</i> &mdash; At the beginning of combat on your turn, if you control a creature with power 4 or greater, you may pay {R}. If you do, return {this} from your graveyard to the battlefield."

View file

@ -0,0 +1,124 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.h;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.dynamicvalue.common.CountersSourceCount;
import mage.abilities.effects.common.DamagePlayersEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.KickerAbility;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.stack.Spell;
/**
*
* @author TheElk801
*/
public class HallarTheFirefletcher extends CardImpl {
public HallarTheFirefletcher(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{G}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.ELF);
this.subtype.add(SubType.ARCHER);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// Trample
this.addAbility(TrampleAbility.getInstance());
// Whenever you cast a spell, if that spell was kicked, put a +1/+1 counter on Hallar, the Firefletcher, then Hallar deals damage equal to the number of +1/+1 counters on it to each opponent.
this.addAbility(new HallarTheFirefletcherTriggeredAbility());
}
public HallarTheFirefletcher(final HallarTheFirefletcher card) {
super(card);
}
@Override
public HallarTheFirefletcher copy() {
return new HallarTheFirefletcher(this);
}
}
class HallarTheFirefletcherTriggeredAbility extends TriggeredAbilityImpl {
HallarTheFirefletcherTriggeredAbility() {
super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance()).setText("put a +1/+1 counter on {this}"), true);
this.addEffect(new DamagePlayersEffect(Outcome.Benefit, new CountersSourceCount(CounterType.P1P1), TargetController.OPPONENT)
.setText("then {this} deals damage equal to the number of +1/+1 counters on it to each opponent")
);
}
HallarTheFirefletcherTriggeredAbility(final HallarTheFirefletcherTriggeredAbility ability) {
super(ability);
}
@Override
public HallarTheFirefletcherTriggeredAbility copy() {
return new HallarTheFirefletcherTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.SPELL_CAST;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Spell spell = game.getStack().getSpell(event.getTargetId());
if (spell != null && spell.getControllerId().equals(controllerId)) {
for (Ability ability : spell.getAbilities()) {
if (ability instanceof KickerAbility && ((KickerAbility) ability).getKickedCounter(game, spell.getSpellAbility()) > 0) {
return true;
}
}
}
return false;
}
@Override
public String getRule() {
return "Whenever you cast a spell, if it was kicked," + super.getRule();
}
}

View file

@ -29,6 +29,7 @@ package mage.cards.o;
import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.AttacksWithCreaturesTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.CardImpl;
@ -45,10 +46,10 @@ import mage.game.events.GameEvent;
public class OverwhelmingInstinct extends CardImpl {
public OverwhelmingInstinct(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{G}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}");
// Whenever you attack with three or more creatures, draw a card.
this.addAbility(new OverwhelmingInstinctTriggeredAbility(new DrawCardSourceControllerEffect(1)));
this.addAbility(new AttacksWithCreaturesTriggeredAbility(new DrawCardSourceControllerEffect(1), 3));
}
public OverwhelmingInstinct(final OverwhelmingInstinct card) {
@ -88,6 +89,6 @@ class OverwhelmingInstinctTriggeredAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
return new StringBuilder("Whenever you attack with three or more creatures, ").append(super.getRule()).toString() ;
return new StringBuilder("Whenever you attack with three or more creatures, ").append(super.getRule()).toString();
}
}
}

View file

@ -0,0 +1,140 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.cards.Card;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.StackObject;
/**
*
* @author TheElk801
*/
public class ShannaSisaysLegacy extends CardImpl {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creatures you control");
public ShannaSisaysLegacy(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{W}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.WARRIOR);
this.power = new MageInt(0);
this.toughness = new MageInt(0);
// Shanna, Sisay's Legacy can't be the target of abilities your opponents control.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ShannaSisaysLegacyEffect()));
// Shanna gets +1/+1 for each creature you control.
DynamicValue value = new PermanentsOnBattlefieldCount(filter);
this.addAbility(new SimpleStaticAbility(
Zone.BATTLEFIELD,
new BoostSourceEffect(value, value, Duration.WhileOnBattlefield)
.setText("{this} gets +1/+1 for each creature you control")
));
}
public ShannaSisaysLegacy(final ShannaSisaysLegacy card) {
super(card);
}
@Override
public ShannaSisaysLegacy copy() {
return new ShannaSisaysLegacy(this);
}
}
class ShannaSisaysLegacyEffect extends ContinuousRuleModifyingEffectImpl {
public ShannaSisaysLegacyEffect() {
super(Duration.WhileOnBattlefield, Outcome.BoostCreature);
staticText = "{this} can't be the target of abilities your opponents control";
}
public ShannaSisaysLegacyEffect(final ShannaSisaysLegacyEffect effect) {
super(effect);
}
@Override
public ShannaSisaysLegacyEffect copy() {
return new ShannaSisaysLegacyEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public String getInfoMessage(Ability source, GameEvent event, Game game) {
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (sourcePermanent != null) {
return sourcePermanent.getLogName() + " can't be the target of abilities you control";
}
return null;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.TARGET;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
Card targetCard = game.getCard(event.getTargetId());
StackObject stackObject = (StackObject) game.getStack().getStackObject(event.getSourceId());
if (targetCard != null && stackObject != null && targetCard.getId().equals(source.getSourceId())) {
if (stackObject instanceof Ability) {
if (!stackObject.getControllerId().equals(source.getControllerId())) {
return true;
}
}
}
return false;
}
}

View file

@ -0,0 +1,86 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.s;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.SourceHasSubtypeCondition;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
import mage.abilities.keyword.EquipAbility;
import mage.constants.SubType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.target.common.TargetPlayerOrPlaneswalker;
/**
*
* @author TheElk801
*/
public class SorcerersWand extends CardImpl {
public SorcerersWand(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}");
this.subtype.add(SubType.EQUIPMENT);
// Equipped creature has "{T}: This creature deals 1 damage to target player or planeswalker. If this creature is a Wizard, it deals 2 damage to that player or planeswalker instead."
Ability ability = new SimpleActivatedAbility(
new ConditionalOneShotEffect(
new DamageTargetEffect(2),
new DamageTargetEffect(1),
new SourceHasSubtypeCondition(SubType.WIZARD),
"This creature deals 1 damage to target player or planeswalker. "
+ "If this creature is a Wizard, it deals 2 damage to that player or planeswalker instead."
), new TapSourceCost()
);
ability.addTarget(new TargetPlayerOrPlaneswalker());
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(ability, AttachmentType.EQUIPMENT)));
// Equip {3}
this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(3)));
}
public SorcerersWand(final SorcerersWand card) {
super(card);
}
@Override
public SorcerersWand copy() {
return new SorcerersWand(this);
}
}

View file

@ -0,0 +1,166 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.t;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author spjspj
*/
public class TianaShipsCaretaker extends CardImpl {
public TianaShipsCaretaker(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{W}");
addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.ANGEL);
this.subtype.add(SubType.ARTIFICER);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// Flying
this.addAbility(FlyingAbility.getInstance());
// First strike
this.addAbility(FirstStrikeAbility.getInstance());
// Whenever an Aura or Equipment you control is put into a graveyard from the battlefield, you may return that card to its owner's hand at the beginning of the next end step.
this.addAbility(new TianaShipsCaretakerTriggeredAbility());
}
public TianaShipsCaretaker(final TianaShipsCaretaker card) {
super(card);
}
@Override
public TianaShipsCaretaker copy() {
return new TianaShipsCaretaker(this);
}
}
class TianaShipsCaretakerTriggeredAbility extends TriggeredAbilityImpl {
TianaShipsCaretakerTriggeredAbility() {
super(Zone.BATTLEFIELD, new TianaShipsCaretakerEffect(), true);
}
TianaShipsCaretakerTriggeredAbility(final TianaShipsCaretakerTriggeredAbility ability) {
super(ability);
}
@Override
public TianaShipsCaretakerTriggeredAbility copy() {
return new TianaShipsCaretakerTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == EventType.ZONE_CHANGE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
if (zEvent.getTarget() == null) {
return false;
}
Permanent permanent = game.getPermanentOrLKIBattlefield(zEvent.getTarget().getId());
if (permanent != null
&& zEvent.getToZone() == Zone.GRAVEYARD
&& zEvent.getFromZone() == Zone.BATTLEFIELD
&& (permanent.isArtifact() && permanent.hasSubtype(SubType.EQUIPMENT, game)
|| permanent.isEnchantment() && permanent.hasSubtype(SubType.AURA, game))
&& permanent.getControllerId().equals(this.controllerId)) {
this.getEffects().setTargetPointer(new FixedTarget(zEvent.getTargetId()));
return true;
}
return false;
}
@Override
public String getRule() {
return "Whenever an Aura or Equipment you control is put into a graveyard from the battlefield, " + super.getRule();
}
}
class TianaShipsCaretakerEffect extends OneShotEffect {
TianaShipsCaretakerEffect() {
super(Outcome.PutCardInPlay);
this.staticText = "you may return that card to its owner's hand at the beginning of the next end step";
}
TianaShipsCaretakerEffect(final TianaShipsCaretakerEffect effect) {
super(effect);
}
@Override
public TianaShipsCaretakerEffect copy() {
return new TianaShipsCaretakerEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Card card = game.getCard(getTargetPointer().getFirst(game, source));
if (card != null && game.getState().getZone(card.getId()) == Zone.GRAVEYARD) {
Effect effect = new ReturnFromGraveyardToHandTargetEffect();
effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game)));
effect.setText("return that card to your hand at the beginning of the next end step");
game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), source);
return true;
}
return false;
}
}

View file

@ -0,0 +1,202 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.t;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.SacrificeXTargetCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.CostModificationType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
import mage.util.CardUtil;
/**
*
* @author LevelX2
*/
public class TorgaarFamineIncarnate extends CardImpl {
public TorgaarFamineIncarnate(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{B}{B}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.AVATAR);
this.power = new MageInt(7);
this.toughness = new MageInt(6);
// As an additional cost to cast this spell, you may sacrifice any number of creatures.
this.getSpellAbility().addCost(new SacrificeXTargetCost(StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT));
// This spell costs {2} less to cast for each creature sacrificed this way.
Ability ability = new SimpleStaticAbility(Zone.STACK, new TorgaarFamineIncarnateEffectCostReductionEffect());
this.addAbility(ability);
// When Torgaar, Famine Incarnate enters the battlefield, up to one target player's life total becomes half their starting life total, rounded down.
ability = new EntersBattlefieldTriggeredAbility(new TorgaarFamineIncarnateEffect(), false);
ability.addTarget(new TargetPlayer(0, 1, false));
this.addAbility(ability);
}
public TorgaarFamineIncarnate(final TorgaarFamineIncarnate card) {
super(card);
}
@Override
public TorgaarFamineIncarnate copy() {
return new TorgaarFamineIncarnate(this);
}
}
//class TorgaarFamineIncarnateSacrificeCost extends CostImpl {
//
// int numbSacrificed = 0;
//
// public TorgaarFamineIncarnateSacrificeCost() {
// this.text = "sacrifice any number of creatures";
//
// }
//
// public TorgaarFamineIncarnateSacrificeCost(final TorgaarFamineIncarnateSacrificeCost cost) {
// super(cost);
// this.numbSacrificed = cost.numbSacrificed;
// }
//
// @Override
// public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
// return true;
// }
//
// @Override
// public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) {
// TargetControlledCreaturePermanent target
// = new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE,
// new FilterControlledCreaturePermanent("select any number of creatures to sacrifice. "
// + "This spell costs {2} less to cast for each creature sacrificed this way"), true);
// Player player = game.getPlayer(controllerId);
// if (player != null) {
// player.chooseTarget(Outcome.Benefit, target, ability, game);
// for (UUID creatureId : target.getTargets()) {
// Permanent creature = game.getPermanent(creatureId);
// if (creature != null) {
// if (creature.sacrifice(sourceId, game)) {
// numbSacrificed++;
// }
// }
// }
// }
// this.paid = true;
// return paid;
// }
//
// public int getNumbSacrificed() {
// return numbSacrificed;
// }
//
// @Override
// public TorgaarFamineIncarnateSacrificeCost copy() {
// return new TorgaarFamineIncarnateSacrificeCost(this);
// }
//}
class TorgaarFamineIncarnateEffect extends OneShotEffect {
public TorgaarFamineIncarnateEffect() {
super(Outcome.Benefit);
this.staticText = "up to one target player's life total becomes half their starting life total, rounded down";
}
public TorgaarFamineIncarnateEffect(final TorgaarFamineIncarnateEffect effect) {
super(effect);
}
@Override
public TorgaarFamineIncarnateEffect copy() {
return new TorgaarFamineIncarnateEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source));
if (targetPlayer != null) {
int startingLifeTotal = game.getLife();
targetPlayer.setLife(startingLifeTotal / 2, game);
}
return true;
}
}
class TorgaarFamineIncarnateEffectCostReductionEffect extends CostModificationEffectImpl {
public TorgaarFamineIncarnateEffectCostReductionEffect() {
super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST);
staticText = "This spell costs {2} less to cast for each creature sacrificed this way";
}
public TorgaarFamineIncarnateEffectCostReductionEffect(final TorgaarFamineIncarnateEffectCostReductionEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source, Ability abilityToModify) {
SpellAbility spellAbility = (SpellAbility) abilityToModify;
for (Cost cost : spellAbility.getCosts()) {
if (cost instanceof SacrificeXTargetCost) {
int reduction = ((SacrificeXTargetCost) cost).getAmount();
CardUtil.adjustCost(spellAbility, reduction * 2);
break;
}
}
return true;
}
@Override
public boolean applies(Ability abilityToModify, Ability source, Game game) {
return abilityToModify instanceof SpellAbility && abilityToModify.getSourceId().equals(source.getSourceId());
}
@Override
public TorgaarFamineIncarnateEffectCostReductionEffect copy() {
return new TorgaarFamineIncarnateEffectCostReductionEffect(this);
}
}

View file

@ -0,0 +1,80 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.w;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.AttacksWithCreaturesTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.StaticFilters;
/**
*
* @author LevelX2
*/
public class WarcryPhoenix extends CardImpl {
public WarcryPhoenix(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
this.subtype.add(SubType.PHOENIX);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Haste
this.addAbility(HasteAbility.getInstance());
// Whenever you attack with three or more creatures, you may pay {2}{R}. If you do, return Warcry Phoenix from your graveyard to the battlefield tapped and attacking.
this.addAbility(new AttacksWithCreaturesTriggeredAbility(Zone.GRAVEYARD,
new DoIfCostPaid(new ReturnToBattlefieldUnderOwnerControlSourceEffect(true, true, -1),
new ManaCostsImpl("{2}{R}"))
.setText("you may pay {2}{R}. If you do, return {this} from your graveyard to the battlefield tapped and attacking"),
3, StaticFilters.FILTER_PERMANENT_CREATURES));
}
public WarcryPhoenix(final WarcryPhoenix card) {
super(card);
}
@Override
public WarcryPhoenix copy() {
return new WarcryPhoenix(this);
}
}

View file

@ -77,6 +77,7 @@ public class Dominaria extends ExpansionSet {
cards.add(new SetCardInfo("Blessed Light", 7, Rarity.UNCOMMON, mage.cards.b.BlessedLight.class));
cards.add(new SetCardInfo("Blessing of Belzenlok", 77, Rarity.COMMON, mage.cards.b.BlessingOfBelzenlok.class));
cards.add(new SetCardInfo("Blink of an Eye", 46, Rarity.COMMON, mage.cards.b.BlinkOfAnEye.class));
cards.add(new SetCardInfo("Bloodstone Goblin", 115, Rarity.COMMON, mage.cards.b.BloodstoneGoblin.class));
cards.add(new SetCardInfo("Bloodtallow Candle", 212, Rarity.COMMON, mage.cards.b.BloodtallowCandle.class));
cards.add(new SetCardInfo("Board the Weatherlight", 8, Rarity.UNCOMMON, mage.cards.b.BoardTheWeatherlight.class));
cards.add(new SetCardInfo("Broken Bond", 157, Rarity.COMMON, mage.cards.b.BrokenBond.class));
@ -95,6 +96,7 @@ public class Dominaria extends ExpansionSet {
cards.add(new SetCardInfo("Cloudreader Sphinx", 47, Rarity.COMMON, mage.cards.c.CloudreaderSphinx.class));
cards.add(new SetCardInfo("Cold-Water Snapper", 48, Rarity.COMMON, mage.cards.c.ColdWaterSnapper.class));
cards.add(new SetCardInfo("Curator's Ward", 49, Rarity.UNCOMMON, mage.cards.c.CuratorsWard.class));
cards.add(new SetCardInfo("Corrosive Ooze", 158, Rarity.COMMON, mage.cards.c.CorrosiveOoze.class));
cards.add(new SetCardInfo("D'Avenant Trapper", 11, Rarity.COMMON, mage.cards.d.DAvenantTrapper.class));
cards.add(new SetCardInfo("Damping Sphere", 213, Rarity.UNCOMMON, mage.cards.d.DampingSphere.class));
cards.add(new SetCardInfo("Danitha Capashen, Paragon", 12, Rarity.UNCOMMON, mage.cards.d.DanithaCapashenParagon.class));
@ -116,6 +118,7 @@ public class Dominaria extends ExpansionSet {
cards.add(new SetCardInfo("Feral Abomination", 92, Rarity.COMMON, mage.cards.f.FeralAbomination.class));
cards.add(new SetCardInfo("Fervent Strike", 117, Rarity.COMMON, mage.cards.f.FerventStrike.class));
cards.add(new SetCardInfo("Fiery Intervention", 118, Rarity.COMMON, mage.cards.f.FieryIntervention.class));
cards.add(new SetCardInfo("Fight with Fire", 119, Rarity.UNCOMMON, mage.cards.f.FightWithFire.class));
cards.add(new SetCardInfo("Final Parting", 93, Rarity.UNCOMMON, mage.cards.f.FinalParting.class));
cards.add(new SetCardInfo("Fire Elemental", 120, Rarity.COMMON, mage.cards.f.FireElemental.class));
cards.add(new SetCardInfo("Firefist Adept", 121, Rarity.UNCOMMON, mage.cards.f.FirefistAdept.class));
@ -142,6 +145,7 @@ public class Dominaria extends ExpansionSet {
cards.add(new SetCardInfo("Grow from the Ashes", 164, Rarity.COMMON, mage.cards.g.GrowFromTheAshes.class));
cards.add(new SetCardInfo("Grunn, the Lonely King", 165, Rarity.UNCOMMON, mage.cards.g.GrunnTheLonelyKing.class));
cards.add(new SetCardInfo("Guardians of Koilos", 216, Rarity.COMMON, mage.cards.g.GuardiansOfKoilos.class));
cards.add(new SetCardInfo("Hallar, the Firefletcher", 196, Rarity.UNCOMMON, mage.cards.h.HallarTheFirefletcher.class));
cards.add(new SetCardInfo("Helm of the Host", 217, Rarity.RARE, mage.cards.h.HelmOfTheHost.class));
cards.add(new SetCardInfo("Hinterland Harbor", 240, Rarity.RARE, mage.cards.h.HinterlandHarbor.class));
cards.add(new SetCardInfo("History of Benalia", 21, Rarity.MYTHIC, mage.cards.h.HistoryOfBenalia.class));
@ -200,7 +204,7 @@ public class Dominaria extends ExpansionSet {
cards.add(new SetCardInfo("Naban, Dean of Iteration", 58, Rarity.RARE, mage.cards.n.NabanDeanOfIteration.class));
cards.add(new SetCardInfo("Naru Meha, Master Wizard", 59, Rarity.MYTHIC, mage.cards.n.NaruMehaMasterWizard.class));
cards.add(new SetCardInfo("Nature's Spiral", 175, Rarity.UNCOMMON, mage.cards.n.NaturesSpiral.class));
cards.add(new SetCardInfo("Navigator's Compass", 175, Rarity.COMMON, mage.cards.n.NavigatorsCompass.class));
cards.add(new SetCardInfo("Navigator's Compass", 225, Rarity.COMMON, mage.cards.n.NavigatorsCompass.class));
cards.add(new SetCardInfo("Niambi, Faithful Healer", 272, Rarity.RARE, mage.cards.n.NiambiFaithfulHealer.class));
cards.add(new SetCardInfo("Oath of Teferi", 200, Rarity.RARE, mage.cards.o.OathOfTeferi.class));
cards.add(new SetCardInfo("On Serra's Wings", 28, Rarity.UNCOMMON, mage.cards.o.OnSerrasWings.class));
@ -235,6 +239,7 @@ public class Dominaria extends ExpansionSet {
cards.add(new SetCardInfo("Serra Disciple", 34, Rarity.COMMON, mage.cards.s.SerraDisciple.class));
cards.add(new SetCardInfo("Settle the Score", 103, Rarity.UNCOMMON, mage.cards.s.SettleTheScore.class));
cards.add(new SetCardInfo("Shalai, Voice of Plenty", 35, Rarity.RARE, mage.cards.s.ShalaiVoiceOfPlenty.class));
cards.add(new SetCardInfo("Shanna, Sisay's Legacy", 204, Rarity.UNCOMMON, mage.cards.s.ShannaSisaysLegacy.class));
cards.add(new SetCardInfo("Shivan Fire", 142, Rarity.COMMON, mage.cards.s.ShivanFire.class));
cards.add(new SetCardInfo("Short Sword", 229, Rarity.COMMON, mage.cards.s.ShortSword.class));
cards.add(new SetCardInfo("Siege-Gang Commander", 143, Rarity.RARE, mage.cards.s.SiegeGangCommander.class));
@ -244,6 +249,7 @@ public class Dominaria extends ExpansionSet {
cards.add(new SetCardInfo("Slimefoot, the Stowaway", 205, Rarity.UNCOMMON, mage.cards.s.SlimefootTheStowaway.class));
cards.add(new SetCardInfo("Slinn Voda, the Rising Deep", 66, Rarity.UNCOMMON, mage.cards.s.SlinnVodaTheRisingDeep.class));
cards.add(new SetCardInfo("Song of Freyalise", 179, Rarity.UNCOMMON, mage.cards.s.SongOfFreyalise.class));
cards.add(new SetCardInfo("Sorcerer's Wand", 231, Rarity.UNCOMMON, mage.cards.s.SorcerersWand.class));
cards.add(new SetCardInfo("Soul Salvage", 104, Rarity.COMMON, mage.cards.s.SoulSalvage.class));
cards.add(new SetCardInfo("Sparring Construct", 232, Rarity.COMMON, mage.cards.s.SparringConstruct.class));
cards.add(new SetCardInfo("Spore Swarm", 180, Rarity.UNCOMMON, mage.cards.s.SporeSwarm.class));
@ -277,9 +283,11 @@ public class Dominaria extends ExpansionSet {
cards.add(new SetCardInfo("The Mirari Conjecture", 57, Rarity.RARE, mage.cards.t.TheMirariConjecture.class));
cards.add(new SetCardInfo("Thorn Elemental", 185, Rarity.UNCOMMON, mage.cards.t.ThornElemental.class));
cards.add(new SetCardInfo("Thran Temporal Gateway", 233, Rarity.RARE, mage.cards.t.ThranTemporalGateway.class));
cards.add(new SetCardInfo("Tiana, Ship's Caretaker", 208, Rarity.UNCOMMON, mage.cards.t.TianaShipsCaretaker.class));
cards.add(new SetCardInfo("Timber Gorge", 279, Rarity.COMMON, mage.cards.t.TimberGorge.class));
cards.add(new SetCardInfo("Time of Ice", 70, Rarity.UNCOMMON, mage.cards.t.TimeOfIce.class));
cards.add(new SetCardInfo("Tolarian Scholar", 71, Rarity.COMMON, mage.cards.t.TolarianScholar.class));
cards.add(new SetCardInfo("Torgaar, Famine Incarnate", 108, Rarity.RARE, mage.cards.t.TorgaarFamineIncarnate.class));
cards.add(new SetCardInfo("Tragic Poet", 37, Rarity.COMMON, mage.cards.t.TragicPoet.class));
cards.add(new SetCardInfo("Traxos, Scourge of Kroog", 234, Rarity.RARE, mage.cards.t.TraxosScourgeOfKroog.class));
cards.add(new SetCardInfo("Triumph of Gerrard", 38, Rarity.UNCOMMON, mage.cards.t.TriumphOfGerrard.class));
@ -295,6 +303,7 @@ public class Dominaria extends ExpansionSet {
cards.add(new SetCardInfo("Vicious Offering", 110, Rarity.COMMON, mage.cards.v.ViciousOffering.class));
cards.add(new SetCardInfo("Vodalian Arcanist", 73, Rarity.COMMON, mage.cards.v.VodalianArcanist.class));
cards.add(new SetCardInfo("Voltaic Servant", 236, Rarity.COMMON, mage.cards.v.VoltaicServant.class));
cards.add(new SetCardInfo("Warcry Phoenix", 150, Rarity.UNCOMMON, mage.cards.w.WarcryPhoenix.class));
cards.add(new SetCardInfo("Warlord's Fury", 151, Rarity.COMMON, mage.cards.w.WarlordsFury.class));
cards.add(new SetCardInfo("Weatherlight", 237, Rarity.MYTHIC, mage.cards.w.Weatherlight.class));
cards.add(new SetCardInfo("Weight of Memory", 74, Rarity.UNCOMMON, mage.cards.w.WeightOfMemory.class));
@ -310,4 +319,4 @@ public class Dominaria extends ExpansionSet {
cards.add(new SetCardInfo("Zahid, Djinn of the Lamp", 76, Rarity.RARE, mage.cards.z.ZahidDjinnOfTheLamp.class));
cards.add(new SetCardInfo("Zhalfirin Void", 249, Rarity.UNCOMMON, mage.cards.z.ZhalfirinVoid.class));
}
}
}

View file

@ -9,9 +9,11 @@ import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
/**
*
@ -23,11 +25,15 @@ public class AttacksWithCreaturesTriggeredAbility extends TriggeredAbilityImpl {
private int minAttackers;
public AttacksWithCreaturesTriggeredAbility(Effect effect, int minAttackers) {
this(effect, minAttackers, new FilterCreaturePermanent("creatures"));
this(effect, minAttackers, StaticFilters.FILTER_PERMANENT_CREATURES);
}
public AttacksWithCreaturesTriggeredAbility(Effect effect, int minAttackers, FilterCreaturePermanent filter) {
super(Zone.BATTLEFIELD, effect);
this(Zone.BATTLEFIELD, effect, minAttackers, filter);
}
public AttacksWithCreaturesTriggeredAbility(Zone zone, Effect effect, int minAttackers, FilterCreaturePermanent filter) {
super(zone, effect);
this.filter = filter;
this.minAttackers = minAttackers;
}
@ -50,13 +56,17 @@ public class AttacksWithCreaturesTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
int attackerCount = 0;
for (UUID attacker : game.getCombat().getAttackers()) {
if (filter.match(game.getPermanent(attacker), game)) {
attackerCount++;
if (game.getCombat().getAttackingPlayerId().equals(getControllerId())) {
int attackerCount = 0;
for (UUID attackerId : game.getCombat().getAttackers()) {
Permanent permanent = game.getPermanent(attackerId);
if (permanent != null && filter.match(game.getPermanent(attackerId), game)) {
attackerCount++;
}
}
return attackerCount >= minAttackers;
}
return attackerCount >= minAttackers && game.getCombat().getAttackingPlayerId().equals(getControllerId());
return false;
}
@Override

View file

@ -85,7 +85,7 @@ public class BlocksOrBecomesBlockedTriggeredAbility extends TriggeredAbilityImpl
Permanent blocked = game.getPermanent(event.getTargetId());
if (blocked != null && filter.match(blocked, game)) {
if (setTargetPointer) {
this.getEffects().setTargetPointer(new FixedTarget(event.getTargetId()));
this.getEffects().setTargetPointer(new FixedTarget(blocked, game));
}
return true;
}
@ -94,7 +94,7 @@ public class BlocksOrBecomesBlockedTriggeredAbility extends TriggeredAbilityImpl
Permanent blocker = game.getPermanent(event.getSourceId());
if (blocker != null && filter.match(blocker, game)) {
if (setTargetPointer) {
this.getEffects().setTargetPointer(new FixedTarget(event.getSourceId()));
this.getEffects().setTargetPointer(new FixedTarget(blocker, game));
}
return true;
}

View file

@ -41,6 +41,7 @@ import mage.game.Game;
public class ReturnToBattlefieldUnderOwnerControlSourceEffect extends OneShotEffect {
private boolean tapped;
private boolean attacking;
private int zoneChangeCounter;
public ReturnToBattlefieldUnderOwnerControlSourceEffect() {
@ -52,16 +53,25 @@ public class ReturnToBattlefieldUnderOwnerControlSourceEffect extends OneShotEff
}
public ReturnToBattlefieldUnderOwnerControlSourceEffect(boolean tapped, int zoneChangeCounter) {
this(tapped, false, zoneChangeCounter);
}
public ReturnToBattlefieldUnderOwnerControlSourceEffect(boolean tapped, boolean attacking, int zoneChangeCounter) {
super(Outcome.Benefit);
this.tapped = tapped;
this.attacking = attacking;
this.zoneChangeCounter = zoneChangeCounter;
staticText = new StringBuilder("return that card to the battlefield").append(tapped ? " tapped" : "").append(" under its owner's control").toString();
staticText = "return that card to the battlefield"
+ (tapped ? " tapped" : "")
+ (attacking ? " attacking" : "")
+ " under its owner's control";
}
public ReturnToBattlefieldUnderOwnerControlSourceEffect(final ReturnToBattlefieldUnderOwnerControlSourceEffect effect) {
super(effect);
this.tapped = effect.tapped;
this.zoneChangeCounter = effect.zoneChangeCounter;
this.attacking = effect.attacking;
}
@Override
@ -80,7 +90,11 @@ public class ReturnToBattlefieldUnderOwnerControlSourceEffect extends OneShotEff
case GRAVEYARD:
if (zoneChangeCounter < 0 || game.getState().getZoneChangeCounter(card.getId()) == zoneChangeCounter) {
Zone currentZone = game.getState().getZone(card.getId());
card.putOntoBattlefield(game, currentZone, source.getSourceId(), card.getOwnerId(), tapped);
if (card.putOntoBattlefield(game, currentZone, source.getSourceId(), card.getOwnerId(), tapped)) {
if (attacking) {
game.getCombat().addAttackingCreature(card.getId(), game);
}
}
}
break;
}

View file

@ -0,0 +1,218 @@
/*
* 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.target.common;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.constants.Zone;
import mage.filter.Filter;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePlayerOrPlaneswalker;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetAmount;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class TargetAnyTargetAmount extends TargetAmount {
protected final FilterCreaturePlayerOrPlaneswalker filter;
public TargetAnyTargetAmount(int amount) {
// 107.1c If a rule or ability instructs a player to choose any number, that player may choose
// any positive number or zero, unless something (such as damage or counters) is being divided
// or distributed among any number of players and/or objects. In that case, a nonzero number
// of players and/or objects must be chosen if possible.
this(new StaticValue(amount));
this.minNumberOfTargets = 1;
}
public TargetAnyTargetAmount(DynamicValue amount) {
super(amount);
this.zone = Zone.ALL;
this.filter = new FilterCreaturePlayerOrPlaneswalker("targets");
this.targetName = filter.getMessage();
}
public TargetAnyTargetAmount(final TargetAnyTargetAmount target) {
super(target);
this.filter = target.filter.copy();
}
@Override
public Filter getFilter() {
return this.filter;
}
@Override
public boolean canTarget(UUID objectId, Game game) {
Permanent permanent = game.getPermanent(objectId);
if (permanent != null) {
return filter.match(permanent, game);
}
Player player = game.getPlayer(objectId);
return player != null && filter.match(player, game);
}
@Override
public boolean canTarget(UUID objectId, Ability source, Game game) {
Permanent permanent = game.getPermanent(objectId);
Player player = game.getPlayer(objectId);
if (source != null) {
MageObject targetSource = source.getSourceObject(game);
if (permanent != null) {
return permanent.canBeTargetedBy(targetSource, source.getControllerId(), game) && filter.match(permanent, source.getSourceId(), source.getControllerId(), game);
}
if (player != null) {
return player.canBeTargetedBy(targetSource, source.getControllerId(), game) && filter.match(player, game);
}
}
if (permanent != null) {
return filter.match(permanent, game);
}
return player != null && filter.match(player, game);
}
@Override
public boolean canTarget(UUID playerId, UUID objectId, Ability source, Game game) {
return canTarget(objectId, source, game);
}
@Override
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
int count = 0;
MageObject targetSource = game.getObject(sourceId);
for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) {
Player player = game.getPlayer(playerId);
if (player != null && player.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(player, game)) {
count++;
if (count >= this.minNumberOfTargets) {
return true;
}
}
}
for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT, sourceControllerId, game)) {
if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(permanent, sourceId, sourceControllerId, game)) {
count++;
if (count >= this.minNumberOfTargets) {
return true;
}
}
}
return false;
}
@Override
public boolean canChoose(UUID sourceControllerId, Game game) {
int count = 0;
for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) {
Player player = game.getPlayer(playerId);
if (player != null && filter.match(player, game)) {
count++;
if (count >= this.minNumberOfTargets) {
return true;
}
}
}
for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT, sourceControllerId, game)) {
if (filter.match(permanent, null, sourceControllerId, game)) {
count++;
if (count >= this.minNumberOfTargets) {
return true;
}
}
}
return false;
}
@Override
public Set<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) {
Set<UUID> possibleTargets = new HashSet<>();
MageObject targetSource = game.getObject(sourceId);
for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) {
Player player = game.getPlayer(playerId);
if (player != null && player.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(player, game)) {
possibleTargets.add(playerId);
}
}
for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT, sourceControllerId, game)) {
if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(permanent, sourceId, sourceControllerId, game)) {
possibleTargets.add(permanent.getId());
}
}
return possibleTargets;
}
@Override
public Set<UUID> possibleTargets(UUID sourceControllerId, Game game) {
Set<UUID> possibleTargets = new HashSet<>();
for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) {
Player player = game.getPlayer(playerId);
if (player != null && filter.match(player, game)) {
possibleTargets.add(playerId);
}
}
for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT, sourceControllerId, game)) {
if (filter.match(permanent, null, sourceControllerId, game)) {
possibleTargets.add(permanent.getId());
}
}
return possibleTargets;
}
@Override
public String getTargetedName(Game game) {
StringBuilder sb = new StringBuilder();
for (UUID targetId : getTargets()) {
Permanent permanent = game.getPermanent(targetId);
if (permanent != null) {
sb.append(permanent.getLogName()).append('(').append(getTargetAmount(targetId)).append(") ");
} else {
Player player = game.getPlayer(targetId);
sb.append(player.getLogName()).append('(').append(getTargetAmount(targetId)).append(") ");
}
}
return sb.toString();
}
@Override
public TargetAnyTargetAmount copy() {
return new TargetAnyTargetAmount(this);
}
}