diff --git a/Mage.Client/release/sample-decks/Black Blue M11.dck b/Mage.Client/release/sample-decks/Black Blue M11.dck new file mode 100644 index 00000000000..49be31027cb Binary files /dev/null and b/Mage.Client/release/sample-decks/Black Blue M11.dck differ diff --git a/Mage.Client/release/sample-decks/Pro Walker.dck b/Mage.Client/release/sample-decks/Pro Walker.dck new file mode 100644 index 00000000000..16dfb6f5b05 Binary files /dev/null and b/Mage.Client/release/sample-decks/Pro Walker.dck differ diff --git a/Mage.Sets/src/mage/sets/shardsofalara/KnightOfTheWhiteOrchid.java b/Mage.Sets/src/mage/sets/shardsofalara/KnightOfTheWhiteOrchid.java index c39a280fbfe..ae14f7343b6 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/KnightOfTheWhiteOrchid.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/KnightOfTheWhiteOrchid.java @@ -34,16 +34,13 @@ import mage.Constants.Outcome; import mage.Constants.Rarity; import mage.Constants.Zone; import mage.MageInt; -import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.ZoneChangeTriggeredAbility; import mage.abilities.effects.common.SearchLibraryPutInPlayEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.cards.CardImpl; import mage.filter.FilterCard; import mage.filter.common.FilterLandPermanent; import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; -import mage.game.events.ZoneChangeEvent; import mage.target.common.TargetCardInLibrary; /** @@ -81,13 +78,18 @@ public class KnightOfTheWhiteOrchid extends CardImpl { } -class KnightOfTheWhiteOrchidAbility extends EntersBattlefieldTriggeredAbility { +class KnightOfTheWhiteOrchidAbility extends ZoneChangeTriggeredAbility { + + private static FilterCard filter1 = new FilterCard("Plains"); + private static FilterLandPermanent filter2 = new FilterLandPermanent(); + + static { + filter1.getName().add("Plains"); + } public KnightOfTheWhiteOrchidAbility() { - super(null, true); - FilterCard filter = new FilterCard("Plains"); - filter.getName().add("Plains"); - TargetCardInLibrary target = new TargetCardInLibrary(filter); + super(Zone.BATTLEFIELD, null, "When {this} enters the battlefield, if an opponent controls more lands than you, you may ", true); + TargetCardInLibrary target = new TargetCardInLibrary(filter1); addEffect(new SearchLibraryPutInPlayEffect(target, false, Outcome.PutLandInPlay)); } @@ -100,34 +102,15 @@ class KnightOfTheWhiteOrchidAbility extends EntersBattlefieldTriggeredAbility { + + public SejiriRefuge(UUID ownerId) { + super(ownerId, 224, "Sejiri Refuge", Rarity.UNCOMMON, new CardType[]{CardType.LAND}, null); + this.expansionSetCode = "ZEN"; + this.addAbility(new EntersBattlefieldTappedAbility()); + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(1), false)); + this.addAbility(new WhiteManaAbility()); + this.addAbility(new BlueManaAbility()); + } + + public SejiriRefuge(final SejiriRefuge card) { + super(card); + } + + @Override + public SejiriRefuge copy() { + return new SejiriRefuge(this); + } + + @Override + public String getArt() { + return "126610_typ_reg_sty_010.jpg"; + } +} diff --git a/Mage/src/mage/abilities/common/EntersBattlefieldTriggeredAbility.java b/Mage/src/mage/abilities/common/EntersBattlefieldTriggeredAbility.java index bd9f74bb297..c0d8f6d2140 100644 --- a/Mage/src/mage/abilities/common/EntersBattlefieldTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/EntersBattlefieldTriggeredAbility.java @@ -29,51 +29,30 @@ package mage.abilities.common; import mage.Constants.Zone; -import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; -import mage.game.events.ZoneChangeEvent; /** * * @author BetaSteward_at_googlemail.com */ -public class EntersBattlefieldTriggeredAbility> extends TriggeredAbilityImpl { +public class EntersBattlefieldTriggeredAbility extends ZoneChangeTriggeredAbility { public EntersBattlefieldTriggeredAbility(Effect effect) { this(effect, false); } public EntersBattlefieldTriggeredAbility(Effect effect, boolean optional) { - super(Zone.BATTLEFIELD, effect, optional); + super(Zone.BATTLEFIELD, effect, "When {this} enters the battlefield, ", optional); } public EntersBattlefieldTriggeredAbility(EntersBattlefieldTriggeredAbility ability) { super(ability); } - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == EventType.ZONE_CHANGE && event.getTargetId().equals(this.getSourceId()) ) { - ZoneChangeEvent zEvent = (ZoneChangeEvent)event; - if (zEvent.getToZone() == Zone.BATTLEFIELD) { - trigger(game, this.controllerId); - return true; - } - } - return false; - } @Override - public String getRule() { - return "When {this} enters the battlefield, " + super.getRule(); - } - - @Override - public T copy() { - return (T) new EntersBattlefieldTriggeredAbility(this); + public EntersBattlefieldTriggeredAbility copy() { + return new EntersBattlefieldTriggeredAbility(this); } } diff --git a/Mage/src/mage/abilities/common/LeavesBattlefieldTriggeredAbility.java b/Mage/src/mage/abilities/common/LeavesBattlefieldTriggeredAbility.java index 5bf6b46fc6d..b80b2d33fa5 100644 --- a/Mage/src/mage/abilities/common/LeavesBattlefieldTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/LeavesBattlefieldTriggeredAbility.java @@ -29,44 +29,22 @@ package mage.abilities.common; import mage.Constants.Zone; -import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; -import mage.game.events.ZoneChangeEvent; /** * * @author BetaSteward_at_googlemail.com */ -public class LeavesBattlefieldTriggeredAbility extends TriggeredAbilityImpl { +public class LeavesBattlefieldTriggeredAbility extends ZoneChangeTriggeredAbility { public LeavesBattlefieldTriggeredAbility(Effect effect, boolean optional) { - super(Zone.BATTLEFIELD, effect, optional); + super(Zone.BATTLEFIELD, null, effect, "When {this} leaves the battlefield, ", optional); } public LeavesBattlefieldTriggeredAbility(LeavesBattlefieldTriggeredAbility ability) { super(ability); } - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == EventType.ZONE_CHANGE && event.getTargetId().equals(this.getSourceId()) ) { - ZoneChangeEvent zEvent = (ZoneChangeEvent)event; - if (zEvent.getFromZone() == Zone.BATTLEFIELD) { - trigger(game, this.controllerId); - return true; - } - } - return false; - } - - @Override - public String getRule() { - return "When {this} leaves the battlefield, " + super.getRule(); - } - @Override public LeavesBattlefieldTriggeredAbility copy() { return new LeavesBattlefieldTriggeredAbility(this); diff --git a/Mage/src/mage/abilities/common/PutIntoGraveFromBattlefieldTriggeredAbility.java b/Mage/src/mage/abilities/common/PutIntoGraveFromBattlefieldTriggeredAbility.java index e61bc0968e4..b02df4086e8 100644 --- a/Mage/src/mage/abilities/common/PutIntoGraveFromBattlefieldTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/PutIntoGraveFromBattlefieldTriggeredAbility.java @@ -29,44 +29,22 @@ package mage.abilities.common; import mage.Constants.Zone; -import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; -import mage.game.events.ZoneChangeEvent; /** * * @author BetaSteward_at_googlemail.com */ -public class PutIntoGraveFromBattlefieldTriggeredAbility extends TriggeredAbilityImpl { +public class PutIntoGraveFromBattlefieldTriggeredAbility extends ZoneChangeTriggeredAbility { public PutIntoGraveFromBattlefieldTriggeredAbility(Effect effect, boolean optional) { - super(Zone.GRAVEYARD, effect, optional); + super(Zone.BATTLEFIELD, Zone.GRAVEYARD, effect, "When {this} is put into a graveyard from the battlefield, ", optional); } public PutIntoGraveFromBattlefieldTriggeredAbility(PutIntoGraveFromBattlefieldTriggeredAbility ability) { super(ability); } - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == EventType.ZONE_CHANGE && event.getTargetId().equals(this.getSourceId()) ) { - ZoneChangeEvent zEvent = (ZoneChangeEvent)event; - if (zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getToZone() == Zone.GRAVEYARD) { - trigger(game, this.controllerId); - return true; - } - } - return false; - } - - @Override - public String getRule() { - return "When {this} is put into a graveyard from the battlefield, " + super.getRule(); - } - @Override public PutIntoGraveFromBattlefieldTriggeredAbility copy() { return new PutIntoGraveFromBattlefieldTriggeredAbility(this); diff --git a/Mage/src/mage/abilities/common/ZoneChangeTriggeredAbility.java b/Mage/src/mage/abilities/common/ZoneChangeTriggeredAbility.java new file mode 100644 index 00000000000..7db8d78600e --- /dev/null +++ b/Mage/src/mage/abilities/common/ZoneChangeTriggeredAbility.java @@ -0,0 +1,99 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.abilities.common; + +import mage.Constants.Zone; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.events.ZoneChangeEvent; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class ZoneChangeTriggeredAbility> extends TriggeredAbilityImpl { + + protected Zone fromZone; + protected Zone toZone; + protected String rule; + + public ZoneChangeTriggeredAbility(Zone fromZone, Zone toZone, Effect effect, String rule, boolean optional) { + super(fromZone, effect, optional); + this.fromZone = fromZone; + this.toZone = toZone; + this.rule = rule; + } + + public ZoneChangeTriggeredAbility(Zone toZone, Effect effect, String rule, boolean optional) { + super(toZone, effect, optional); + this.fromZone = null; + this.toZone = toZone; + this.rule = rule; + } + + public ZoneChangeTriggeredAbility(ZoneChangeTriggeredAbility ability) { + super(ability); + this.fromZone = ability.fromZone; + this.toZone = ability.toZone; + this.rule = ability.rule; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == EventType.ZONE_CHANGE && event.getTargetId().equals(this.getSourceId())) { + ZoneChangeEvent zEvent = (ZoneChangeEvent)event; + if ((fromZone == null || zEvent.getFromZone() == fromZone) && (toZone == null || zEvent.getToZone() == toZone)) { + trigger(game, this.controllerId); + return true; + } + } + return false; + } + + @Override + public String getRule() { + return rule + super.getRule(); + } + + @Override + public T copy() { + return (T)new ZoneChangeTriggeredAbility(this); + } + + public Zone getFromZone() { + return fromZone; + } + + public Zone getToZone() { + return toZone; + } +} diff --git a/Mage/src/mage/abilities/effects/ContinuousEffectImpl.java b/Mage/src/mage/abilities/effects/ContinuousEffectImpl.java index 0f1f956b242..bc34e8189f8 100644 --- a/Mage/src/mage/abilities/effects/ContinuousEffectImpl.java +++ b/Mage/src/mage/abilities/effects/ContinuousEffectImpl.java @@ -118,15 +118,24 @@ public abstract class ContinuousEffectImpl> ex public void init(Ability source, Game game) { //20100716 - 611.2c if (source instanceof ActivatedAbility) { - switch (layer) { - case CopyEffects_1: - case ControlChangingEffects_2: - case TextChangingEffects_3: - case TypeChangingEffects_4: - case ColorChangingEffects_5: - case AbilityAddingRemovingEffects_6: - case PTChangingEffects_7: + if (layer != null) { + switch (layer) { + case CopyEffects_1: + case ControlChangingEffects_2: + case TextChangingEffects_3: + case TypeChangingEffects_4: + case ColorChangingEffects_5: + case AbilityAddingRemovingEffects_6: + case PTChangingEffects_7: + this.affectedObjectsSet = true; + } + } + else { + if (hasLayer(Layer.CopyEffects_1) || hasLayer(Layer.ControlChangingEffects_2) || hasLayer(Layer.TextChangingEffects_3) || + hasLayer(Layer.TypeChangingEffects_4) || hasLayer(Layer.ColorChangingEffects_5) || hasLayer(Layer.AbilityAddingRemovingEffects_6) || + hasLayer(Layer.PTChangingEffects_7)) { this.affectedObjectsSet = true; + } } } } diff --git a/Mage/src/mage/game/permanent/PermanentCard.java b/Mage/src/mage/game/permanent/PermanentCard.java index b7711567647..167f79e4e7a 100644 --- a/Mage/src/mage/game/permanent/PermanentCard.java +++ b/Mage/src/mage/game/permanent/PermanentCard.java @@ -36,6 +36,7 @@ import mage.Constants.Zone; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.TriggeredAbility; +import mage.abilities.common.ZoneChangeTriggeredAbility; import mage.abilities.keyword.LevelAbility; import mage.cards.Card; import mage.cards.LevelerCard; @@ -116,11 +117,18 @@ public class PermanentCard extends PermanentImpl { public void checkPermanentOnlyTriggers(ZoneChangeEvent event, Game game) { // we only want to trigger abilities that are not on the underlying card ie. have been added by another effect + // or we want to trigger abilities that only trigger on leaving the battlefield // card abilities will get triggered later when the card hits the new zone Card card = game.getCard(objectId).copy(); for (TriggeredAbility ability: abilities.getTriggeredAbilities(event.getFromZone())) { if (!card.getAbilities().containsKey(ability.getId())) ability.checkTrigger(event, game); + else if (ability instanceof ZoneChangeTriggeredAbility && event.getFromZone() == Zone.BATTLEFIELD) { + ZoneChangeTriggeredAbility zcAbility = (ZoneChangeTriggeredAbility)ability; + if (zcAbility.getToZone() == null) { + ability.checkTrigger(event, game); + } + } } for (TriggeredAbility ability: abilities.getTriggeredAbilities(event.getToZone())) { if (!card.getAbilities().containsKey(ability.getId()))