diff --git a/Mage.Sets/src/mage/cards/k/KardurDoomscourge.java b/Mage.Sets/src/mage/cards/k/KardurDoomscourge.java index 07f0c636033..6d0951ba1ae 100644 --- a/Mage.Sets/src/mage/cards/k/KardurDoomscourge.java +++ b/Mage.Sets/src/mage/cards/k/KardurDoomscourge.java @@ -2,7 +2,6 @@ package mage.cards.k; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.DiesCreatureTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.RestrictionEffect; import mage.abilities.effects.common.GainLifeEffect; @@ -10,30 +9,21 @@ import mage.abilities.effects.common.LoseLifeOpponentsEffect; import mage.abilities.effects.common.combat.AttacksIfAbleAllEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.SubType; -import mage.constants.SuperType; -import mage.filter.FilterPermanent; +import mage.constants.*; import mage.filter.StaticFilters; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.predicate.permanent.AttackingPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.watchers.common.AttackedThisTurnWatcher; import java.util.UUID; +import mage.abilities.common.AttackingCreaturePutIntoGraveyardTriggeredAbility; +import mage.filter.common.FilterCreaturePermanent; /** * @author TheElk801 */ public final class KardurDoomscourge extends CardImpl { - private static final FilterPermanent filter = new FilterControlledCreaturePermanent("an attacking creature"); - - static { - filter.add(AttackingPredicate.instance); - } - public KardurDoomscourge(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{R}"); @@ -48,12 +38,13 @@ public final class KardurDoomscourge extends CardImpl { StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE, Duration.UntilYourNextTurn ).setText("until your next turn, creatures your opponents control attack each combat if able")); ability.addEffect(new KardurDoomscourgeEffect()); + ability.addWatcher(new AttackedThisTurnWatcher()); this.addAbility(ability); // Whenever an attacking creature dies, each opponent loses 1 life and you gain 1 life. - ability = new DiesCreatureTriggeredAbility(new LoseLifeOpponentsEffect(1), false, filter); - ability.addEffect(new GainLifeEffect(1).concatBy("and")); - this.addAbility(ability); + Ability ability2 = new AttackingCreaturePutIntoGraveyardTriggeredAbility(new LoseLifeOpponentsEffect(1), new FilterCreaturePermanent("an attacking creature"), false, true, false); + ability2.addEffect(new GainLifeEffect(1).concatBy("and")); + this.addAbility(ability2); } private KardurDoomscourge(final KardurDoomscourge card) { diff --git a/Mage.Sets/src/mage/cards/k/KithkinMourncaller.java b/Mage.Sets/src/mage/cards/k/KithkinMourncaller.java index f0ac5042603..575b2a13440 100644 --- a/Mage.Sets/src/mage/cards/k/KithkinMourncaller.java +++ b/Mage.Sets/src/mage/cards/k/KithkinMourncaller.java @@ -3,7 +3,7 @@ package mage.cards.k; import java.util.UUID; import mage.MageInt; -import mage.abilities.common.PutIntoGraveFromBattlefieldAllTriggeredAbility; +import mage.abilities.common.AttackingCreaturePutIntoGraveyardTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -32,8 +32,7 @@ public final class KithkinMourncaller extends CardImpl { this.toughness = new MageInt(2); // Whenever an attacking Kithkin or Elf is put into your graveyard from the battlefield, you may draw a card. - this.addAbility(new PutIntoGraveFromBattlefieldAllTriggeredAbility(new DrawCardSourceControllerEffect(1), - true, filter, false, true)); + this.addAbility(new AttackingCreaturePutIntoGraveyardTriggeredAbility(new DrawCardSourceControllerEffect(1), filter, true, false, true)); } private KithkinMourncaller(final KithkinMourncaller card) { diff --git a/Mage/src/main/java/mage/abilities/common/AttackingCreaturePutIntoGraveyardTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/AttackingCreaturePutIntoGraveyardTriggeredAbility.java new file mode 100644 index 00000000000..afb204e5642 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/common/AttackingCreaturePutIntoGraveyardTriggeredAbility.java @@ -0,0 +1,121 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.abilities.common; + +import java.util.List; +import java.util.UUID; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import static mage.game.events.GameEvent.EventType.DECLARE_ATTACKERS_STEP; +import static mage.game.events.GameEvent.EventType.END_COMBAT_STEP_POST; +import static mage.game.events.GameEvent.EventType.REMOVED_FROM_COMBAT; +import static mage.game.events.GameEvent.EventType.ZONE_CHANGE; +import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; + +/** + * + * @author weirddan455 and jeffwadsworth + */ +public class AttackingCreaturePutIntoGraveyardTriggeredAbility extends TriggeredAbilityImpl { + + protected FilterPermanent filterPermanent; + private final boolean onlyToControllerGraveyard; + private final boolean itDies; + + public AttackingCreaturePutIntoGraveyardTriggeredAbility(Effect effect, FilterPermanent filterPermanent, Boolean onlyToControllerGraveyard, Boolean itDies, Boolean optional) { + super(Zone.BATTLEFIELD, effect, optional); + this.filterPermanent = filterPermanent; + this.onlyToControllerGraveyard = onlyToControllerGraveyard; + this.itDies = itDies; + } + + private AttackingCreaturePutIntoGraveyardTriggeredAbility(final AttackingCreaturePutIntoGraveyardTriggeredAbility ability) { + super(ability); + this.filterPermanent = ability.filterPermanent; + this.onlyToControllerGraveyard = ability.onlyToControllerGraveyard; + this.itDies = ability.itDies; + } + + @Override + public AttackingCreaturePutIntoGraveyardTriggeredAbility copy() { + return new AttackingCreaturePutIntoGraveyardTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + switch (event.getType()) { + case DECLARE_ATTACKERS_STEP: + case END_COMBAT_STEP_POST: + case ZONE_CHANGE: + case REMOVED_FROM_COMBAT: + return true; + default: + return false; + } + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + switch (event.getType()) { + case DECLARE_ATTACKERS_STEP: + Permanent permanent = game.getPermanent(event.getTargetId()); + if (permanent != null + && !filterPermanent.match(permanent, game)) { + return false; + } + game.getState().setValue(this.getSourceId() + "Attackers", game.getCombat().getAttackers()); + return false; + case END_COMBAT_STEP_POST: + game.getState().setValue(this.getSourceId() + "Attackers", null); + return false; + case ZONE_CHANGE: + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + if (zEvent.getFromZone() == Zone.BATTLEFIELD + && zEvent.getToZone() == Zone.GRAVEYARD) { + if (onlyToControllerGraveyard + && !this.isControlledBy(game.getOwnerId(zEvent.getTargetId()))) { + return false; + } + if (itDies + && !zEvent.isDiesEvent()) { + return false; + } + List attackers = (List) game.getState().getValue(this.getSourceId() + "Attackers"); + return attackers != null + && attackers.contains(zEvent.getTargetId()); + } + case REMOVED_FROM_COMBAT: + // a card removed from combat is no longer an attacker or blocker so remove it from the list + if (game.isSimulation()) { // a simulated game will always choose to apply any triggered effect IE: Gustcloak Savior + return false; + } + List attackersList = (List) game.getState().getValue(this.getSourceId() + "Attackers"); + if (attackersList != null + && attackersList.contains(event.getTargetId())) { + attackersList.remove(event.getTargetId()); + game.getState().setValue(this.getSourceId() + "Attackers", attackersList); + } + + default: + return false; + } + } + + @Override + public String getTriggerPhrase() { + if (itDies) { + return "Whenever " + filterPermanent.getMessage() + " dies, "; + } + return "Whenever " + filterPermanent.getMessage() + " is put into " + (onlyToControllerGraveyard ? "your" : "a") + + " graveyard from the battlefield, "; + } + +} diff --git a/Mage/src/main/java/mage/game/combat/Combat.java b/Mage/src/main/java/mage/game/combat/Combat.java index d29ef524ce5..1fbbba6ad2f 100644 --- a/Mage/src/main/java/mage/game/combat/Combat.java +++ b/Mage/src/main/java/mage/game/combat/Combat.java @@ -354,8 +354,8 @@ public class Combat implements Serializable, Copyable { if (game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARING_ATTACKERS, attackingPlayerId, attackingPlayerId)) || (!canBand && !canBandWithOther) || !player.chooseUse(Outcome.Benefit, - (isBanded ? "Band " + attacker.getLogName() - + " with another " : "Form a band with " + attacker.getLogName() + " and an ") + (isBanded ? "Band " + attacker.getLogName() + + " with another " : "Form a band with " + attacker.getLogName() + " and an ") + "attacking creature?", null, game)) { break; } @@ -573,7 +573,7 @@ public class Combat implements Serializable, Copyable { * Handle the blocker selection process * * @param blockController player that controls how to block, if null the - * defender is the controller + * defender is the controller * @param game */ public void selectBlockers(Player blockController, Ability source, Game game) { @@ -1390,7 +1390,7 @@ public class Combat implements Serializable, Copyable { * @param playerId * @param game * @param solveBanding check whether also add creatures banded with - * attackerId + * attackerId */ public void addBlockingGroup(UUID blockerId, UUID attackerId, UUID playerId, Game game, boolean solveBanding) { Permanent blocker = game.getPermanent(blockerId); @@ -1463,6 +1463,7 @@ public class Combat implements Serializable, Copyable { creature.clearBandedCards(); blockingGroups.remove(creatureId); if (result && withInfo) { + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.REMOVED_FROM_COMBAT, creatureId, null, null)); game.informPlayers(creature.getLogName() + " removed from combat"); } } diff --git a/Mage/src/main/java/mage/game/events/GameEvent.java b/Mage/src/main/java/mage/game/events/GameEvent.java index 988fa97ae60..82a5db6b452 100644 --- a/Mage/src/main/java/mage/game/events/GameEvent.java +++ b/Mage/src/main/java/mage/game/events/GameEvent.java @@ -457,6 +457,7 @@ public class GameEvent implements Serializable { ROOM_ENTERED, VENTURE, VENTURED, DUNGEON_COMPLETED, + REMOVED_FROM_COMBAT, // targetId id of permanent removed from combat //custom events CUSTOM_EVENT }