From 9dce38a0a92a1724071421e6bb147ce749b9ae84 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 28 Oct 2013 23:50:08 +0100 Subject: [PATCH] Added and changed some framework classes. --- .../betrayersofkamigawa/FaithfulSquire.java | 4 +- .../championsofkamigawa/KashiTribeReaver.java | 4 +- .../KashiTribeWarriors.java | 4 +- .../championsofkamigawa/MatsuTribeDecoy.java | 4 +- .../championsofkamigawa/OrochiRanger.java | 4 +- .../src/mage/sets/legions/ToxinSliver.java | 4 +- .../src/mage/sets/ravnika/StinkweedImp.java | 4 +- .../saviorsofkamigawa/KashiTribeElite.java | 4 +- .../MatsuTribeBirdstalker.java | 4 +- .../mage/abilities/TriggeredAbilityImpl.java | 26 ++-- ...geToACreatureAttachedTriggeredAbility.java | 100 ++++++++++++++ ...ealsDamageToACreatureTriggeredAbility.java | 88 +++++++++++++ ...mageToAPlayerAttachedTriggeredAbility.java | 2 +- .../ConditionalReplacementEffect.java | 122 ++++++++++++++++++ .../PreventAllDamageAttachedEffect.java | 104 +++++++++++++++ 15 files changed, 450 insertions(+), 28 deletions(-) create mode 100644 Mage/src/mage/abilities/common/DealsDamageToACreatureAttachedTriggeredAbility.java create mode 100644 Mage/src/mage/abilities/common/DealsDamageToACreatureTriggeredAbility.java create mode 100644 Mage/src/mage/abilities/decorator/ConditionalReplacementEffect.java create mode 100644 Mage/src/mage/abilities/effects/common/PreventAllDamageAttachedEffect.java diff --git a/Mage.Sets/src/mage/sets/betrayersofkamigawa/FaithfulSquire.java b/Mage.Sets/src/mage/sets/betrayersofkamigawa/FaithfulSquire.java index c47af460cf..cff63a9516 100644 --- a/Mage.Sets/src/mage/sets/betrayersofkamigawa/FaithfulSquire.java +++ b/Mage.Sets/src/mage/sets/betrayersofkamigawa/FaithfulSquire.java @@ -82,7 +82,7 @@ public class FaithfulSquire extends CardImpl { this.addAbility(new ConditionalTriggeredAbility( new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new FlipSourceEffect()), new HasCounterCondition(CounterType.KI, 2, Integer.MAX_VALUE), - "At the beginning of the end step, if there are two or more ki counters on Faithful Squire, you may flip it.", true)); + "At the beginning of the end step, if there are two or more ki counters on {this}, you may flip it.", true)); Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinousEffect(new CopyTokenEffect(new KaisoMemoryOfLoyalty()), FlippedCondition.getInstance(), "")); ability.setRuleVisible(false); @@ -118,7 +118,7 @@ class KaisoMemoryOfLoyalty extends Token { Zone.BATTLEFIELD, new PreventDamageTargetEffect(Duration.EndOfTurn, Integer.MAX_VALUE), new RemoveCountersSourceCost(CounterType.KI.createInstance())); - ability.addTarget(new TargetCreaturePermanent()); + ability.addTarget(new TargetCreaturePermanent(true)); this.addAbility(ability); } } diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/KashiTribeReaver.java b/Mage.Sets/src/mage/sets/championsofkamigawa/KashiTribeReaver.java index 122bc7bda7..a3d36eb1c0 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/KashiTribeReaver.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/KashiTribeReaver.java @@ -33,7 +33,7 @@ import mage.constants.Rarity; import mage.constants.Zone; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.DealsCombatDamageToACreatureTriggeredAbility; +import mage.abilities.common.DealsDamageToACreatureTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.RegenerateSourceEffect; @@ -59,7 +59,7 @@ public class KashiTribeReaver extends CardImpl { // Whenever Kashi-Tribe Reaver deals combat damage to a creature, tap that creature and it doesn't untap during its controller's next untap step. Ability ability; - ability = new DealsCombatDamageToACreatureTriggeredAbility(new TapTargetEffect("that creature"), false, true); + ability = new DealsDamageToACreatureTriggeredAbility(new TapTargetEffect("that creature"), true, false, true); ability.addEffect(new SkipNextUntapTargetEffect("and it")); this.addAbility(ability); // {1}{G}: Regenerate Kashi-Tribe Reaver. diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/KashiTribeWarriors.java b/Mage.Sets/src/mage/sets/championsofkamigawa/KashiTribeWarriors.java index dbd47ac7aa..71d3a05219 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/KashiTribeWarriors.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/KashiTribeWarriors.java @@ -33,7 +33,7 @@ import mage.constants.CardType; import mage.constants.Rarity; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.DealsCombatDamageToACreatureTriggeredAbility; +import mage.abilities.common.DealsDamageToACreatureTriggeredAbility; import mage.abilities.effects.common.SkipNextUntapTargetEffect; import mage.abilities.effects.common.TapTargetEffect; import mage.cards.CardImpl; @@ -56,7 +56,7 @@ public class KashiTribeWarriors extends CardImpl { // Whenever Kashi-Tribe Reaver deals combat damage to a creature, tap that creature and it doesn't untap during its controller's next untap step. Ability ability; - ability = new DealsCombatDamageToACreatureTriggeredAbility(new TapTargetEffect("that creature"), false, true); + ability = new DealsDamageToACreatureTriggeredAbility(new TapTargetEffect("that creature"), true, false, true); ability.addEffect(new SkipNextUntapTargetEffect("and it")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/MatsuTribeDecoy.java b/Mage.Sets/src/mage/sets/championsofkamigawa/MatsuTribeDecoy.java index 5ae4b995ef..5ab1e643be 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/MatsuTribeDecoy.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/MatsuTribeDecoy.java @@ -33,7 +33,7 @@ import mage.constants.Rarity; import mage.constants.Zone; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.DealsCombatDamageToACreatureTriggeredAbility; +import mage.abilities.common.DealsDamageToACreatureTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.combat.MustBeBlockedByTargetSourceEffect; @@ -64,7 +64,7 @@ public class MatsuTribeDecoy extends CardImpl { this.addAbility(ability); // Whenever Kashi-Tribe Reaver deals combat damage to a creature, tap that creature and it doesn't untap during its controller's next untap step. Ability ability2; - ability2 = new DealsCombatDamageToACreatureTriggeredAbility(new TapTargetEffect("that creature"), false, true); + ability2 = new DealsDamageToACreatureTriggeredAbility(new TapTargetEffect("that creature"), true, false, true); ability2.addEffect(new SkipNextUntapTargetEffect("and it")); this.addAbility(ability2); } diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/OrochiRanger.java b/Mage.Sets/src/mage/sets/championsofkamigawa/OrochiRanger.java index 6c4887e367..0cfa5e2a84 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/OrochiRanger.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/OrochiRanger.java @@ -33,7 +33,7 @@ import mage.constants.CardType; import mage.constants.Rarity; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.DealsCombatDamageToACreatureTriggeredAbility; +import mage.abilities.common.DealsDamageToACreatureTriggeredAbility; import mage.abilities.effects.common.SkipNextUntapTargetEffect; import mage.abilities.effects.common.TapTargetEffect; import mage.cards.CardImpl; @@ -56,7 +56,7 @@ public class OrochiRanger extends CardImpl { // Whenever Orochi Ranger deals combat damage to a creature, tap that creature and it doesn't untap during its controller's next untap step. Ability ability; - ability = new DealsCombatDamageToACreatureTriggeredAbility(new TapTargetEffect("that creature"), false, true); + ability = new DealsDamageToACreatureTriggeredAbility(new TapTargetEffect("that creature"), true, false, true); ability.addEffect(new SkipNextUntapTargetEffect("and it")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/legions/ToxinSliver.java b/Mage.Sets/src/mage/sets/legions/ToxinSliver.java index ae7dd75cc6..f4632640c6 100644 --- a/Mage.Sets/src/mage/sets/legions/ToxinSliver.java +++ b/Mage.Sets/src/mage/sets/legions/ToxinSliver.java @@ -30,7 +30,7 @@ package mage.sets.legions; import java.util.UUID; import mage.MageInt; import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.common.DealsCombatDamageToACreatureTriggeredAbility; +import mage.abilities.common.DealsDamageToACreatureTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; @@ -57,7 +57,7 @@ public class ToxinSliver extends CardImpl { this.toughness = new MageInt(3); // Whenever a Sliver deals combat damage to a creature, destroy that creature. It can't be regenerated. - this.addAbility(new DealsCombatDamageToACreatureTriggeredAbility(new DestroyTargetEffect(false), false, true)); + this.addAbility(new DealsDamageToACreatureTriggeredAbility(new DestroyTargetEffect(false), true, false, true)); } diff --git a/Mage.Sets/src/mage/sets/ravnika/StinkweedImp.java b/Mage.Sets/src/mage/sets/ravnika/StinkweedImp.java index 9af6c1155b..495d1f58c5 100644 --- a/Mage.Sets/src/mage/sets/ravnika/StinkweedImp.java +++ b/Mage.Sets/src/mage/sets/ravnika/StinkweedImp.java @@ -31,7 +31,7 @@ import java.util.UUID; import mage.constants.CardType; import mage.constants.Rarity; import mage.MageInt; -import mage.abilities.common.DealsCombatDamageToACreatureTriggeredAbility; +import mage.abilities.common.DealsDamageToACreatureTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.DredgeAbility; import mage.abilities.keyword.FlyingAbility; @@ -55,7 +55,7 @@ public class StinkweedImp extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); // Whenever Stinkweed Imp deals combat damage to a creature, destroy that creature. - this.addAbility(new DealsCombatDamageToACreatureTriggeredAbility(new DestroyTargetEffect(), false, true)); + this.addAbility(new DealsDamageToACreatureTriggeredAbility(new DestroyTargetEffect(), true, false, true)); // Dredge 5 this.addAbility(new DredgeAbility(5)); } diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/KashiTribeElite.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/KashiTribeElite.java index de52029402..1cce601c76 100644 --- a/Mage.Sets/src/mage/sets/saviorsofkamigawa/KashiTribeElite.java +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/KashiTribeElite.java @@ -33,7 +33,7 @@ import mage.constants.CardType; import mage.constants.Rarity; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.DealsCombatDamageToACreatureTriggeredAbility; +import mage.abilities.common.DealsDamageToACreatureTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.SkipNextUntapTargetEffect; import mage.abilities.effects.common.TapTargetEffect; @@ -74,7 +74,7 @@ public class KashiTribeElite extends CardImpl { // Whenever Kashi-Tribe Elite deals combat damage to a creature, tap that creature and it doesn't untap during its controller's next untap step. Ability ability; - ability = new DealsCombatDamageToACreatureTriggeredAbility(new TapTargetEffect("that creature"), false, true); + ability = new DealsDamageToACreatureTriggeredAbility(new TapTargetEffect("that creature"), true, false, true); ability.addEffect(new SkipNextUntapTargetEffect("and it")); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/MatsuTribeBirdstalker.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/MatsuTribeBirdstalker.java index d040a0e30c..e930fc52a1 100644 --- a/Mage.Sets/src/mage/sets/saviorsofkamigawa/MatsuTribeBirdstalker.java +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/MatsuTribeBirdstalker.java @@ -33,7 +33,7 @@ import mage.constants.CardType; import mage.constants.Rarity; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.DealsCombatDamageToACreatureTriggeredAbility; +import mage.abilities.common.DealsDamageToACreatureTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.SkipNextUntapTargetEffect; @@ -62,7 +62,7 @@ public class MatsuTribeBirdstalker extends CardImpl { // Whenever Kashi-Tribe Elite deals combat damage to a creature, tap that creature and it doesn't untap during its controller's next untap step. Ability ability; - ability = new DealsCombatDamageToACreatureTriggeredAbility(new TapTargetEffect("that creature"), false, true); + ability = new DealsDamageToACreatureTriggeredAbility(new TapTargetEffect("that creature"), true, false, true); ability.addEffect(new SkipNextUntapTargetEffect("and it")); this.addAbility(ability); diff --git a/Mage/src/mage/abilities/TriggeredAbilityImpl.java b/Mage/src/mage/abilities/TriggeredAbilityImpl.java index e8fa2dcd65..2a1776533e 100644 --- a/Mage/src/mage/abilities/TriggeredAbilityImpl.java +++ b/Mage/src/mage/abilities/TriggeredAbilityImpl.java @@ -111,16 +111,24 @@ public abstract class TriggeredAbilityImpl> ex StringBuilder sb = new StringBuilder(); if (!superRule.isEmpty()) { String ruleLow = superRule.toLowerCase(); - if (optional && !ruleLow.startsWith("you ")) { - if (this.getTargets().isEmpty() - || ruleLow.startsWith("exile") - || ruleLow.startsWith("destroy") - || ruleLow.startsWith("return") - || ruleLow.startsWith("tap") - || ruleLow.startsWith("untap")) { - sb.append("you may "); + if (optional) { + if (ruleLow.startsWith("you ")) { + if (!ruleLow.startsWith("you may")) { + StringBuilder newRule = new StringBuilder(superRule); + newRule.insert(4, "may "); + superRule = newRule.toString(); + } } else { - sb.append("you may have "); + if (this.getTargets().isEmpty() + || ruleLow.startsWith("exile") + || ruleLow.startsWith("destroy") + || ruleLow.startsWith("return") + || ruleLow.startsWith("tap") + || ruleLow.startsWith("untap")) { + sb.append("you may "); + } else { + sb.append("you may have "); + } } } diff --git a/Mage/src/mage/abilities/common/DealsDamageToACreatureAttachedTriggeredAbility.java b/Mage/src/mage/abilities/common/DealsDamageToACreatureAttachedTriggeredAbility.java new file mode 100644 index 0000000000..3776c13eac --- /dev/null +++ b/Mage/src/mage/abilities/common/DealsDamageToACreatureAttachedTriggeredAbility.java @@ -0,0 +1,100 @@ +/* + * 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.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.DamagedCreatureEvent; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.permanent.Permanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author LevelX + */ +public class DealsDamageToACreatureAttachedTriggeredAbility extends TriggeredAbilityImpl { + + private boolean combatOnly; + private boolean setTargetPointer; + private String attachedDescription; + + public DealsDamageToACreatureAttachedTriggeredAbility(Effect effect, boolean combatOnly, String attachedDescription, boolean optional, boolean setTargetPointer) { + super(Zone.BATTLEFIELD, effect, optional); + this.setTargetPointer = setTargetPointer; + this.attachedDescription = attachedDescription; + } + + public DealsDamageToACreatureAttachedTriggeredAbility(final DealsDamageToACreatureAttachedTriggeredAbility ability) { + super(ability); + this.setTargetPointer = ability.setTargetPointer; + this.combatOnly = ability.combatOnly; + this.attachedDescription = ability.attachedDescription; + } + + @Override + public DealsDamageToACreatureAttachedTriggeredAbility copy() { + return new DealsDamageToACreatureAttachedTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == EventType.DAMAGED_CREATURE + && (!combatOnly || ((DamagedCreatureEvent) event).isCombatDamage())) { + Permanent attachment = game.getPermanent(this.getSourceId()); + if (attachment != null + && attachment.getAttachedTo() != null + && event.getSourceId().equals(attachment.getAttachedTo()) + ) { + if (setTargetPointer) { + for (Effect effect : this.getEffects()) { + effect.setTargetPointer(new FixedTarget(event.getTargetId())); + effect.setValue("damage", event.getAmount()); + } + } + return true; + } + + } + return false; + } + + @Override + public String getRule() { + return new StringBuilder("Whenever ").append(attachedDescription) + .append(" deals ") + .append(combatOnly ? "combat ":"") + .append("damage to a creature, ") + .append(super.getRule()).toString(); + } + +} diff --git a/Mage/src/mage/abilities/common/DealsDamageToACreatureTriggeredAbility.java b/Mage/src/mage/abilities/common/DealsDamageToACreatureTriggeredAbility.java new file mode 100644 index 0000000000..19793fc712 --- /dev/null +++ b/Mage/src/mage/abilities/common/DealsDamageToACreatureTriggeredAbility.java @@ -0,0 +1,88 @@ +/* + * 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.DamagedCreatureEvent; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author LevelX + */ +public class DealsDamageToACreatureTriggeredAbility extends TriggeredAbilityImpl { + + private boolean combatOnly; + private boolean setTargetPointer; + + public DealsDamageToACreatureTriggeredAbility(Effect effect, boolean combatOnly, boolean optional, boolean setTargetPointer) { + super(Zone.BATTLEFIELD, effect, optional); + this.setTargetPointer = setTargetPointer; + } + + public DealsDamageToACreatureTriggeredAbility(final DealsDamageToACreatureTriggeredAbility ability) { + super(ability); + this.setTargetPointer = ability.setTargetPointer; + this.combatOnly = ability.combatOnly; + } + + @Override + public DealsDamageToACreatureTriggeredAbility copy() { + return new DealsDamageToACreatureTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == EventType.DAMAGED_CREATURE) { + if (event.getSourceId().equals(this.sourceId) + && (!combatOnly || ((DamagedCreatureEvent) event).isCombatDamage())) { + if (setTargetPointer) { + for (Effect effect : this.getEffects()) { + effect.setTargetPointer(new FixedTarget(event.getTargetId())); + effect.setValue("damage", event.getAmount()); + } + } + return true; + } + + } + return false; + } + + @Override + public String getRule() { + return new StringBuilder("Whenever {this} deals ").append(combatOnly ? "combat ":"").append("damage to a creature, ").append(super.getRule()).toString(); + } + +} diff --git a/Mage/src/mage/abilities/common/DealsDamageToAPlayerAttachedTriggeredAbility.java b/Mage/src/mage/abilities/common/DealsDamageToAPlayerAttachedTriggeredAbility.java index 12ec86cd5a..3a682c492e 100644 --- a/Mage/src/mage/abilities/common/DealsDamageToAPlayerAttachedTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/DealsDamageToAPlayerAttachedTriggeredAbility.java @@ -64,7 +64,7 @@ public class DealsDamageToAPlayerAttachedTriggeredAbility extends TriggeredAbili @Override public String getRule() { StringBuilder sb = new StringBuilder("Whenever ").append(attachedDescription); - sb.append(" creature deals"); + sb.append(" deals"); if (!onlyCombat) { sb.append(" combat"); } diff --git a/Mage/src/mage/abilities/decorator/ConditionalReplacementEffect.java b/Mage/src/mage/abilities/decorator/ConditionalReplacementEffect.java new file mode 100644 index 0000000000..b1f3a10ad0 --- /dev/null +++ b/Mage/src/mage/abilities/decorator/ConditionalReplacementEffect.java @@ -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.abilities.decorator; + +import mage.abilities.Ability; +import mage.abilities.condition.Condition; +import mage.abilities.condition.FixedCondition; +import mage.abilities.effects.ReplacementEffect; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.constants.Duration; +import mage.game.Game; +import mage.game.events.GameEvent; + +/** + * + * @author LevelX2 + */ +public class ConditionalReplacementEffect extends ReplacementEffectImpl { + + protected ReplacementEffect effect; + protected ReplacementEffect otherwiseEffect; + protected Condition condition; + protected boolean lockedInCondition; + protected boolean conditionState; + + public ConditionalReplacementEffect(ReplacementEffect effect, Condition condition, boolean lockedInCondition) { + this(effect, condition, null, lockedInCondition); + } + + public ConditionalReplacementEffect(ReplacementEffect effect, Condition condition, ReplacementEffect otherwiseEffect, boolean lockedInCondition) { + super(effect.getDuration(), effect.getOutcome()); + this.effect = effect; + this.condition = condition; + this.otherwiseEffect = otherwiseEffect; + this.lockedInCondition = lockedInCondition; + } + + public ConditionalReplacementEffect(final ConditionalReplacementEffect effect) { + super(effect); + this.effect = (ReplacementEffect) effect.effect.copy(); + if (effect.otherwiseEffect != null) { + this.otherwiseEffect = (ReplacementEffect) effect.otherwiseEffect.copy(); + } + this.condition = effect.condition; + this.lockedInCondition = effect.lockedInCondition; + this.conditionState = effect.conditionState; + } + + @Override + public boolean isDiscarded() { + return effect.isDiscarded() || (otherwiseEffect != null && otherwiseEffect.isDiscarded()); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + if (conditionState) { + effect.setTargetPointer(this.targetPointer); + return effect.replaceEvent(event, source, game); + } else if (otherwiseEffect != null) { + otherwiseEffect.setTargetPointer(this.targetPointer); + return otherwiseEffect.replaceEvent(event, source, game); + } + if (!conditionState && effect.getDuration() == Duration.OneUse) { + used = true; + } + if (!conditionState && effect.getDuration() == Duration.Custom) { + this.discard(); + } + return true; + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (lockedInCondition && !(condition instanceof FixedCondition)) { + condition = new FixedCondition(condition.apply(game, source)); + } + conditionState = condition.apply(game, source); + if (conditionState) { + effect.setTargetPointer(this.targetPointer); + return effect.applies(event, source, game); + } else if (otherwiseEffect != null) { + otherwiseEffect.setTargetPointer(this.targetPointer); + return otherwiseEffect.applies(event, source, game); + } + return false; + } + + @Override + public ConditionalReplacementEffect copy() { + return new ConditionalReplacementEffect(this); + } +} diff --git a/Mage/src/mage/abilities/effects/common/PreventAllDamageAttachedEffect.java b/Mage/src/mage/abilities/effects/common/PreventAllDamageAttachedEffect.java new file mode 100644 index 0000000000..b8e2075d3a --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/PreventAllDamageAttachedEffect.java @@ -0,0 +1,104 @@ +/* + * 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.effects.common; + +import mage.abilities.Ability; +import mage.abilities.effects.PreventionEffectImpl; +import mage.constants.Duration; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX2 + */ +public class PreventAllDamageAttachedEffect extends PreventionEffectImpl { + + private String attachedDescription; + private boolean combatOnly; + + public PreventAllDamageAttachedEffect(Duration duration, String attachedDescription, boolean combatOnly) { + super(duration); + this.attachedDescription = attachedDescription; + this.combatOnly = combatOnly; + staticText = setText(); + } + + public PreventAllDamageAttachedEffect(final PreventAllDamageAttachedEffect effect) { + super(effect); + this.attachedDescription = effect.attachedDescription; + this.combatOnly = effect.combatOnly; + } + + @Override + public PreventAllDamageAttachedEffect copy() { + return new PreventAllDamageAttachedEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE, source.getFirstTarget(), source.getSourceId(), source.getControllerId(), event.getAmount(), false); + if (!game.replaceEvent(preventEvent)) { + int damage = event.getAmount(); + event.setAmount(0); + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.PREVENTED_DAMAGE, source.getFirstTarget(), source.getSourceId(), source.getControllerId(), damage)); + } + return false; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (super.applies(event, source, game)) { + Permanent attachment = game.getPermanent(source.getSourceId()); + if (attachment != null + && attachment.getAttachedTo() != null) { + if (event.getTargetId().equals(attachment.getAttachedTo())) { + return true; + } + } + } + return false; + } + + private String setText() { + StringBuilder sb = new StringBuilder("Prevent all "); + if (combatOnly) { + sb.append("combat "); + } + sb.append("damage that would be dealt to "); + sb.append(attachedDescription); + return sb.toString(); + } +}