From 96fe50cebe2f25777cc7a495d3bbdacaff18a9bd Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 17 Feb 2015 14:17:18 +0100 Subject: [PATCH 1/5] * Sharding Sphinx - Fixed that ability also triggered for damage not done to players, added missing color to created token (fixes #731). --- .../sets/shardsofalara/ShardingSphinx.java | 67 +++++-------------- ...alsDamageToAPlayerAllTriggeredAbility.java | 1 - 2 files changed, 17 insertions(+), 51 deletions(-) diff --git a/Mage.Sets/src/mage/sets/shardsofalara/ShardingSphinx.java b/Mage.Sets/src/mage/sets/shardsofalara/ShardingSphinx.java index b84b4e7d77..7ae8b57126 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/ShardingSphinx.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/ShardingSphinx.java @@ -28,21 +28,16 @@ package mage.sets.shardsofalara; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.SetTargetPointer; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.CardTypePredicate; -import mage.game.Game; -import mage.game.events.DamagedEvent; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; import mage.game.permanent.token.Token; /** @@ -51,19 +46,28 @@ import mage.game.permanent.token.Token; */ public class ShardingSphinx extends CardImpl { + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("an artifact creature you control"); + + static{ + filter.add(new CardTypePredicate(CardType.ARTIFACT)); + } + public ShardingSphinx(UUID ownerId) { super(ownerId, 55, "Sharding Sphinx", Rarity.RARE, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}{U}{U}"); this.expansionSetCode = "ALA"; this.subtype.add("Sphinx"); - this.color.setBlue(true); this.power = new MageInt(4); this.toughness = new MageInt(4); // Flying this.addAbility(FlyingAbility.getInstance()); + // Whenever an artifact creature you control deals combat damage to a player, you may put a 1/1 blue Thopter artifact creature token with flying onto the battlefield. - this.addAbility(new ShardingSphinxTriggeredAbility()); + this.addAbility(new DealsDamageToAPlayerAllTriggeredAbility( + new CreateTokenEffect(new ThopterToken()), + filter, true, SetTargetPointer.NONE, true)); + } public ShardingSphinx(final ShardingSphinx card) { @@ -76,52 +80,15 @@ public class ShardingSphinx extends CardImpl { } } -class ShardingSphinxTriggeredAbility extends TriggeredAbilityImpl { - - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("artifact creature you control"); - static{ - filter.add(new CardTypePredicate(CardType.ARTIFACT)); - } - - public ShardingSphinxTriggeredAbility() { - super(Zone.BATTLEFIELD, new CreateTokenEffect(new ThopterToken()), true); - } - - public ShardingSphinxTriggeredAbility(final ShardingSphinxTriggeredAbility ability) { - super(ability); - } - - @Override - public ShardingSphinxTriggeredAbility copy() { - return new ShardingSphinxTriggeredAbility(this); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.DAMAGED_CREATURE || event.getType() == GameEvent.EventType.DAMAGED_PLANESWALKER || event.getType() == GameEvent.EventType.DAMAGED_PLAYER) { - Permanent permanent = game.getPermanent(event.getSourceId()); - if(permanent != null && filter.match(permanent, sourceId, controllerId, game) && ((DamagedEvent) event).isCombatDamage()){ - return true; - } - } - return false; - } - - @Override - public String getRule() { - return "Whenever a creature you control deals combat damage, " + super.getRule(); - } - -} - class ThopterToken extends Token { ThopterToken() { super("Thopter", "a 1/1 blue Thopter artifact creature token with flying"); cardType.add(CardType.CREATURE); cardType.add(CardType.ARTIFACT); + color.setBlue(true); subtype.add("Thopter"); power = new MageInt(1); toughness = new MageInt(1); this.addAbility(FlyingAbility.getInstance()); } -} \ No newline at end of file +} diff --git a/Mage/src/mage/abilities/common/DealsDamageToAPlayerAllTriggeredAbility.java b/Mage/src/mage/abilities/common/DealsDamageToAPlayerAllTriggeredAbility.java index e5321dcc78..69ac883329 100644 --- a/Mage/src/mage/abilities/common/DealsDamageToAPlayerAllTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/DealsDamageToAPlayerAllTriggeredAbility.java @@ -36,7 +36,6 @@ import mage.filter.FilterPermanent; import mage.game.Game; import mage.game.events.DamagedPlayerEvent; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.target.targetpointer.FixedTarget; From 1deaf53b972f4c742d185f2aaea0022662375f5b Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 18 Feb 2015 01:51:23 +0100 Subject: [PATCH 2/5] * Garruk, Apex Predator - Fixed that the third abilit did not apply the life gain if the target creature did not die (e.g. because of indestructable). --- Mage.Sets/src/mage/sets/magic2015/GarrukApexPredator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/magic2015/GarrukApexPredator.java b/Mage.Sets/src/mage/sets/magic2015/GarrukApexPredator.java index cc11de82f0..6d8acd686e 100644 --- a/Mage.Sets/src/mage/sets/magic2015/GarrukApexPredator.java +++ b/Mage.Sets/src/mage/sets/magic2015/GarrukApexPredator.java @@ -135,7 +135,7 @@ class GarrukApexPredatorEffect3 extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); - Permanent creature = (Permanent) game.getLastKnownInformation(source.getFirstTarget(), Zone.BATTLEFIELD); + Permanent creature = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source)); if (player != null && creature != null) { player.gainLife(creature.getToughness().getValue(), game); return true; From b59616fda8384da03f4768da94180e1f99b1905a Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 18 Feb 2015 01:53:51 +0100 Subject: [PATCH 3/5] * Karona, False God - Fixed that the untap effect was applied continuous. --- .../src/mage/sets/scourge/KaronaFalseGod.java | 122 +++++++++--------- 1 file changed, 60 insertions(+), 62 deletions(-) diff --git a/Mage.Sets/src/mage/sets/scourge/KaronaFalseGod.java b/Mage.Sets/src/mage/sets/scourge/KaronaFalseGod.java index 1a9f103602..7f75277ac5 100644 --- a/Mage.Sets/src/mage/sets/scourge/KaronaFalseGod.java +++ b/Mage.Sets/src/mage/sets/scourge/KaronaFalseGod.java @@ -29,10 +29,14 @@ package mage.sets.scourge; import java.util.UUID; import mage.MageInt; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continious.BoostAllEffect; +import mage.abilities.effects.common.continious.GainControlTargetEffect; import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; import mage.cards.repository.CardRepository; @@ -40,16 +44,16 @@ import mage.choices.Choice; import mage.choices.ChoiceImpl; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.Layer; import mage.constants.Outcome; import mage.constants.Rarity; -import mage.constants.SubLayer; import mage.constants.TargetController; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.targetpointer.FixedTarget; /** * @@ -63,11 +67,6 @@ public class KaronaFalseGod extends CardImpl { this.supertype.add("Legendary"); this.subtype.add("Avatar"); - this.color.setGreen(true); - this.color.setBlue(true); - this.color.setWhite(true); - this.color.setRed(true); - this.color.setBlack(true); this.power = new MageInt(5); this.toughness = new MageInt(5); @@ -75,10 +74,10 @@ public class KaronaFalseGod extends CardImpl { this.addAbility(HasteAbility.getInstance()); // At the beginning of each player's upkeep, that player untaps Karona, False God and gains control of it. - this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new KaronaFalseGodControlEffect(), TargetController.ANY, false)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new KaronaFalseGodUntapGetControlEffect(), TargetController.ANY, false, true)); // Whenever Karona attacks, creatures of the creature type of your choice get +3/+3 until end of turn. - this.addAbility(new AttacksTriggeredAbility(new KaronaFalseGodBoostEffect(), false, "Whenever {this} attacks, creatures of the creature type of your choice get +3/+3 until end of turn.")); + this.addAbility(new AttacksTriggeredAbility(new KaronaFalseGodEffect(), false)); } public KaronaFalseGod(final KaronaFalseGod card) { @@ -91,78 +90,77 @@ public class KaronaFalseGod extends CardImpl { } } -class KaronaFalseGodControlEffect extends ContinuousEffectImpl { - - KaronaFalseGodControlEffect() { - super(Duration.Custom, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.GainControl); - this.staticText = "that player untaps {this} and gains control of it."; +class KaronaFalseGodUntapGetControlEffect extends OneShotEffect { + + public KaronaFalseGodUntapGetControlEffect() { + super(Outcome.GainControl); + this.staticText = "that player untaps Karona, False God and gains control of it"; } - - KaronaFalseGodControlEffect(final KaronaFalseGodControlEffect effect) { + + public KaronaFalseGodUntapGetControlEffect(final KaronaFalseGodUntapGetControlEffect effect) { super(effect); } - + @Override - public KaronaFalseGodControlEffect copy() { - return new KaronaFalseGodControlEffect(this); + public KaronaFalseGodUntapGetControlEffect copy() { + return new KaronaFalseGodUntapGetControlEffect(this); } - + @Override public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - Player player = game.getPlayer(game.getActivePlayerId()); - if (player != null && permanent != null) { - permanent.untap(game); - if (permanent.changeControllerId(player.getId(), game)) { - return true; - } + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = source.getSourceObject(game); + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + if (controller != null && sourceObject != null && sourceObject.equals(sourcePermanent)) { + sourcePermanent.untap(game); + ContinuousEffect effect = new GainControlTargetEffect(Duration.Custom, true, getTargetPointer().getFirst(game, source)); + effect.setTargetPointer(new FixedTarget(sourcePermanent.getId())); + effect.setText("and gains control of it"); + game.addEffect(effect, source); + return true; } return false; } } -class KaronaFalseGodBoostEffect extends ContinuousEffectImpl { - - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); - private String typeChosen = ""; - - KaronaFalseGodBoostEffect() { - super(Duration.EndOfTurn, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature); - staticText = "creatures of the creature type of your choice get +3/+3 until end of turn."; +class KaronaFalseGodEffect extends OneShotEffect { + + public KaronaFalseGodEffect() { + super(Outcome.BoostCreature); + this.staticText = "creatures of the creature type of your choice get +3/+3 until end of turn"; } - - KaronaFalseGodBoostEffect(final KaronaFalseGodBoostEffect effect) { + + public KaronaFalseGodEffect(final KaronaFalseGodEffect effect) { super(effect); } - + @Override - public KaronaFalseGodBoostEffect copy() { - return new KaronaFalseGodBoostEffect(this); + public KaronaFalseGodEffect copy() { + return new KaronaFalseGodEffect(this); } - + @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - if (typeChosen.isEmpty()) { - Choice typeChoice = new ChoiceImpl(true); - typeChoice.setMessage("Choose creature type"); - typeChoice.setChoices(CardRepository.instance.getCreatureTypes()); - while (!player.choose(Outcome.BoostCreature, typeChoice, game)) { - if (!player.isInGame()) { - return false; - } - } - typeChosen = typeChoice.getChoice(); - game.informPlayers(player.getName() + " has chosen " + typeChosen); - } - for (Permanent perm: game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) { - if (perm.hasSubtype(typeChosen)) { - perm.addPower(3); - perm.addToughness(3); + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = game.getObject(source.getSourceId()); + if (sourceObject != null && controller != null) { + Choice typeChoice = new ChoiceImpl(true); + typeChoice.setMessage("Choose creature type"); + typeChoice.setChoices(CardRepository.instance.getCreatureTypes()); + while (!controller.choose(Outcome.BoostCreature, typeChoice, game)) { + if (!controller.isInGame()) { + return false; } } + String typeChosen = typeChoice.getChoice(); + if (!typeChosen.isEmpty()) { + game.informPlayers(controller.getName() + " has chosen " + typeChosen); + FilterCreaturePermanent filter = new FilterCreaturePermanent(); + filter.add(new SubtypePredicate(typeChosen)); + game.addEffect(new BoostAllEffect(3,3,Duration.EndOfTurn, filter, false), source); + } + return true; } - return true; + return false; } -} \ No newline at end of file +} From de1f8271ae2fae523febab54e377582d1e75e4e1 Mon Sep 17 00:00:00 2001 From: Andy Fries Date: Tue, 17 Feb 2015 22:35:56 -0800 Subject: [PATCH 4/5] fixed bug in Maralen of the Mornsong effect only applying to owner --- Mage.Sets/src/mage/sets/morningtide/MaralenOfTheMornsong.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/morningtide/MaralenOfTheMornsong.java b/Mage.Sets/src/mage/sets/morningtide/MaralenOfTheMornsong.java index df67891e68..7a738627fa 100644 --- a/Mage.Sets/src/mage/sets/morningtide/MaralenOfTheMornsong.java +++ b/Mage.Sets/src/mage/sets/morningtide/MaralenOfTheMornsong.java @@ -126,7 +126,8 @@ class MaralenOfTheMornsongEffect2 extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); + UUID activePlayerId = game.getActivePlayerId(); + Player player = game.getPlayer(activePlayerId); if (player != null) { player.loseLife(3, game); TargetCardInLibrary target = new TargetCardInLibrary(); From 687fe91f496f998915d610d53381d0101e13ef0c Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 18 Feb 2015 09:11:33 +0100 Subject: [PATCH 5/5] * Fixed possible null pointer exception. --- Mage/src/mage/game/permanent/PermanentCard.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Mage/src/mage/game/permanent/PermanentCard.java b/Mage/src/mage/game/permanent/PermanentCard.java index 1c9910abac..82ec080216 100644 --- a/Mage/src/mage/game/permanent/PermanentCard.java +++ b/Mage/src/mage/game/permanent/PermanentCard.java @@ -138,7 +138,9 @@ public class PermanentCard extends PermanentImpl { Card originalCard = game.getCard(this.getId()); if (isFaceDown()) { setFaceDown(false); - originalCard.setFaceDown(false); //TODO: Do this in a better way + if (originalCard != null) { + originalCard.setFaceDown(false); //TODO: Do this in a better way + } } ZoneChangeEvent event = new ZoneChangeEvent(this, sourceId, controllerId, fromZone, toZone, appliedEffects); if (!game.replaceEvent(event)) { @@ -146,7 +148,9 @@ public class PermanentCard extends PermanentImpl { game.rememberLKI(objectId, Zone.BATTLEFIELD, this); if (owner != null) { this.setControllerId(ownerId); // neccessary for e.g. abilities in graveyard or hand to not have a controller != owner - originalCard.updateZoneChangeCounter(); + if (originalCard != null) { + originalCard.updateZoneChangeCounter(); + } switch (event.getToZone()) { case GRAVEYARD: owner.putInGraveyard(card, game, !flag);